blob: 58aab087e1782fbb01032afd587f89ef8c8cdefc [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 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 * Intent broadcast that we have tried to start, but are
546 * waiting for its application's process to be created. We only
547 * need one (instead of a list) because we always process broadcasts
548 * one at a time, so no others can be started while waiting for this
549 * one.
550 */
551 BroadcastRecord mPendingBroadcast = null;
552
553 /**
554 * Keeps track of all IIntentReceivers that have been registered for
555 * broadcasts. Hash keys are the receiver IBinder, hash value is
556 * a ReceiverList.
557 */
558 final HashMap mRegisteredReceivers = new HashMap();
559
560 /**
561 * Resolver for broadcast intents to registered receivers.
562 * Holds BroadcastFilter (subclass of IntentFilter).
563 */
564 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
565 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
566 @Override
567 protected boolean allowFilterResult(
568 BroadcastFilter filter, List<BroadcastFilter> dest) {
569 IBinder target = filter.receiverList.receiver.asBinder();
570 for (int i=dest.size()-1; i>=0; i--) {
571 if (dest.get(i).receiverList.receiver.asBinder() == target) {
572 return false;
573 }
574 }
575 return true;
576 }
577 };
578
579 /**
580 * State of all active sticky broadcasts. Keys are the action of the
581 * sticky Intent, values are an ArrayList of all broadcasted intents with
582 * that action (which should usually be one).
583 */
584 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
585 new HashMap<String, ArrayList<Intent>>();
586
587 /**
588 * All currently running services.
589 */
590 final HashMap<ComponentName, ServiceRecord> mServices =
591 new HashMap<ComponentName, ServiceRecord>();
592
593 /**
594 * All currently running services indexed by the Intent used to start them.
595 */
596 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
597 new HashMap<Intent.FilterComparison, ServiceRecord>();
598
599 /**
600 * All currently bound service connections. Keys are the IBinder of
601 * the client's IServiceConnection.
602 */
603 final HashMap<IBinder, ConnectionRecord> mServiceConnections
604 = new HashMap<IBinder, ConnectionRecord>();
605
606 /**
607 * List of services that we have been asked to start,
608 * but haven't yet been able to. It is used to hold start requests
609 * while waiting for their corresponding application thread to get
610 * going.
611 */
612 final ArrayList<ServiceRecord> mPendingServices
613 = new ArrayList<ServiceRecord>();
614
615 /**
616 * List of services that are scheduled to restart following a crash.
617 */
618 final ArrayList<ServiceRecord> mRestartingServices
619 = new ArrayList<ServiceRecord>();
620
621 /**
622 * List of services that are in the process of being stopped.
623 */
624 final ArrayList<ServiceRecord> mStoppingServices
625 = new ArrayList<ServiceRecord>();
626
627 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700628 * Backup/restore process management
629 */
630 String mBackupAppName = null;
631 BackupRecord mBackupTarget = null;
632
633 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 * List of PendingThumbnailsRecord objects of clients who are still
635 * waiting to receive all of the thumbnails for a task.
636 */
637 final ArrayList mPendingThumbnails = new ArrayList();
638
639 /**
640 * List of HistoryRecord objects that have been finished and must
641 * still report back to a pending thumbnail receiver.
642 */
643 final ArrayList mCancelledThumbnails = new ArrayList();
644
645 /**
646 * All of the currently running global content providers. Keys are a
647 * string containing the provider name and values are a
648 * ContentProviderRecord object containing the data about it. Note
649 * that a single provider may be published under multiple names, so
650 * there may be multiple entries here for a single one in mProvidersByClass.
651 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700652 final HashMap<String, ContentProviderRecord> mProvidersByName
653 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654
655 /**
656 * All of the currently running global content providers. Keys are a
657 * string containing the provider's implementation class and values are a
658 * ContentProviderRecord object containing the data about it.
659 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700660 final HashMap<String, ContentProviderRecord> mProvidersByClass
661 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662
663 /**
664 * List of content providers who have clients waiting for them. The
665 * application is currently being launched and the provider will be
666 * removed from this list once it is published.
667 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700668 final ArrayList<ContentProviderRecord> mLaunchingProviders
669 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670
671 /**
672 * Global set of specific Uri permissions that have been granted.
673 */
674 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
675 = new SparseArray<HashMap<Uri, UriPermission>>();
676
677 /**
678 * Thread-local storage used to carry caller permissions over through
679 * indirect content-provider access.
680 * @see #ActivityManagerService.openContentUri()
681 */
682 private class Identity {
683 public int pid;
684 public int uid;
685
686 Identity(int _pid, int _uid) {
687 pid = _pid;
688 uid = _uid;
689 }
690 }
691 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
692
693 /**
694 * All information we have collected about the runtime performance of
695 * any user id that can impact battery performance.
696 */
697 final BatteryStatsService mBatteryStatsService;
698
699 /**
700 * information about component usage
701 */
702 final UsageStatsService mUsageStatsService;
703
704 /**
705 * Current configuration information. HistoryRecord objects are given
706 * a reference to this object to indicate which configuration they are
707 * currently running in, so this object must be kept immutable.
708 */
709 Configuration mConfiguration = new Configuration();
710
711 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800712 * Current sequencing integer of the configuration, for skipping old
713 * configurations.
714 */
715 int mConfigurationSeq = 0;
716
717 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700718 * Hardware-reported OpenGLES version.
719 */
720 final int GL_ES_VERSION;
721
722 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 * List of initialization arguments to pass to all processes when binding applications to them.
724 * For example, references to the commonly used services.
725 */
726 HashMap<String, IBinder> mAppBindArgs;
727
728 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700729 * Temporary to avoid allocations. Protected by main lock.
730 */
731 final StringBuilder mStringBuilder = new StringBuilder(256);
732
733 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 * Used to control how we initialize the service.
735 */
736 boolean mStartRunning = false;
737 ComponentName mTopComponent;
738 String mTopAction;
739 String mTopData;
740 boolean mSystemReady = false;
741 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700742 boolean mWaitingUpdate = false;
743 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744
745 Context mContext;
746
747 int mFactoryTest;
748
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700749 boolean mCheckedForSetup;
750
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800751 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700752 * The time at which we will allow normal application switches again,
753 * after a call to {@link #stopAppSwitches()}.
754 */
755 long mAppSwitchesAllowedTime;
756
757 /**
758 * This is set to true after the first switch after mAppSwitchesAllowedTime
759 * is set; any switches after that will clear the time.
760 */
761 boolean mDidAppSwitch;
762
763 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764 * Set while we are wanting to sleep, to prevent any
765 * activities from being started/resumed.
766 */
767 boolean mSleeping = false;
768
769 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700770 * Set if we are shutting down the system, similar to sleeping.
771 */
772 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773
774 /**
775 * Task identifier that activities are currently being started
776 * in. Incremented each time a new task is created.
777 * todo: Replace this with a TokenSpace class that generates non-repeating
778 * integers that won't wrap.
779 */
780 int mCurTask = 1;
781
782 /**
783 * Current sequence id for oom_adj computation traversal.
784 */
785 int mAdjSeq = 0;
786
787 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700788 * Current sequence id for process LRU updating.
789 */
790 int mLruSeq = 0;
791
792 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
794 * is set, indicating the user wants processes started in such a way
795 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
796 * running in each process (thus no pre-initialized process, etc).
797 */
798 boolean mSimpleProcessManagement = false;
799
800 /**
801 * System monitoring: number of processes that died since the last
802 * N procs were started.
803 */
804 int[] mProcDeaths = new int[20];
805
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700806 /**
807 * This is set if we had to do a delayed dexopt of an app before launching
808 * it, to increasing the ANR timeouts in that case.
809 */
810 boolean mDidDexOpt;
811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 String mDebugApp = null;
813 boolean mWaitForDebugger = false;
814 boolean mDebugTransient = false;
815 String mOrigDebugApp = null;
816 boolean mOrigWaitForDebugger = false;
817 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700818 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700820 final RemoteCallbackList<IActivityWatcher> mWatchers
821 = new RemoteCallbackList<IActivityWatcher>();
822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800823 /**
824 * Callback of last caller to {@link #requestPss}.
825 */
826 Runnable mRequestPssCallback;
827
828 /**
829 * Remaining processes for which we are waiting results from the last
830 * call to {@link #requestPss}.
831 */
832 final ArrayList<ProcessRecord> mRequestPssList
833 = new ArrayList<ProcessRecord>();
834
835 /**
836 * Runtime statistics collection thread. This object's lock is used to
837 * protect all related state.
838 */
839 final Thread mProcessStatsThread;
840
841 /**
842 * Used to collect process stats when showing not responding dialog.
843 * Protected by mProcessStatsThread.
844 */
845 final ProcessStats mProcessStats = new ProcessStats(
846 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700847 final AtomicLong mLastCpuTime = new AtomicLong(0);
848 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 long mLastWriteTime = 0;
851
852 /**
853 * Set to true after the system has finished booting.
854 */
855 boolean mBooted = false;
856
857 int mProcessLimit = 0;
858
859 WindowManagerService mWindowManager;
860
861 static ActivityManagerService mSelf;
862 static ActivityThread mSystemThread;
863
864 private final class AppDeathRecipient implements IBinder.DeathRecipient {
865 final ProcessRecord mApp;
866 final int mPid;
867 final IApplicationThread mAppThread;
868
869 AppDeathRecipient(ProcessRecord app, int pid,
870 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800871 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 TAG, "New death recipient " + this
873 + " for thread " + thread.asBinder());
874 mApp = app;
875 mPid = pid;
876 mAppThread = thread;
877 }
878
879 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800880 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 TAG, "Death received in " + this
882 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 synchronized(ActivityManagerService.this) {
884 appDiedLocked(mApp, mPid, mAppThread);
885 }
886 }
887 }
888
889 static final int SHOW_ERROR_MSG = 1;
890 static final int SHOW_NOT_RESPONDING_MSG = 2;
891 static final int SHOW_FACTORY_ERROR_MSG = 3;
892 static final int UPDATE_CONFIGURATION_MSG = 4;
893 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
894 static final int WAIT_FOR_DEBUGGER_MSG = 6;
895 static final int BROADCAST_INTENT_MSG = 7;
896 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 static final int SERVICE_TIMEOUT_MSG = 12;
898 static final int UPDATE_TIME_ZONE = 13;
899 static final int SHOW_UID_ERROR_MSG = 14;
900 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700902 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700903 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800904 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700905 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
906 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700907 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908
909 AlertDialog mUidAlert;
910
911 final Handler mHandler = new Handler() {
912 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800913 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 //}
915
916 public void handleMessage(Message msg) {
917 switch (msg.what) {
918 case SHOW_ERROR_MSG: {
919 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 synchronized (ActivityManagerService.this) {
921 ProcessRecord proc = (ProcessRecord)data.get("app");
922 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800923 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 return;
925 }
926 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700927 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800928 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 d.show();
930 proc.crashDialog = d;
931 } else {
932 // The device is asleep, so just pretend that the user
933 // saw a crash dialog and hit "force quit".
934 res.set(0);
935 }
936 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700937
938 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 } break;
940 case SHOW_NOT_RESPONDING_MSG: {
941 synchronized (ActivityManagerService.this) {
942 HashMap data = (HashMap) msg.obj;
943 ProcessRecord proc = (ProcessRecord)data.get("app");
944 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800945 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 return;
947 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800948
949 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
950 null, null, 0, null, null, null,
951 false, false, MY_PID, Process.SYSTEM_UID);
952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700954 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 d.show();
956 proc.anrDialog = d;
957 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700958
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700959 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700961 case SHOW_STRICT_MODE_VIOLATION_MSG: {
962 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
963 synchronized (ActivityManagerService.this) {
964 ProcessRecord proc = (ProcessRecord) data.get("app");
965 if (proc == null) {
966 Slog.e(TAG, "App not found when showing strict mode dialog.");
967 break;
968 }
969 if (proc.crashDialog != null) {
970 Slog.e(TAG, "App already has strict mode dialog: " + proc);
971 return;
972 }
973 AppErrorResult res = (AppErrorResult) data.get("result");
974 if (!mSleeping && !mShuttingDown) {
975 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
976 d.show();
977 proc.crashDialog = d;
978 } else {
979 // The device is asleep, so just pretend that the user
980 // saw a crash dialog and hit "force quit".
981 res.set(0);
982 }
983 }
984 ensureBootCompleted();
985 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 case SHOW_FACTORY_ERROR_MSG: {
987 Dialog d = new FactoryErrorDialog(
988 mContext, msg.getData().getCharSequence("msg"));
989 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700990 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 } break;
992 case UPDATE_CONFIGURATION_MSG: {
993 final ContentResolver resolver = mContext.getContentResolver();
994 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
995 } break;
996 case GC_BACKGROUND_PROCESSES_MSG: {
997 synchronized (ActivityManagerService.this) {
998 performAppGcsIfAppropriateLocked();
999 }
1000 } break;
1001 case WAIT_FOR_DEBUGGER_MSG: {
1002 synchronized (ActivityManagerService.this) {
1003 ProcessRecord app = (ProcessRecord)msg.obj;
1004 if (msg.arg1 != 0) {
1005 if (!app.waitedForDebugger) {
1006 Dialog d = new AppWaitingForDebuggerDialog(
1007 ActivityManagerService.this,
1008 mContext, app);
1009 app.waitDialog = d;
1010 app.waitedForDebugger = true;
1011 d.show();
1012 }
1013 } else {
1014 if (app.waitDialog != null) {
1015 app.waitDialog.dismiss();
1016 app.waitDialog = null;
1017 }
1018 }
1019 }
1020 } break;
1021 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001022 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 TAG, "Received BROADCAST_INTENT_MSG");
1024 processNextBroadcast(true);
1025 } break;
1026 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001027 if (mDidDexOpt) {
1028 mDidDexOpt = false;
1029 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1030 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1031 return;
1032 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001033 // Only process broadcast timeouts if the system is ready. That way
1034 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1035 // to do heavy lifting for system up
1036 if (mSystemReady) {
1037 broadcastTimeout();
1038 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001041 if (mDidDexOpt) {
1042 mDidDexOpt = false;
1043 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1044 nmsg.obj = msg.obj;
1045 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1046 return;
1047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 serviceTimeout((ProcessRecord)msg.obj);
1049 } break;
1050 case UPDATE_TIME_ZONE: {
1051 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001052 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1053 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 if (r.thread != null) {
1055 try {
1056 r.thread.updateTimeZone();
1057 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001058 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059 }
1060 }
1061 }
1062 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001063 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 case SHOW_UID_ERROR_MSG: {
1065 // XXX This is a temporary dialog, no need to localize.
1066 AlertDialog d = new BaseErrorDialog(mContext);
1067 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1068 d.setCancelable(false);
1069 d.setTitle("System UIDs Inconsistent");
1070 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1071 d.setButton("I'm Feeling Lucky",
1072 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1073 mUidAlert = d;
1074 d.show();
1075 } break;
1076 case IM_FEELING_LUCKY_MSG: {
1077 if (mUidAlert != null) {
1078 mUidAlert.dismiss();
1079 mUidAlert = null;
1080 }
1081 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001083 if (mDidDexOpt) {
1084 mDidDexOpt = false;
1085 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1086 nmsg.obj = msg.obj;
1087 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1088 return;
1089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 ProcessRecord app = (ProcessRecord)msg.obj;
1091 synchronized (ActivityManagerService.this) {
1092 processStartTimedOutLocked(app);
1093 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001094 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001095 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1096 synchronized (ActivityManagerService.this) {
1097 doPendingActivityLaunchesLocked(true);
1098 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001099 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001100 case KILL_APPLICATION_MSG: {
1101 synchronized (ActivityManagerService.this) {
1102 int uid = msg.arg1;
1103 boolean restart = (msg.arg2 == 1);
1104 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001105 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001106 }
1107 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001108 case FINALIZE_PENDING_INTENT_MSG: {
1109 ((PendingIntentRecord)msg.obj).completeFinalize();
1110 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001111 case POST_HEAVY_NOTIFICATION_MSG: {
1112 INotificationManager inm = NotificationManager.getService();
1113 if (inm == null) {
1114 return;
1115 }
1116
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001117 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001118 ProcessRecord process = root.app;
1119 if (process == null) {
1120 return;
1121 }
1122
1123 try {
1124 Context context = mContext.createPackageContext(process.info.packageName, 0);
1125 String text = mContext.getString(R.string.heavy_weight_notification,
1126 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1127 Notification notification = new Notification();
1128 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1129 notification.when = 0;
1130 notification.flags = Notification.FLAG_ONGOING_EVENT;
1131 notification.tickerText = text;
1132 notification.defaults = 0; // please be quiet
1133 notification.sound = null;
1134 notification.vibrate = null;
1135 notification.setLatestEventInfo(context, text,
1136 mContext.getText(R.string.heavy_weight_notification_detail),
1137 PendingIntent.getActivity(mContext, 0, root.intent,
1138 PendingIntent.FLAG_CANCEL_CURRENT));
1139
1140 try {
1141 int[] outId = new int[1];
1142 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1143 notification, outId);
1144 } catch (RuntimeException e) {
1145 Slog.w(ActivityManagerService.TAG,
1146 "Error showing notification for heavy-weight app", e);
1147 } catch (RemoteException e) {
1148 }
1149 } catch (NameNotFoundException e) {
1150 Log.w(TAG, "Unable to create context for heavy notification", e);
1151 }
1152 } break;
1153 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1154 INotificationManager inm = NotificationManager.getService();
1155 if (inm == null) {
1156 return;
1157 }
1158 try {
1159 inm.cancelNotification("android",
1160 R.string.heavy_weight_notification);
1161 } catch (RuntimeException e) {
1162 Slog.w(ActivityManagerService.TAG,
1163 "Error canceling notification for service", e);
1164 } catch (RemoteException e) {
1165 }
1166 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 }
1168 }
1169 };
1170
1171 public static void setSystemProcess() {
1172 try {
1173 ActivityManagerService m = mSelf;
1174
1175 ServiceManager.addService("activity", m);
1176 ServiceManager.addService("meminfo", new MemBinder(m));
1177 if (MONITOR_CPU_USAGE) {
1178 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 ServiceManager.addService("permission", new PermissionController(m));
1181
1182 ApplicationInfo info =
1183 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001184 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001185 mSystemThread.installSystemApplicationInfo(info);
1186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 synchronized (mSelf) {
1188 ProcessRecord app = mSelf.newProcessRecordLocked(
1189 mSystemThread.getApplicationThread(), info,
1190 info.processName);
1191 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001192 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001193 app.maxAdj = SYSTEM_ADJ;
1194 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1195 synchronized (mSelf.mPidsSelfLocked) {
1196 mSelf.mPidsSelfLocked.put(app.pid, app);
1197 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001198 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 }
1200 } catch (PackageManager.NameNotFoundException e) {
1201 throw new RuntimeException(
1202 "Unable to find android system package", e);
1203 }
1204 }
1205
1206 public void setWindowManager(WindowManagerService wm) {
1207 mWindowManager = wm;
1208 }
1209
1210 public static final Context main(int factoryTest) {
1211 AThread thr = new AThread();
1212 thr.start();
1213
1214 synchronized (thr) {
1215 while (thr.mService == null) {
1216 try {
1217 thr.wait();
1218 } catch (InterruptedException e) {
1219 }
1220 }
1221 }
1222
1223 ActivityManagerService m = thr.mService;
1224 mSelf = m;
1225 ActivityThread at = ActivityThread.systemMain();
1226 mSystemThread = at;
1227 Context context = at.getSystemContext();
1228 m.mContext = context;
1229 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001230 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231
1232 m.mBatteryStatsService.publish(context);
1233 m.mUsageStatsService.publish(context);
1234
1235 synchronized (thr) {
1236 thr.mReady = true;
1237 thr.notifyAll();
1238 }
1239
1240 m.startRunning(null, null, null, null);
1241
1242 return context;
1243 }
1244
1245 public static ActivityManagerService self() {
1246 return mSelf;
1247 }
1248
1249 static class AThread extends Thread {
1250 ActivityManagerService mService;
1251 boolean mReady = false;
1252
1253 public AThread() {
1254 super("ActivityManager");
1255 }
1256
1257 public void run() {
1258 Looper.prepare();
1259
1260 android.os.Process.setThreadPriority(
1261 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001262 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001263
1264 ActivityManagerService m = new ActivityManagerService();
1265
1266 synchronized (this) {
1267 mService = m;
1268 notifyAll();
1269 }
1270
1271 synchronized (this) {
1272 while (!mReady) {
1273 try {
1274 wait();
1275 } catch (InterruptedException e) {
1276 }
1277 }
1278 }
1279
1280 Looper.loop();
1281 }
1282 }
1283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 static class MemBinder extends Binder {
1285 ActivityManagerService mActivityManagerService;
1286 MemBinder(ActivityManagerService activityManagerService) {
1287 mActivityManagerService = activityManagerService;
1288 }
1289
1290 @Override
1291 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1292 ActivityManagerService service = mActivityManagerService;
1293 ArrayList<ProcessRecord> procs;
1294 synchronized (mActivityManagerService) {
1295 if (args != null && args.length > 0
1296 && args[0].charAt(0) != '-') {
1297 procs = new ArrayList<ProcessRecord>();
1298 int pid = -1;
1299 try {
1300 pid = Integer.parseInt(args[0]);
1301 } catch (NumberFormatException e) {
1302
1303 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001304 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1305 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001306 if (proc.pid == pid) {
1307 procs.add(proc);
1308 } else if (proc.processName.equals(args[0])) {
1309 procs.add(proc);
1310 }
1311 }
1312 if (procs.size() <= 0) {
1313 pw.println("No process found for: " + args[0]);
1314 return;
1315 }
1316 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001317 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001318 }
1319 }
1320 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1321 }
1322 }
1323
1324 static class CpuBinder extends Binder {
1325 ActivityManagerService mActivityManagerService;
1326 CpuBinder(ActivityManagerService activityManagerService) {
1327 mActivityManagerService = activityManagerService;
1328 }
1329
1330 @Override
1331 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1332 synchronized (mActivityManagerService.mProcessStatsThread) {
1333 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1334 }
1335 }
1336 }
1337
1338 private ActivityManagerService() {
1339 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1340 if (v != null && Integer.getInteger(v) != 0) {
1341 mSimpleProcessManagement = true;
1342 }
1343 v = System.getenv("ANDROID_DEBUG_APP");
1344 if (v != null) {
1345 mSimpleProcessManagement = true;
1346 }
1347
Joe Onorato8a9b2202010-02-26 18:56:32 -08001348 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 File dataDir = Environment.getDataDirectory();
1351 File systemDir = new File(dataDir, "system");
1352 systemDir.mkdirs();
1353 mBatteryStatsService = new BatteryStatsService(new File(
1354 systemDir, "batterystats.bin").toString());
1355 mBatteryStatsService.getActiveStatistics().readLocked();
1356 mBatteryStatsService.getActiveStatistics().writeLocked();
1357
1358 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001359 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360
Jack Palevichb90d28c2009-07-22 15:35:24 -07001361 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1362 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1363
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001364 mConfiguration.setToDefaults();
1365 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 mProcessStats.init();
1367
1368 // Add ourself to the Watchdog monitors.
1369 Watchdog.getInstance().addMonitor(this);
1370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001371 mProcessStatsThread = new Thread("ProcessStats") {
1372 public void run() {
1373 while (true) {
1374 try {
1375 try {
1376 synchronized(this) {
1377 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001378 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001380 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 // + ", write delay=" + nextWriteDelay);
1382 if (nextWriteDelay < nextCpuDelay) {
1383 nextCpuDelay = nextWriteDelay;
1384 }
1385 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001386 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387 this.wait(nextCpuDelay);
1388 }
1389 }
1390 } catch (InterruptedException e) {
1391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 updateCpuStatsNow();
1393 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001394 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 }
1396 }
1397 }
1398 };
1399 mProcessStatsThread.start();
1400 }
1401
1402 @Override
1403 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1404 throws RemoteException {
1405 try {
1406 return super.onTransact(code, data, reply, flags);
1407 } catch (RuntimeException e) {
1408 // The activity manager only throws security exceptions, so let's
1409 // log all others.
1410 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001411 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 }
1413 throw e;
1414 }
1415 }
1416
1417 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001418 final long now = SystemClock.uptimeMillis();
1419 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1420 return;
1421 }
1422 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1423 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 mProcessStatsThread.notify();
1425 }
1426 }
1427 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429 void updateCpuStatsNow() {
1430 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001431 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 final long now = SystemClock.uptimeMillis();
1433 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001436 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1437 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 haveNewCpuStats = true;
1439 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001440 //Slog.i(TAG, mProcessStats.printCurrentState());
1441 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 // + mProcessStats.getTotalCpuPercent() + "%");
1443
Joe Onorato8a9b2202010-02-26 18:56:32 -08001444 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 if ("true".equals(SystemProperties.get("events.cpu"))) {
1446 int user = mProcessStats.getLastUserTime();
1447 int system = mProcessStats.getLastSystemTime();
1448 int iowait = mProcessStats.getLastIoWaitTime();
1449 int irq = mProcessStats.getLastIrqTime();
1450 int softIrq = mProcessStats.getLastSoftIrqTime();
1451 int idle = mProcessStats.getLastIdleTime();
1452
1453 int total = user + system + iowait + irq + softIrq + idle;
1454 if (total == 0) total = 1;
1455
Doug Zongker2bec3d42009-12-04 12:52:44 -08001456 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 ((user+system+iowait+irq+softIrq) * 100) / total,
1458 (user * 100) / total,
1459 (system * 100) / total,
1460 (iowait * 100) / total,
1461 (irq * 100) / total,
1462 (softIrq * 100) / total);
1463 }
1464 }
1465
Amith Yamasanie43530a2009-08-21 13:11:37 -07001466 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001467 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001468 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 synchronized(mPidsSelfLocked) {
1470 if (haveNewCpuStats) {
1471 if (mBatteryStatsService.isOnBattery()) {
1472 final int N = mProcessStats.countWorkingStats();
1473 for (int i=0; i<N; i++) {
1474 ProcessStats.Stats st
1475 = mProcessStats.getWorkingStats(i);
1476 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1477 if (pr != null) {
1478 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1479 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001480 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001481 } else {
1482 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001483 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001484 if (ps != null) {
1485 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001486 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 }
1489 }
1490 }
1491 }
1492 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1495 mLastWriteTime = now;
1496 mBatteryStatsService.getActiveStatistics().writeLocked();
1497 }
1498 }
1499 }
1500 }
1501
1502 /**
1503 * Initialize the application bind args. These are passed to each
1504 * process when the bindApplication() IPC is sent to the process. They're
1505 * lazily setup to make sure the services are running when they're asked for.
1506 */
1507 private HashMap<String, IBinder> getCommonServicesLocked() {
1508 if (mAppBindArgs == null) {
1509 mAppBindArgs = new HashMap<String, IBinder>();
1510
1511 // Setup the application init args
1512 mAppBindArgs.put("package", ServiceManager.getService("package"));
1513 mAppBindArgs.put("window", ServiceManager.getService("window"));
1514 mAppBindArgs.put(Context.ALARM_SERVICE,
1515 ServiceManager.getService(Context.ALARM_SERVICE));
1516 }
1517 return mAppBindArgs;
1518 }
1519
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001520 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 if (mFocusedActivity != r) {
1522 mFocusedActivity = r;
1523 mWindowManager.setFocusedApp(r, true);
1524 }
1525 }
1526
Dianne Hackborn906497c2010-05-10 15:57:38 -07001527 private final void updateLruProcessInternalLocked(ProcessRecord app,
1528 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001530 int lrui = mLruProcesses.indexOf(app);
1531 if (lrui >= 0) mLruProcesses.remove(lrui);
1532
1533 int i = mLruProcesses.size()-1;
1534 int skipTop = 0;
1535
Dianne Hackborn906497c2010-05-10 15:57:38 -07001536 app.lruSeq = mLruSeq;
1537
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001538 // compute the new weight for this process.
1539 if (updateActivityTime) {
1540 app.lastActivityTime = SystemClock.uptimeMillis();
1541 }
1542 if (app.activities.size() > 0) {
1543 // If this process has activities, we more strongly want to keep
1544 // it around.
1545 app.lruWeight = app.lastActivityTime;
1546 } else if (app.pubProviders.size() > 0) {
1547 // If this process contains content providers, we want to keep
1548 // it a little more strongly.
1549 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1550 // Also don't let it kick out the first few "real" hidden processes.
1551 skipTop = MIN_HIDDEN_APPS;
1552 } else {
1553 // If this process doesn't have activities, we less strongly
1554 // want to keep it around, and generally want to avoid getting
1555 // in front of any very recently used activities.
1556 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1557 // Also don't let it kick out the first few "real" hidden processes.
1558 skipTop = MIN_HIDDEN_APPS;
1559 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001560
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001561 while (i >= 0) {
1562 ProcessRecord p = mLruProcesses.get(i);
1563 // If this app shouldn't be in front of the first N background
1564 // apps, then skip over that many that are currently hidden.
1565 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1566 skipTop--;
1567 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001568 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001569 mLruProcesses.add(i+1, app);
1570 break;
1571 }
1572 i--;
1573 }
1574 if (i < 0) {
1575 mLruProcesses.add(0, app);
1576 }
1577
Dianne Hackborn906497c2010-05-10 15:57:38 -07001578 // If the app is currently using a content provider or service,
1579 // bump those processes as well.
1580 if (app.connections.size() > 0) {
1581 for (ConnectionRecord cr : app.connections) {
1582 if (cr.binding != null && cr.binding.service != null
1583 && cr.binding.service.app != null
1584 && cr.binding.service.app.lruSeq != mLruSeq) {
1585 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1586 updateActivityTime, i+1);
1587 }
1588 }
1589 }
1590 if (app.conProviders.size() > 0) {
1591 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1592 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1593 updateLruProcessInternalLocked(cpr.app, oomAdj,
1594 updateActivityTime, i+1);
1595 }
1596 }
1597 }
1598
Joe Onorato8a9b2202010-02-26 18:56:32 -08001599 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 if (oomAdj) {
1601 updateOomAdjLocked();
1602 }
1603 }
1604
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001605 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001606 boolean oomAdj, boolean updateActivityTime) {
1607 mLruSeq++;
1608 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1609 }
1610
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001611 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 String processName, int uid) {
1613 if (uid == Process.SYSTEM_UID) {
1614 // The system gets to run in any process. If there are multiple
1615 // processes with the same uid, just pick the first (this
1616 // should never happen).
1617 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1618 processName);
1619 return procs != null ? procs.valueAt(0) : null;
1620 }
1621 ProcessRecord proc = mProcessNames.get(processName, uid);
1622 return proc;
1623 }
1624
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001625 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001626 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001627 try {
1628 if (pm.performDexOpt(packageName)) {
1629 mDidDexOpt = true;
1630 }
1631 } catch (RemoteException e) {
1632 }
1633 }
1634
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001635 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 int transit = mWindowManager.getPendingAppTransition();
1637 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1638 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1639 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1640 }
1641
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001642 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001644 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1646 // We don't have to do anything more if:
1647 // (1) There is an existing application record; and
1648 // (2) The caller doesn't think it is dead, OR there is no thread
1649 // object attached to it so we know it couldn't have crashed; and
1650 // (3) There is a pid assigned to it, so it is either starting or
1651 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001652 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 + " app=" + app + " knownToBeDead=" + knownToBeDead
1654 + " thread=" + (app != null ? app.thread : null)
1655 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001656 if (app != null && app.pid > 0) {
1657 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001658 // We already have the app running, or are waiting for it to
1659 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001660 return app;
1661 } else {
1662 // An application record is attached to a previous process,
1663 // clean it up now.
1664 handleAppDiedLocked(app, true);
1665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 String hostingNameStr = hostingName != null
1669 ? hostingName.flattenToShortString() : null;
1670
1671 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1672 // If we are in the background, then check to see if this process
1673 // is bad. If so, we will just silently fail.
1674 if (mBadProcesses.get(info.processName, info.uid) != null) {
1675 return null;
1676 }
1677 } else {
1678 // When the user is explicitly starting a process, then clear its
1679 // crash count so that we won't make it bad until they see at
1680 // least one crash dialog again, and make the process good again
1681 // if it had been bad.
1682 mProcessCrashTimes.remove(info.processName, info.uid);
1683 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001684 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 info.processName);
1686 mBadProcesses.remove(info.processName, info.uid);
1687 if (app != null) {
1688 app.bad = false;
1689 }
1690 }
1691 }
1692
1693 if (app == null) {
1694 app = newProcessRecordLocked(null, info, processName);
1695 mProcessNames.put(processName, info.uid, app);
1696 } else {
1697 // If this is a new package in the process, add the package to the list
1698 app.addPackage(info.packageName);
1699 }
1700
1701 // If the system is not ready yet, then hold off on starting this
1702 // process until it is.
1703 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001704 && !isAllowedWhileBooting(info)
1705 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 if (!mProcessesOnHold.contains(app)) {
1707 mProcessesOnHold.add(app);
1708 }
1709 return app;
1710 }
1711
1712 startProcessLocked(app, hostingType, hostingNameStr);
1713 return (app.pid != 0) ? app : null;
1714 }
1715
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001716 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1717 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1718 }
1719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 private final void startProcessLocked(ProcessRecord app,
1721 String hostingType, String hostingNameStr) {
1722 if (app.pid > 0 && app.pid != MY_PID) {
1723 synchronized (mPidsSelfLocked) {
1724 mPidsSelfLocked.remove(app.pid);
1725 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1726 }
1727 app.pid = 0;
1728 }
1729
1730 mProcessesOnHold.remove(app);
1731
1732 updateCpuStats();
1733
1734 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1735 mProcDeaths[0] = 0;
1736
1737 try {
1738 int uid = app.info.uid;
1739 int[] gids = null;
1740 try {
1741 gids = mContext.getPackageManager().getPackageGids(
1742 app.info.packageName);
1743 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001744 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 }
1746 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1747 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1748 && mTopComponent != null
1749 && app.processName.equals(mTopComponent.getPackageName())) {
1750 uid = 0;
1751 }
1752 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1753 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1754 uid = 0;
1755 }
1756 }
1757 int debugFlags = 0;
1758 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1759 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1760 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001761 // Run the app in safe mode if its manifest requests so or the
1762 // system is booted in safe mode.
1763 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1764 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001765 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1766 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1768 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1769 }
1770 if ("1".equals(SystemProperties.get("debug.assert"))) {
1771 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1772 }
1773 int pid = Process.start("android.app.ActivityThread",
1774 mSimpleProcessManagement ? app.processName : null, uid, uid,
1775 gids, debugFlags, null);
1776 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1777 synchronized (bs) {
1778 if (bs.isOnBattery()) {
1779 app.batteryStats.incStartsLocked();
1780 }
1781 }
1782
Doug Zongker2bec3d42009-12-04 12:52:44 -08001783 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 app.processName, hostingType,
1785 hostingNameStr != null ? hostingNameStr : "");
1786
1787 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001788 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 }
1790
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001791 StringBuilder buf = mStringBuilder;
1792 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793 buf.append("Start proc ");
1794 buf.append(app.processName);
1795 buf.append(" for ");
1796 buf.append(hostingType);
1797 if (hostingNameStr != null) {
1798 buf.append(" ");
1799 buf.append(hostingNameStr);
1800 }
1801 buf.append(": pid=");
1802 buf.append(pid);
1803 buf.append(" uid=");
1804 buf.append(uid);
1805 buf.append(" gids={");
1806 if (gids != null) {
1807 for (int gi=0; gi<gids.length; gi++) {
1808 if (gi != 0) buf.append(", ");
1809 buf.append(gids[gi]);
1810
1811 }
1812 }
1813 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001814 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 if (pid == 0 || pid == MY_PID) {
1816 // Processes are being emulated with threads.
1817 app.pid = MY_PID;
1818 app.removed = false;
1819 mStartingProcesses.add(app);
1820 } else if (pid > 0) {
1821 app.pid = pid;
1822 app.removed = false;
1823 synchronized (mPidsSelfLocked) {
1824 this.mPidsSelfLocked.put(pid, app);
1825 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1826 msg.obj = app;
1827 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1828 }
1829 } else {
1830 app.pid = 0;
1831 RuntimeException e = new RuntimeException(
1832 "Failure starting process " + app.processName
1833 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001834 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 }
1836 } catch (RuntimeException e) {
1837 // XXX do better error recovery.
1838 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001839 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 }
1841 }
1842
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001843 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 if (resumed) {
1845 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1846 } else {
1847 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1848 }
1849 }
1850
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001851 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001852 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1853 && mTopAction == null) {
1854 // We are running in factory test mode, but unable to find
1855 // the factory test app, so just sit around displaying the
1856 // error message and don't try to start anything.
1857 return false;
1858 }
1859 Intent intent = new Intent(
1860 mTopAction,
1861 mTopData != null ? Uri.parse(mTopData) : null);
1862 intent.setComponent(mTopComponent);
1863 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1864 intent.addCategory(Intent.CATEGORY_HOME);
1865 }
1866 ActivityInfo aInfo =
1867 intent.resolveActivityInfo(mContext.getPackageManager(),
1868 STOCK_PM_FLAGS);
1869 if (aInfo != null) {
1870 intent.setComponent(new ComponentName(
1871 aInfo.applicationInfo.packageName, aInfo.name));
1872 // Don't do this if the home app is currently being
1873 // instrumented.
1874 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1875 aInfo.applicationInfo.uid);
1876 if (app == null || app.instrumentationClass == null) {
1877 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001878 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001879 null, null, 0, 0, 0, false, false);
1880 }
1881 }
1882
1883
1884 return true;
1885 }
1886
1887 /**
1888 * Starts the "new version setup screen" if appropriate.
1889 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001890 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001891 // Only do this once per boot.
1892 if (mCheckedForSetup) {
1893 return;
1894 }
1895
1896 // We will show this screen if the current one is a different
1897 // version than the last one shown, and we are not running in
1898 // low-level factory test mode.
1899 final ContentResolver resolver = mContext.getContentResolver();
1900 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1901 Settings.Secure.getInt(resolver,
1902 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1903 mCheckedForSetup = true;
1904
1905 // See if we should be showing the platform update setup UI.
1906 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1907 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1908 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1909
1910 // We don't allow third party apps to replace this.
1911 ResolveInfo ri = null;
1912 for (int i=0; ris != null && i<ris.size(); i++) {
1913 if ((ris.get(i).activityInfo.applicationInfo.flags
1914 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1915 ri = ris.get(i);
1916 break;
1917 }
1918 }
1919
1920 if (ri != null) {
1921 String vers = ri.activityInfo.metaData != null
1922 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1923 : null;
1924 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
1925 vers = ri.activityInfo.applicationInfo.metaData.getString(
1926 Intent.METADATA_SETUP_VERSION);
1927 }
1928 String lastVers = Settings.Secure.getString(
1929 resolver, Settings.Secure.LAST_SETUP_SHOWN);
1930 if (vers != null && !vers.equals(lastVers)) {
1931 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1932 intent.setComponent(new ComponentName(
1933 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001934 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001935 null, null, 0, 0, 0, false, false);
1936 }
1937 }
1938 }
1939 }
1940
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001941 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001942 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001943
1944 final int identHash = System.identityHashCode(r);
1945 updateUsageStats(r, true);
1946
1947 int i = mWatchers.beginBroadcast();
1948 while (i > 0) {
1949 i--;
1950 IActivityWatcher w = mWatchers.getBroadcastItem(i);
1951 if (w != null) {
1952 try {
1953 w.activityResuming(identHash);
1954 } catch (RemoteException e) {
1955 }
1956 }
1957 }
1958 mWatchers.finishBroadcast();
1959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001960
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001961 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001962 final int N = mPendingActivityLaunches.size();
1963 if (N <= 0) {
1964 return;
1965 }
1966 for (int i=0; i<N; i++) {
1967 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001968 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001969 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
1970 doResume && i == (N-1));
1971 }
1972 mPendingActivityLaunches.clear();
1973 }
1974
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08001975 public final int startActivity(IApplicationThread caller,
1976 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
1977 int grantedMode, IBinder resultTo,
1978 String resultWho, int requestCode, boolean onlyIfNeeded,
1979 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001980 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07001981 grantedUriPermissions, grantedMode, resultTo, resultWho,
1982 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08001983 }
1984
1985 public final WaitResult startActivityAndWait(IApplicationThread caller,
1986 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
1987 int grantedMode, IBinder resultTo,
1988 String resultWho, int requestCode, boolean onlyIfNeeded,
1989 boolean debug) {
1990 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001991 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07001992 grantedUriPermissions, grantedMode, resultTo, resultWho,
1993 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08001994 return res;
1995 }
1996
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07001997 public final int startActivityWithConfig(IApplicationThread caller,
1998 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
1999 int grantedMode, IBinder resultTo,
2000 String resultWho, int requestCode, boolean onlyIfNeeded,
2001 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002002 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002003 grantedUriPermissions, grantedMode, resultTo, resultWho,
2004 requestCode, onlyIfNeeded, debug, null, config);
2005 }
2006
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002007 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002008 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002009 IBinder resultTo, String resultWho, int requestCode,
2010 int flagsMask, int flagsValues) {
2011 // Refuse possible leaked file descriptors
2012 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2013 throw new IllegalArgumentException("File descriptors passed in Intent");
2014 }
2015
2016 IIntentSender sender = intent.getTarget();
2017 if (!(sender instanceof PendingIntentRecord)) {
2018 throw new IllegalArgumentException("Bad PendingIntent object");
2019 }
2020
2021 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002022
2023 synchronized (this) {
2024 // If this is coming from the currently resumed activity, it is
2025 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002026 if (mMainStack.mResumedActivity != null
2027 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002028 Binder.getCallingUid()) {
2029 mAppSwitchesAllowedTime = 0;
2030 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002031 }
2032
2033 return pir.sendInner(0, fillInIntent, resolvedType,
2034 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2035 }
2036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 public boolean startNextMatchingActivity(IBinder callingActivity,
2038 Intent intent) {
2039 // Refuse possible leaked file descriptors
2040 if (intent != null && intent.hasFileDescriptors() == true) {
2041 throw new IllegalArgumentException("File descriptors passed in Intent");
2042 }
2043
2044 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002045 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 if (index < 0) {
2047 return false;
2048 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002049 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050 if (r.app == null || r.app.thread == null) {
2051 // The caller is not running... d'oh!
2052 return false;
2053 }
2054 intent = new Intent(intent);
2055 // The caller is not allowed to change the data.
2056 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2057 // And we are resetting to find the next component...
2058 intent.setComponent(null);
2059
2060 ActivityInfo aInfo = null;
2061 try {
2062 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002063 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002065 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066
2067 // Look for the original activity in the list...
2068 final int N = resolves != null ? resolves.size() : 0;
2069 for (int i=0; i<N; i++) {
2070 ResolveInfo rInfo = resolves.get(i);
2071 if (rInfo.activityInfo.packageName.equals(r.packageName)
2072 && rInfo.activityInfo.name.equals(r.info.name)) {
2073 // We found the current one... the next matching is
2074 // after it.
2075 i++;
2076 if (i<N) {
2077 aInfo = resolves.get(i).activityInfo;
2078 }
2079 break;
2080 }
2081 }
2082 } catch (RemoteException e) {
2083 }
2084
2085 if (aInfo == null) {
2086 // Nobody who is next!
2087 return false;
2088 }
2089
2090 intent.setComponent(new ComponentName(
2091 aInfo.applicationInfo.packageName, aInfo.name));
2092 intent.setFlags(intent.getFlags()&~(
2093 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2094 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2095 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2096 Intent.FLAG_ACTIVITY_NEW_TASK));
2097
2098 // Okay now we need to start the new activity, replacing the
2099 // currently running activity. This is a little tricky because
2100 // we want to start the new one as if the current one is finished,
2101 // but not finish the current one first so that there is no flicker.
2102 // And thus...
2103 final boolean wasFinishing = r.finishing;
2104 r.finishing = true;
2105
2106 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002107 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002108 final String resultWho = r.resultWho;
2109 final int requestCode = r.requestCode;
2110 r.resultTo = null;
2111 if (resultTo != null) {
2112 resultTo.removeResultsLocked(r, resultWho, requestCode);
2113 }
2114
2115 final long origId = Binder.clearCallingIdentity();
2116 // XXX we are not dealing with propagating grantedUriPermissions...
2117 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002118 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002119 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002120 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121 Binder.restoreCallingIdentity(origId);
2122
2123 r.finishing = wasFinishing;
2124 if (res != START_SUCCESS) {
2125 return false;
2126 }
2127 return true;
2128 }
2129 }
2130
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002131 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 Intent intent, String resolvedType, IBinder resultTo,
2133 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002134
2135 // This is so super not safe, that only the system (or okay root)
2136 // can do it.
2137 final int callingUid = Binder.getCallingUid();
2138 if (callingUid != 0 && callingUid != Process.myUid()) {
2139 throw new SecurityException(
2140 "startActivityInPackage only available to the system");
2141 }
2142
The Android Open Source Project4df24232009-03-05 14:34:35 -08002143 final boolean componentSpecified = intent.getComponent() != null;
2144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002145 // Don't modify the client's object!
2146 intent = new Intent(intent);
2147
2148 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 ActivityInfo aInfo;
2150 try {
2151 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002152 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002153 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002154 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 aInfo = rInfo != null ? rInfo.activityInfo : null;
2156 } catch (RemoteException e) {
2157 aInfo = null;
2158 }
2159
2160 if (aInfo != null) {
2161 // Store the found target back into the intent, because now that
2162 // we have it we never want to do this again. For example, if the
2163 // user navigates back to this point in the history, we should
2164 // always restart the exact same activity.
2165 intent.setComponent(new ComponentName(
2166 aInfo.applicationInfo.packageName, aInfo.name));
2167 }
2168
2169 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002170 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002171 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002172 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173 }
2174 }
2175
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002176 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 // Remove any existing entries that are the same kind of task.
2178 int N = mRecentTasks.size();
2179 for (int i=0; i<N; i++) {
2180 TaskRecord tr = mRecentTasks.get(i);
2181 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2182 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2183 mRecentTasks.remove(i);
2184 i--;
2185 N--;
2186 if (task.intent == null) {
2187 // If the new recent task we are adding is not fully
2188 // specified, then replace it with the existing recent task.
2189 task = tr;
2190 }
2191 }
2192 }
2193 if (N >= MAX_RECENT_TASKS) {
2194 mRecentTasks.remove(N-1);
2195 }
2196 mRecentTasks.add(0, task);
2197 }
2198
2199 public void setRequestedOrientation(IBinder token,
2200 int requestedOrientation) {
2201 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002202 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 if (index < 0) {
2204 return;
2205 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002206 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207 final long origId = Binder.clearCallingIdentity();
2208 mWindowManager.setAppOrientation(r, requestedOrientation);
2209 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002210 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002211 r.mayFreezeScreenLocked(r.app) ? r : null);
2212 if (config != null) {
2213 r.frozenBeforeDestroy = true;
2214 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002215 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216 }
2217 }
2218 Binder.restoreCallingIdentity(origId);
2219 }
2220 }
2221
2222 public int getRequestedOrientation(IBinder token) {
2223 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002224 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002225 if (index < 0) {
2226 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2227 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002228 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002229 return mWindowManager.getAppOrientation(r);
2230 }
2231 }
2232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 /**
2234 * This is the internal entry point for handling Activity.finish().
2235 *
2236 * @param token The Binder token referencing the Activity we want to finish.
2237 * @param resultCode Result code, if any, from this Activity.
2238 * @param resultData Result data (Intent), if any, from this Activity.
2239 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002240 * @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 -08002241 */
2242 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2243 // Refuse possible leaked file descriptors
2244 if (resultData != null && resultData.hasFileDescriptors() == true) {
2245 throw new IllegalArgumentException("File descriptors passed in Intent");
2246 }
2247
2248 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002249 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002251 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 if (next != null) {
2253 // ask watcher if this is allowed
2254 boolean resumeOK = true;
2255 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002256 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002258 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 }
2260
2261 if (!resumeOK) {
2262 return false;
2263 }
2264 }
2265 }
2266 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002267 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002268 resultData, "app-request");
2269 Binder.restoreCallingIdentity(origId);
2270 return res;
2271 }
2272 }
2273
Dianne Hackborn860755f2010-06-03 18:47:52 -07002274 public final void finishHeavyWeightApp() {
2275 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2276 != PackageManager.PERMISSION_GRANTED) {
2277 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2278 + Binder.getCallingPid()
2279 + ", uid=" + Binder.getCallingUid()
2280 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2281 Slog.w(TAG, msg);
2282 throw new SecurityException(msg);
2283 }
2284
2285 synchronized(this) {
2286 if (mHeavyWeightProcess == null) {
2287 return;
2288 }
2289
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002290 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002291 mHeavyWeightProcess.activities);
2292 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002293 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002294 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002295 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002296 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002297 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002298 null, "finish-heavy");
2299 }
2300 }
2301 }
2302
2303 mHeavyWeightProcess = null;
2304 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2305 }
2306 }
2307
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002308 public void crashApplication(int uid, int initialPid, String packageName,
2309 String message) {
2310 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2311 != PackageManager.PERMISSION_GRANTED) {
2312 String msg = "Permission Denial: crashApplication() from pid="
2313 + Binder.getCallingPid()
2314 + ", uid=" + Binder.getCallingUid()
2315 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2316 Slog.w(TAG, msg);
2317 throw new SecurityException(msg);
2318 }
2319
2320 synchronized(this) {
2321 ProcessRecord proc = null;
2322
2323 // Figure out which process to kill. We don't trust that initialPid
2324 // still has any relation to current pids, so must scan through the
2325 // list.
2326 synchronized (mPidsSelfLocked) {
2327 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2328 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2329 if (p.info.uid != uid) {
2330 continue;
2331 }
2332 if (p.pid == initialPid) {
2333 proc = p;
2334 break;
2335 }
2336 for (String str : p.pkgList) {
2337 if (str.equals(packageName)) {
2338 proc = p;
2339 }
2340 }
2341 }
2342 }
2343
2344 if (proc == null) {
2345 Log.w(TAG, "crashApplication: nothing for uid=" + uid
2346 + " initialPid=" + initialPid
2347 + " packageName=" + packageName);
2348 return;
2349 }
2350
2351 if (proc.thread != null) {
2352 long ident = Binder.clearCallingIdentity();
2353 try {
2354 proc.thread.scheduleCrash(message);
2355 } catch (RemoteException e) {
2356 }
2357 Binder.restoreCallingIdentity(ident);
2358 }
2359 }
2360 }
2361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002362 public final void finishSubActivity(IBinder token, String resultWho,
2363 int requestCode) {
2364 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002365 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002366 if (index < 0) {
2367 return;
2368 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002369 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370
2371 final long origId = Binder.clearCallingIdentity();
2372
2373 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002374 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2375 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 if (r.resultTo == self && r.requestCode == requestCode) {
2377 if ((r.resultWho == null && resultWho == null) ||
2378 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002379 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 Activity.RESULT_CANCELED, null, "request-sub");
2381 }
2382 }
2383 }
2384
2385 Binder.restoreCallingIdentity(origId);
2386 }
2387 }
2388
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002389 public boolean willActivityBeVisible(IBinder token) {
2390 synchronized(this) {
2391 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002392 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2393 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002394 if (r == token) {
2395 return true;
2396 }
2397 if (r.fullscreen && !r.finishing) {
2398 return false;
2399 }
2400 }
2401 return true;
2402 }
2403 }
2404
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002405 public void overridePendingTransition(IBinder token, String packageName,
2406 int enterAnim, int exitAnim) {
2407 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002408 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002409 if (index < 0) {
2410 return;
2411 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002412 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002413
2414 final long origId = Binder.clearCallingIdentity();
2415
2416 if (self.state == ActivityState.RESUMED
2417 || self.state == ActivityState.PAUSING) {
2418 mWindowManager.overridePendingAppTransition(packageName,
2419 enterAnim, exitAnim);
2420 }
2421
2422 Binder.restoreCallingIdentity(origId);
2423 }
2424 }
2425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002426 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002427 * Main function for removing an existing process from the activity manager
2428 * as a result of that process going away. Clears out all connections
2429 * to the process.
2430 */
2431 private final void handleAppDiedLocked(ProcessRecord app,
2432 boolean restarting) {
2433 cleanUpApplicationRecordLocked(app, restarting, -1);
2434 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002435 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 }
2437
2438 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002439 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2440 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2441 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002443 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2444 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 }
2446
2447 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002448 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002449
2450 boolean atTop = true;
2451 boolean hasVisibleActivities = false;
2452
2453 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002454 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002455 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002456 TAG, "Removing app " + app + " from history with " + i + " entries");
2457 while (i > 0) {
2458 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002459 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002460 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002461 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2462 if (r.app == app) {
2463 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
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 this entry! frozen=" + r.haveState
2466 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002467 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468
2469 r.inHistory = false;
2470 mWindowManager.removeAppToken(r);
2471 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002472 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002473 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002474 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002475
2476 } else {
2477 // We have the current state for this activity, so
2478 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002479 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002480 TAG, "Keeping entry, setting app to null");
2481 if (r.visible) {
2482 hasVisibleActivities = true;
2483 }
2484 r.app = null;
2485 r.nowVisible = false;
2486 if (!r.haveState) {
2487 r.icicle = null;
2488 }
2489 }
2490
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002491 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492 r.state = ActivityState.STOPPED;
2493 }
2494 atTop = false;
2495 }
2496
2497 app.activities.clear();
2498
2499 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002500 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 + " running instrumentation " + app.instrumentationClass);
2502 Bundle info = new Bundle();
2503 info.putString("shortMsg", "Process crashed.");
2504 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2505 }
2506
2507 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002508 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 // If there was nothing to resume, and we are not already
2510 // restarting this process, but there is a visible activity that
2511 // is hosted by the process... then make sure all visible
2512 // activities are running, taking care of restarting this
2513 // process.
2514 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002515 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 }
2517 }
2518 }
2519 }
2520
2521 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2522 IBinder threadBinder = thread.asBinder();
2523
2524 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002525 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2526 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2528 return i;
2529 }
2530 }
2531 return -1;
2532 }
2533
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002534 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535 IApplicationThread thread) {
2536 if (thread == null) {
2537 return null;
2538 }
2539
2540 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002541 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 }
2543
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002544 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 IApplicationThread thread) {
2546
2547 mProcDeaths[0]++;
2548
Magnus Edlund7bb25812010-02-24 15:45:06 +01002549 // Clean up already done if the process has been re-started.
2550 if (app.pid == pid && app.thread != null &&
2551 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002552 if (!app.killedBackground) {
2553 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2554 + ") has died.");
2555 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002556 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002557 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002558 TAG, "Dying app: " + app + ", pid: " + pid
2559 + ", thread: " + thread.asBinder());
2560 boolean doLowMem = app.instrumentationClass == null;
2561 handleAppDiedLocked(app, false);
2562
2563 if (doLowMem) {
2564 // If there are no longer any background processes running,
2565 // and the app that died was not running instrumentation,
2566 // then tell everyone we are now low on memory.
2567 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002568 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2569 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2571 haveBg = true;
2572 break;
2573 }
2574 }
2575
2576 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002577 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002578 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002579 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002580 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2581 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002582 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002583 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2584 // The low memory report is overriding any current
2585 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002586 // heavy/important/visible/foreground processes first.
2587 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002588 rec.lastRequestedGc = 0;
2589 } else {
2590 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002592 rec.reportLowMemory = true;
2593 rec.lastLowMemory = now;
2594 mProcessesToGc.remove(rec);
2595 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596 }
2597 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002598 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 }
2600 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002601 } else if (app.pid != pid) {
2602 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002603 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002604 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002605 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002606 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002607 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608 + thread.asBinder());
2609 }
2610 }
2611
Dan Egnor42471dd2010-01-07 17:25:22 -08002612 /**
2613 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002614 * @param clearTraces causes the dump file to be erased prior to the new
2615 * traces being written, if true; when false, the new traces will be
2616 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08002617 * @param pids of dalvik VM processes to dump stack traces for
2618 * @return file containing stack traces, or null if no dump file is configured
2619 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07002620 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002621 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2622 if (tracesPath == null || tracesPath.length() == 0) {
2623 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002625
2626 File tracesFile = new File(tracesPath);
2627 try {
2628 File tracesDir = tracesFile.getParentFile();
2629 if (!tracesDir.exists()) tracesFile.mkdirs();
2630 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2631
Christopher Tate6ee412d2010-05-28 12:01:56 -07002632 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002633 tracesFile.createNewFile();
2634 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2635 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002636 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002637 return null;
2638 }
2639
2640 // Use a FileObserver to detect when traces finish writing.
2641 // The order of traces is considered important to maintain for legibility.
2642 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2643 public synchronized void onEvent(int event, String path) { notify(); }
2644 };
2645
2646 try {
2647 observer.startWatching();
2648 int num = pids.size();
2649 for (int i = 0; i < num; i++) {
2650 synchronized (observer) {
2651 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
2652 observer.wait(200); // Wait for write-close, give up after 200msec
2653 }
2654 }
2655 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08002656 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002657 } finally {
2658 observer.stopWatching();
2659 }
2660
2661 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002662 }
2663
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002664 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2665 ActivityRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002666 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002667
2668 synchronized (this) {
2669 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2670 if (mShuttingDown) {
2671 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2672 return;
2673 } else if (app.notResponding) {
2674 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2675 return;
2676 } else if (app.crashing) {
2677 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2678 return;
2679 }
2680
2681 // In case we come through here for the same app before completing
2682 // this one, mark as anring now so we will bail out.
2683 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002684
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002685 // Log the ANR to the event log.
2686 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2687 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002688
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002689 // Dump thread traces as quickly as we can, starting with "interesting" processes.
2690 pids.add(app.pid);
2691
2692 int parentPid = app.pid;
2693 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
2694 if (parentPid != app.pid) pids.add(parentPid);
2695
2696 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002697
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002698 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2699 ProcessRecord r = mLruProcesses.get(i);
2700 if (r != null && r.thread != null) {
2701 int pid = r.pid;
2702 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
2703 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002704 }
2705 }
2706
Christopher Tate6ee412d2010-05-28 12:01:56 -07002707 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002708
2709 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002710 StringBuilder info = mStringBuilder;
2711 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002712 info.append("ANR in ").append(app.processName);
2713 if (activity != null && activity.shortComponentName != null) {
2714 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002715 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002716 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002718 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002720 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002721 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723
Dan Egnor42471dd2010-01-07 17:25:22 -08002724 String cpuInfo = null;
2725 if (MONITOR_CPU_USAGE) {
2726 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002727 synchronized (mProcessStatsThread) {
2728 cpuInfo = mProcessStats.printCurrentState();
2729 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002730 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 }
2732
Joe Onorato8a9b2202010-02-26 18:56:32 -08002733 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002734 if (tracesFile == null) {
2735 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2736 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2737 }
2738
2739 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2740
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002741 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002743 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2744 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002746 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2747 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 }
2749 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002750 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002751 }
2752 }
2753
Dan Egnor42471dd2010-01-07 17:25:22 -08002754 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2755 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2756 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002757
2758 synchronized (this) {
2759 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2760 Process.killProcess(app.pid);
2761 return;
2762 }
2763
2764 // Set the app's notResponding state, and look up the errorReportReceiver
2765 makeAppNotRespondingLocked(app,
2766 activity != null ? activity.shortComponentName : null,
2767 annotation != null ? "ANR " + annotation : "ANR",
2768 info.toString());
2769
2770 // Bring up the infamous App Not Responding dialog
2771 Message msg = Message.obtain();
2772 HashMap map = new HashMap();
2773 msg.what = SHOW_NOT_RESPONDING_MSG;
2774 msg.obj = map;
2775 map.put("app", app);
2776 if (activity != null) {
2777 map.put("activity", activity);
2778 }
2779
2780 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002782 }
2783
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002784 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002785 app.persistentActivities--;
2786 if (app.persistentActivities > 0) {
2787 // Still more of 'em...
2788 return;
2789 }
2790 if (app.persistent) {
2791 // Ah, but the application itself is persistent. Whatever!
2792 return;
2793 }
2794
2795 // App is no longer persistent... make sure it and the ones
2796 // following it in the LRU list have the correc oom_adj.
2797 updateOomAdjLocked();
2798 }
2799
2800 public void setPersistent(IBinder token, boolean isPersistent) {
2801 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2802 != PackageManager.PERMISSION_GRANTED) {
2803 String msg = "Permission Denial: setPersistent() from pid="
2804 + Binder.getCallingPid()
2805 + ", uid=" + Binder.getCallingUid()
2806 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002807 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 throw new SecurityException(msg);
2809 }
2810
2811 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002812 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813 if (index < 0) {
2814 return;
2815 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002816 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817 ProcessRecord app = r.app;
2818
Joe Onorato8a9b2202010-02-26 18:56:32 -08002819 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 TAG, "Setting persistence " + isPersistent + ": " + r);
2821
2822 if (isPersistent) {
2823 if (r.persistent) {
2824 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002825 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 return;
2827 }
2828 r.persistent = true;
2829 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002830 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002831 if (app.persistentActivities > 1) {
2832 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002833 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002834 return;
2835 }
2836 if (app.persistent) {
2837 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002838 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002839 return;
2840 }
2841
2842 // App is now persistent... make sure it and the ones
2843 // following it now have the correct oom_adj.
2844 final long origId = Binder.clearCallingIdentity();
2845 updateOomAdjLocked();
2846 Binder.restoreCallingIdentity(origId);
2847
2848 } else {
2849 if (!r.persistent) {
2850 // Okay okay, I heard you already!
2851 return;
2852 }
2853 r.persistent = false;
2854 final long origId = Binder.clearCallingIdentity();
2855 decPersistentCountLocked(app);
2856 Binder.restoreCallingIdentity(origId);
2857
2858 }
2859 }
2860 }
2861
2862 public boolean clearApplicationUserData(final String packageName,
2863 final IPackageDataObserver observer) {
2864 int uid = Binder.getCallingUid();
2865 int pid = Binder.getCallingPid();
2866 long callingId = Binder.clearCallingIdentity();
2867 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002868 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 int pkgUid = -1;
2870 synchronized(this) {
2871 try {
2872 pkgUid = pm.getPackageUid(packageName);
2873 } catch (RemoteException e) {
2874 }
2875 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002876 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002877 return false;
2878 }
2879 if (uid == pkgUid || checkComponentPermission(
2880 android.Manifest.permission.CLEAR_APP_USER_DATA,
2881 pid, uid, -1)
2882 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08002883 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 } else {
2885 throw new SecurityException(pid+" does not have permission:"+
2886 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
2887 "for process:"+packageName);
2888 }
2889 }
2890
2891 try {
2892 //clear application user data
2893 pm.clearApplicationUserData(packageName, observer);
2894 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
2895 Uri.fromParts("package", packageName, null));
2896 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06002897 synchronized (this) {
2898 broadcastIntentLocked(null, null, intent,
2899 null, null, 0, null, null, null,
2900 false, false, MY_PID, Process.SYSTEM_UID);
2901 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002902 } catch (RemoteException e) {
2903 }
2904 } finally {
2905 Binder.restoreCallingIdentity(callingId);
2906 }
2907 return true;
2908 }
2909
Dianne Hackborn03abb812010-01-04 18:43:19 -08002910 public void killBackgroundProcesses(final String packageName) {
2911 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
2912 != PackageManager.PERMISSION_GRANTED &&
2913 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
2914 != PackageManager.PERMISSION_GRANTED) {
2915 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002916 + Binder.getCallingPid()
2917 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08002918 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002919 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920 throw new SecurityException(msg);
2921 }
2922
2923 long callingId = Binder.clearCallingIdentity();
2924 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002925 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002926 int pkgUid = -1;
2927 synchronized(this) {
2928 try {
2929 pkgUid = pm.getPackageUid(packageName);
2930 } catch (RemoteException e) {
2931 }
2932 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002933 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 return;
2935 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08002936 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08002937 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002938 }
2939 } finally {
2940 Binder.restoreCallingIdentity(callingId);
2941 }
2942 }
2943
2944 public void forceStopPackage(final String packageName) {
2945 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2946 != PackageManager.PERMISSION_GRANTED) {
2947 String msg = "Permission Denial: forceStopPackage() from pid="
2948 + Binder.getCallingPid()
2949 + ", uid=" + Binder.getCallingUid()
2950 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002951 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002952 throw new SecurityException(msg);
2953 }
2954
2955 long callingId = Binder.clearCallingIdentity();
2956 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002957 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08002958 int pkgUid = -1;
2959 synchronized(this) {
2960 try {
2961 pkgUid = pm.getPackageUid(packageName);
2962 } catch (RemoteException e) {
2963 }
2964 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002965 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002966 return;
2967 }
2968 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002969 }
2970 } finally {
2971 Binder.restoreCallingIdentity(callingId);
2972 }
2973 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002974
2975 /*
2976 * The pkg name and uid have to be specified.
2977 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
2978 */
2979 public void killApplicationWithUid(String pkg, int uid) {
2980 if (pkg == null) {
2981 return;
2982 }
2983 // Make sure the uid is valid.
2984 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002985 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002986 return;
2987 }
2988 int callerUid = Binder.getCallingUid();
2989 // Only the system server can kill an application
2990 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07002991 // Post an aysnc message to kill the application
2992 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
2993 msg.arg1 = uid;
2994 msg.arg2 = 0;
2995 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07002996 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002997 } else {
2998 throw new SecurityException(callerUid + " cannot kill pkg: " +
2999 pkg);
3000 }
3001 }
3002
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003003 public void closeSystemDialogs(String reason) {
3004 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
3005 if (reason != null) {
3006 intent.putExtra("reason", reason);
3007 }
3008
3009 final int uid = Binder.getCallingUid();
3010 final long origId = Binder.clearCallingIdentity();
3011 synchronized (this) {
3012 int i = mWatchers.beginBroadcast();
3013 while (i > 0) {
3014 i--;
3015 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3016 if (w != null) {
3017 try {
3018 w.closingSystemDialogs(reason);
3019 } catch (RemoteException e) {
3020 }
3021 }
3022 }
3023 mWatchers.finishBroadcast();
3024
Dianne Hackbornffa42482009-09-23 22:20:11 -07003025 mWindowManager.closeSystemDialogs(reason);
3026
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003027 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3028 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003029 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003030 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003031 Activity.RESULT_CANCELED, null, "close-sys");
3032 }
3033 }
3034
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003035 broadcastIntentLocked(null, null, intent, null,
3036 null, 0, null, null, null, false, false, -1, uid);
3037 }
3038 Binder.restoreCallingIdentity(origId);
3039 }
3040
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003041 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003042 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003043 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3044 for (int i=pids.length-1; i>=0; i--) {
3045 infos[i] = new Debug.MemoryInfo();
3046 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003047 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003048 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003049 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003050
3051 public void killApplicationProcess(String processName, int uid) {
3052 if (processName == null) {
3053 return;
3054 }
3055
3056 int callerUid = Binder.getCallingUid();
3057 // Only the system server can kill an application
3058 if (callerUid == Process.SYSTEM_UID) {
3059 synchronized (this) {
3060 ProcessRecord app = getProcessRecordLocked(processName, uid);
3061 if (app != null) {
3062 try {
3063 app.thread.scheduleSuicide();
3064 } catch (RemoteException e) {
3065 // If the other end already died, then our work here is done.
3066 }
3067 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003068 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003069 + processName + " / " + uid);
3070 }
3071 }
3072 } else {
3073 throw new SecurityException(callerUid + " cannot kill app process: " +
3074 processName);
3075 }
3076 }
3077
Dianne Hackborn03abb812010-01-04 18:43:19 -08003078 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003079 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003080 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3081 Uri.fromParts("package", packageName, null));
3082 intent.putExtra(Intent.EXTRA_UID, uid);
3083 broadcastIntentLocked(null, null, intent,
3084 null, null, 0, null, null, null,
3085 false, false, MY_PID, Process.SYSTEM_UID);
3086 }
3087
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003088 private final boolean killPackageProcessesLocked(String packageName, int uid,
3089 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003090 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003091
Dianne Hackborn03abb812010-01-04 18:43:19 -08003092 // Remove all processes this package may have touched: all with the
3093 // same UID (except for the system or root user), and all whose name
3094 // matches the package name.
3095 final String procNamePrefix = packageName + ":";
3096 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3097 final int NA = apps.size();
3098 for (int ia=0; ia<NA; ia++) {
3099 ProcessRecord app = apps.valueAt(ia);
3100 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003101 if (doit) {
3102 procs.add(app);
3103 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003104 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3105 || app.processName.equals(packageName)
3106 || app.processName.startsWith(procNamePrefix)) {
3107 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003108 if (!doit) {
3109 return true;
3110 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003111 app.removed = true;
3112 procs.add(app);
3113 }
3114 }
3115 }
3116 }
3117
3118 int N = procs.size();
3119 for (int i=0; i<N; i++) {
3120 removeProcessLocked(procs.get(i), callerWillRestart);
3121 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003122 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003123 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003124
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003125 private final boolean forceStopPackageLocked(String name, int uid,
3126 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127 int i, N;
3128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003129 if (uid < 0) {
3130 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003131 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003132 } catch (RemoteException e) {
3133 }
3134 }
3135
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003136 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003137 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003138
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003139 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3140 while (badApps.hasNext()) {
3141 SparseArray<Long> ba = badApps.next();
3142 if (ba.get(uid) != null) {
3143 badApps.remove();
3144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 }
3146 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003147
3148 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3149 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003150
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003151 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3152 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003153 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003154 if (!doit) {
3155 return true;
3156 }
3157 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003158 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 if (r.app != null) {
3160 r.app.removed = true;
3161 }
3162 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003163 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003164 }
3165 }
3166
3167 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3168 for (ServiceRecord service : mServices.values()) {
3169 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003170 if (!doit) {
3171 return true;
3172 }
3173 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003174 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 if (service.app != null) {
3176 service.app.removed = true;
3177 }
3178 service.app = null;
3179 services.add(service);
3180 }
3181 }
3182
3183 N = services.size();
3184 for (i=0; i<N; i++) {
3185 bringDownServiceLocked(services.get(i), true);
3186 }
3187
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003188 if (doit) {
3189 if (purgeCache) {
3190 AttributeCache ac = AttributeCache.instance();
3191 if (ac != null) {
3192 ac.removePackage(name);
3193 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003194 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003195 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003196 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003197
3198 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199 }
3200
3201 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3202 final String name = app.processName;
3203 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003204 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 TAG, "Force removing process " + app + " (" + name
3206 + "/" + uid + ")");
3207
3208 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003209 if (mHeavyWeightProcess == app) {
3210 mHeavyWeightProcess = null;
3211 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 boolean needRestart = false;
3214 if (app.pid > 0 && app.pid != MY_PID) {
3215 int pid = app.pid;
3216 synchronized (mPidsSelfLocked) {
3217 mPidsSelfLocked.remove(pid);
3218 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3219 }
3220 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003221 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 Process.killProcess(pid);
3223
3224 if (app.persistent) {
3225 if (!callerWillRestart) {
3226 addAppLocked(app.info);
3227 } else {
3228 needRestart = true;
3229 }
3230 }
3231 } else {
3232 mRemovedProcesses.add(app);
3233 }
3234
3235 return needRestart;
3236 }
3237
3238 private final void processStartTimedOutLocked(ProcessRecord app) {
3239 final int pid = app.pid;
3240 boolean gone = false;
3241 synchronized (mPidsSelfLocked) {
3242 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3243 if (knownApp != null && knownApp.thread == null) {
3244 mPidsSelfLocked.remove(pid);
3245 gone = true;
3246 }
3247 }
3248
3249 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003250 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003251 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003252 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003254 if (mHeavyWeightProcess == app) {
3255 mHeavyWeightProcess = null;
3256 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3257 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003258 // Take care of any launching providers waiting for this process.
3259 checkAppInLaunchingProvidersLocked(app, true);
3260 // Take care of any services that are waiting for the process.
3261 for (int i=0; i<mPendingServices.size(); i++) {
3262 ServiceRecord sr = mPendingServices.get(i);
3263 if (app.info.uid == sr.appInfo.uid
3264 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003265 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003266 mPendingServices.remove(i);
3267 i--;
3268 bringDownServiceLocked(sr, true);
3269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003271 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003272 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003273 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003274 try {
3275 IBackupManager bm = IBackupManager.Stub.asInterface(
3276 ServiceManager.getService(Context.BACKUP_SERVICE));
3277 bm.agentDisconnected(app.info.packageName);
3278 } catch (RemoteException e) {
3279 // Can't happen; the backup manager is local
3280 }
3281 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003282 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003283 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003284 mPendingBroadcast = null;
3285 scheduleBroadcastsLocked();
3286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003288 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 }
3290 }
3291
3292 private final boolean attachApplicationLocked(IApplicationThread thread,
3293 int pid) {
3294
3295 // Find the application record that is being attached... either via
3296 // the pid if we are running in multiple processes, or just pull the
3297 // next app record if we are emulating process with anonymous threads.
3298 ProcessRecord app;
3299 if (pid != MY_PID && pid >= 0) {
3300 synchronized (mPidsSelfLocked) {
3301 app = mPidsSelfLocked.get(pid);
3302 }
3303 } else if (mStartingProcesses.size() > 0) {
3304 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003305 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003306 } else {
3307 app = null;
3308 }
3309
3310 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003311 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003313 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 if (pid > 0 && pid != MY_PID) {
3315 Process.killProcess(pid);
3316 } else {
3317 try {
3318 thread.scheduleExit();
3319 } catch (Exception e) {
3320 // Ignore exceptions.
3321 }
3322 }
3323 return false;
3324 }
3325
3326 // If this application record is still attached to a previous
3327 // process, clean it up now.
3328 if (app.thread != null) {
3329 handleAppDiedLocked(app, true);
3330 }
3331
3332 // Tell the process all about itself.
3333
Joe Onorato8a9b2202010-02-26 18:56:32 -08003334 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 TAG, "Binding process pid " + pid + " to record " + app);
3336
3337 String processName = app.processName;
3338 try {
3339 thread.asBinder().linkToDeath(new AppDeathRecipient(
3340 app, pid, thread), 0);
3341 } catch (RemoteException e) {
3342 app.resetPackageList();
3343 startProcessLocked(app, "link fail", processName);
3344 return false;
3345 }
3346
Doug Zongker2bec3d42009-12-04 12:52:44 -08003347 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348
3349 app.thread = thread;
3350 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003351 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3352 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 app.forcingToForeground = null;
3354 app.foregroundServices = false;
3355 app.debugging = false;
3356
3357 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3358
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003359 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
3360 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003361
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003362 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003363 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003364 }
3365
Joe Onorato8a9b2202010-02-26 18:56:32 -08003366 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 TAG, "New app record " + app
3368 + " thread=" + thread.asBinder() + " pid=" + pid);
3369 try {
3370 int testMode = IApplicationThread.DEBUG_OFF;
3371 if (mDebugApp != null && mDebugApp.equals(processName)) {
3372 testMode = mWaitForDebugger
3373 ? IApplicationThread.DEBUG_WAIT
3374 : IApplicationThread.DEBUG_ON;
3375 app.debugging = true;
3376 if (mDebugTransient) {
3377 mDebugApp = mOrigDebugApp;
3378 mWaitForDebugger = mOrigWaitForDebugger;
3379 }
3380 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003381
Christopher Tate181fafa2009-05-14 11:12:14 -07003382 // If the app is being launched for restore or full backup, set it up specially
3383 boolean isRestrictedBackupMode = false;
3384 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3385 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3386 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3387 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003388
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003389 ensurePackageDexOpt(app.instrumentationInfo != null
3390 ? app.instrumentationInfo.packageName
3391 : app.info.packageName);
3392 if (app.instrumentationClass != null) {
3393 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003394 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003395 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003396 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003397 thread.bindApplication(processName, app.instrumentationInfo != null
3398 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003399 app.instrumentationClass, app.instrumentationProfileFile,
3400 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003401 isRestrictedBackupMode || !normalMode,
3402 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003403 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003404 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405 } catch (Exception e) {
3406 // todo: Yikes! What should we do? For now we will try to
3407 // start another process, but that could easily get us in
3408 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003409 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410
3411 app.resetPackageList();
3412 startProcessLocked(app, "bind fail", processName);
3413 return false;
3414 }
3415
3416 // Remove this record from the list of starting applications.
3417 mPersistentStartingProcesses.remove(app);
3418 mProcessesOnHold.remove(app);
3419
3420 boolean badApp = false;
3421 boolean didSomething = false;
3422
3423 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003424 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003425 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3427 && processName.equals(hr.processName)) {
3428 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003429 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 didSomething = true;
3431 }
3432 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003433 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 + hr.intent.getComponent().flattenToShortString(), e);
3435 badApp = true;
3436 }
3437 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003438 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003439 }
3440 }
3441
3442 // Find any services that should be running in this process...
3443 if (!badApp && mPendingServices.size() > 0) {
3444 ServiceRecord sr = null;
3445 try {
3446 for (int i=0; i<mPendingServices.size(); i++) {
3447 sr = mPendingServices.get(i);
3448 if (app.info.uid != sr.appInfo.uid
3449 || !processName.equals(sr.processName)) {
3450 continue;
3451 }
3452
3453 mPendingServices.remove(i);
3454 i--;
3455 realStartServiceLocked(sr, app);
3456 didSomething = true;
3457 }
3458 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003459 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 + sr.shortName, e);
3461 badApp = true;
3462 }
3463 }
3464
3465 // Check if the next broadcast receiver is in this process...
3466 BroadcastRecord br = mPendingBroadcast;
3467 if (!badApp && br != null && br.curApp == app) {
3468 try {
3469 mPendingBroadcast = null;
3470 processCurBroadcastLocked(br, app);
3471 didSomething = true;
3472 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003473 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 + br.curComponent.flattenToShortString(), e);
3475 badApp = true;
3476 logBroadcastReceiverDiscard(br);
3477 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3478 br.resultExtras, br.resultAbort, true);
3479 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003480 // We need to reset the state if we fails to start the receiver.
3481 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003482 }
3483 }
3484
Christopher Tate181fafa2009-05-14 11:12:14 -07003485 // Check whether the next backup agent is in this process...
3486 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003487 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003488 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003489 try {
3490 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3491 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003492 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003493 e.printStackTrace();
3494 }
3495 }
3496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 if (badApp) {
3498 // todo: Also need to kill application to deal with all
3499 // kinds of exceptions.
3500 handleAppDiedLocked(app, false);
3501 return false;
3502 }
3503
3504 if (!didSomething) {
3505 updateOomAdjLocked();
3506 }
3507
3508 return true;
3509 }
3510
3511 public final void attachApplication(IApplicationThread thread) {
3512 synchronized (this) {
3513 int callingPid = Binder.getCallingPid();
3514 final long origId = Binder.clearCallingIdentity();
3515 attachApplicationLocked(thread, callingPid);
3516 Binder.restoreCallingIdentity(origId);
3517 }
3518 }
3519
Dianne Hackborne88846e2009-09-30 21:34:25 -07003520 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003522 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 Binder.restoreCallingIdentity(origId);
3524 }
3525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003527 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003528 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 mWindowManager.enableScreenAfterBoot();
3530 }
3531
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003532 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003533 IntentFilter pkgFilter = new IntentFilter();
3534 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3535 pkgFilter.addDataScheme("package");
3536 mContext.registerReceiver(new BroadcastReceiver() {
3537 @Override
3538 public void onReceive(Context context, Intent intent) {
3539 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3540 if (pkgs != null) {
3541 for (String pkg : pkgs) {
3542 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3543 setResultCode(Activity.RESULT_OK);
3544 return;
3545 }
3546 }
3547 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003548 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003549 }, pkgFilter);
3550
3551 synchronized (this) {
3552 // Ensure that any processes we had put on hold are now started
3553 // up.
3554 final int NP = mProcessesOnHold.size();
3555 if (NP > 0) {
3556 ArrayList<ProcessRecord> procs =
3557 new ArrayList<ProcessRecord>(mProcessesOnHold);
3558 for (int ip=0; ip<NP; ip++) {
3559 this.startProcessLocked(procs.get(ip), "on-hold", null);
3560 }
3561 }
3562
3563 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
3564 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003565 broadcastIntentLocked(null, null,
3566 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3567 null, null, 0, null, null,
3568 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3569 false, false, MY_PID, Process.SYSTEM_UID);
3570 }
3571 }
3572 }
3573
3574 final void ensureBootCompleted() {
3575 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003576 boolean enableScreen;
3577 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003578 booting = mBooting;
3579 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003580 enableScreen = !mBooted;
3581 mBooted = true;
3582 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003583
3584 if (booting) {
3585 finishBooting();
3586 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003587
3588 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003589 enableScreenAfterBoot();
3590 }
3591 }
3592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 public final void activityPaused(IBinder token, Bundle icicle) {
3594 // Refuse possible leaked file descriptors
3595 if (icicle != null && icicle.hasFileDescriptors()) {
3596 throw new IllegalArgumentException("File descriptors passed in Bundle");
3597 }
3598
3599 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003600 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003601 Binder.restoreCallingIdentity(origId);
3602 }
3603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003604 public final void activityStopped(IBinder token, Bitmap thumbnail,
3605 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003606 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 TAG, "Activity stopped: token=" + token);
3608
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003609 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610
3611 final long origId = Binder.clearCallingIdentity();
3612
3613 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003614 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003616 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003617 r.thumbnail = thumbnail;
3618 r.description = description;
3619 r.stopped = true;
3620 r.state = ActivityState.STOPPED;
3621 if (!r.finishing) {
3622 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003623 r.stack.destroyActivityLocked(r, true);
3624 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003625 }
3626 }
3627 }
3628 }
3629
3630 if (r != null) {
3631 sendPendingThumbnail(r, null, null, null, false);
3632 }
3633
3634 trimApplications();
3635
3636 Binder.restoreCallingIdentity(origId);
3637 }
3638
3639 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003640 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003641 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 }
3643
3644 public String getCallingPackage(IBinder token) {
3645 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003646 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003647 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003648 }
3649 }
3650
3651 public ComponentName getCallingActivity(IBinder token) {
3652 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003653 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003654 return r != null ? r.intent.getComponent() : null;
3655 }
3656 }
3657
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003658 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003659 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003661 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 if (r != null) {
3663 return r.resultTo;
3664 }
3665 }
3666 return null;
3667 }
3668
3669 public ComponentName getActivityClassForToken(IBinder token) {
3670 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003671 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003673 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 return r.intent.getComponent();
3675 }
3676 return null;
3677 }
3678 }
3679
3680 public String getPackageForToken(IBinder token) {
3681 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003682 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003684 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 return r.packageName;
3686 }
3687 return null;
3688 }
3689 }
3690
3691 public IIntentSender getIntentSender(int type,
3692 String packageName, IBinder token, String resultWho,
3693 int requestCode, Intent intent, String resolvedType, int flags) {
3694 // Refuse possible leaked file descriptors
3695 if (intent != null && intent.hasFileDescriptors() == true) {
3696 throw new IllegalArgumentException("File descriptors passed in Intent");
3697 }
3698
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003699 if (type == INTENT_SENDER_BROADCAST) {
3700 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3701 throw new IllegalArgumentException(
3702 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3703 }
3704 }
3705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 synchronized(this) {
3707 int callingUid = Binder.getCallingUid();
3708 try {
3709 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3710 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003711 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712 .getPackageUid(packageName);
3713 if (uid != Binder.getCallingUid()) {
3714 String msg = "Permission Denial: getIntentSender() from pid="
3715 + Binder.getCallingPid()
3716 + ", uid=" + Binder.getCallingUid()
3717 + ", (need uid=" + uid + ")"
3718 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003719 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720 throw new SecurityException(msg);
3721 }
3722 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003723
3724 return getIntentSenderLocked(type, packageName, callingUid,
3725 token, resultWho, requestCode, intent, resolvedType, flags);
3726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003727 } catch (RemoteException e) {
3728 throw new SecurityException(e);
3729 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003730 }
3731 }
3732
3733 IIntentSender getIntentSenderLocked(int type,
3734 String packageName, int callingUid, IBinder token, String resultWho,
3735 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003736 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003737 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003738 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003739 if (index < 0) {
3740 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003742 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003743 if (activity.finishing) {
3744 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003746 }
3747
3748 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3749 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3750 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3751 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3752 |PendingIntent.FLAG_UPDATE_CURRENT);
3753
3754 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3755 type, packageName, activity, resultWho,
3756 requestCode, intent, resolvedType, flags);
3757 WeakReference<PendingIntentRecord> ref;
3758 ref = mIntentSenderRecords.get(key);
3759 PendingIntentRecord rec = ref != null ? ref.get() : null;
3760 if (rec != null) {
3761 if (!cancelCurrent) {
3762 if (updateCurrent) {
3763 rec.key.requestIntent.replaceExtras(intent);
3764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 return rec;
3766 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003767 rec.canceled = true;
3768 mIntentSenderRecords.remove(key);
3769 }
3770 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003771 return rec;
3772 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003773 rec = new PendingIntentRecord(this, key, callingUid);
3774 mIntentSenderRecords.put(key, rec.ref);
3775 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3776 if (activity.pendingResults == null) {
3777 activity.pendingResults
3778 = new HashSet<WeakReference<PendingIntentRecord>>();
3779 }
3780 activity.pendingResults.add(rec.ref);
3781 }
3782 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 }
3784
3785 public void cancelIntentSender(IIntentSender sender) {
3786 if (!(sender instanceof PendingIntentRecord)) {
3787 return;
3788 }
3789 synchronized(this) {
3790 PendingIntentRecord rec = (PendingIntentRecord)sender;
3791 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003792 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793 .getPackageUid(rec.key.packageName);
3794 if (uid != Binder.getCallingUid()) {
3795 String msg = "Permission Denial: cancelIntentSender() from pid="
3796 + Binder.getCallingPid()
3797 + ", uid=" + Binder.getCallingUid()
3798 + " is not allowed to cancel packges "
3799 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003800 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003801 throw new SecurityException(msg);
3802 }
3803 } catch (RemoteException e) {
3804 throw new SecurityException(e);
3805 }
3806 cancelIntentSenderLocked(rec, true);
3807 }
3808 }
3809
3810 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3811 rec.canceled = true;
3812 mIntentSenderRecords.remove(rec.key);
3813 if (cleanActivity && rec.key.activity != null) {
3814 rec.key.activity.pendingResults.remove(rec.ref);
3815 }
3816 }
3817
3818 public String getPackageForIntentSender(IIntentSender pendingResult) {
3819 if (!(pendingResult instanceof PendingIntentRecord)) {
3820 return null;
3821 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003822 try {
3823 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3824 return res.key.packageName;
3825 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 }
3827 return null;
3828 }
3829
3830 public void setProcessLimit(int max) {
3831 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3832 "setProcessLimit()");
3833 mProcessLimit = max;
3834 }
3835
3836 public int getProcessLimit() {
3837 return mProcessLimit;
3838 }
3839
3840 void foregroundTokenDied(ForegroundToken token) {
3841 synchronized (ActivityManagerService.this) {
3842 synchronized (mPidsSelfLocked) {
3843 ForegroundToken cur
3844 = mForegroundProcesses.get(token.pid);
3845 if (cur != token) {
3846 return;
3847 }
3848 mForegroundProcesses.remove(token.pid);
3849 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3850 if (pr == null) {
3851 return;
3852 }
3853 pr.forcingToForeground = null;
3854 pr.foregroundServices = false;
3855 }
3856 updateOomAdjLocked();
3857 }
3858 }
3859
3860 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
3861 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3862 "setProcessForeground()");
3863 synchronized(this) {
3864 boolean changed = false;
3865
3866 synchronized (mPidsSelfLocked) {
3867 ProcessRecord pr = mPidsSelfLocked.get(pid);
3868 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003869 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 return;
3871 }
3872 ForegroundToken oldToken = mForegroundProcesses.get(pid);
3873 if (oldToken != null) {
3874 oldToken.token.unlinkToDeath(oldToken, 0);
3875 mForegroundProcesses.remove(pid);
3876 pr.forcingToForeground = null;
3877 changed = true;
3878 }
3879 if (isForeground && token != null) {
3880 ForegroundToken newToken = new ForegroundToken() {
3881 public void binderDied() {
3882 foregroundTokenDied(this);
3883 }
3884 };
3885 newToken.pid = pid;
3886 newToken.token = token;
3887 try {
3888 token.linkToDeath(newToken, 0);
3889 mForegroundProcesses.put(pid, newToken);
3890 pr.forcingToForeground = token;
3891 changed = true;
3892 } catch (RemoteException e) {
3893 // If the process died while doing this, we will later
3894 // do the cleanup with the process death link.
3895 }
3896 }
3897 }
3898
3899 if (changed) {
3900 updateOomAdjLocked();
3901 }
3902 }
3903 }
3904
3905 // =========================================================
3906 // PERMISSIONS
3907 // =========================================================
3908
3909 static class PermissionController extends IPermissionController.Stub {
3910 ActivityManagerService mActivityManagerService;
3911 PermissionController(ActivityManagerService activityManagerService) {
3912 mActivityManagerService = activityManagerService;
3913 }
3914
3915 public boolean checkPermission(String permission, int pid, int uid) {
3916 return mActivityManagerService.checkPermission(permission, pid,
3917 uid) == PackageManager.PERMISSION_GRANTED;
3918 }
3919 }
3920
3921 /**
3922 * This can be called with or without the global lock held.
3923 */
3924 int checkComponentPermission(String permission, int pid, int uid,
3925 int reqUid) {
3926 // We might be performing an operation on behalf of an indirect binder
3927 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
3928 // client identity accordingly before proceeding.
3929 Identity tlsIdentity = sCallerIdentity.get();
3930 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003931 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
3933 uid = tlsIdentity.uid;
3934 pid = tlsIdentity.pid;
3935 }
3936
3937 // Root, system server and our own process get to do everything.
3938 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
3939 !Process.supportsProcesses()) {
3940 return PackageManager.PERMISSION_GRANTED;
3941 }
3942 // If the target requires a specific UID, always fail for others.
3943 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003944 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 return PackageManager.PERMISSION_DENIED;
3946 }
3947 if (permission == null) {
3948 return PackageManager.PERMISSION_GRANTED;
3949 }
3950 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003951 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 .checkUidPermission(permission, uid);
3953 } catch (RemoteException e) {
3954 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003955 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003956 }
3957 return PackageManager.PERMISSION_DENIED;
3958 }
3959
3960 /**
3961 * As the only public entry point for permissions checking, this method
3962 * can enforce the semantic that requesting a check on a null global
3963 * permission is automatically denied. (Internally a null permission
3964 * string is used when calling {@link #checkComponentPermission} in cases
3965 * when only uid-based security is needed.)
3966 *
3967 * This can be called with or without the global lock held.
3968 */
3969 public int checkPermission(String permission, int pid, int uid) {
3970 if (permission == null) {
3971 return PackageManager.PERMISSION_DENIED;
3972 }
3973 return checkComponentPermission(permission, pid, uid, -1);
3974 }
3975
3976 /**
3977 * Binder IPC calls go through the public entry point.
3978 * This can be called with or without the global lock held.
3979 */
3980 int checkCallingPermission(String permission) {
3981 return checkPermission(permission,
3982 Binder.getCallingPid(),
3983 Binder.getCallingUid());
3984 }
3985
3986 /**
3987 * This can be called with or without the global lock held.
3988 */
3989 void enforceCallingPermission(String permission, String func) {
3990 if (checkCallingPermission(permission)
3991 == PackageManager.PERMISSION_GRANTED) {
3992 return;
3993 }
3994
3995 String msg = "Permission Denial: " + func + " from pid="
3996 + Binder.getCallingPid()
3997 + ", uid=" + Binder.getCallingUid()
3998 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003999 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 throw new SecurityException(msg);
4001 }
4002
4003 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4004 ProviderInfo pi, int uid, int modeFlags) {
4005 try {
4006 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4007 if ((pi.readPermission != null) &&
4008 (pm.checkUidPermission(pi.readPermission, uid)
4009 != PackageManager.PERMISSION_GRANTED)) {
4010 return false;
4011 }
4012 }
4013 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4014 if ((pi.writePermission != null) &&
4015 (pm.checkUidPermission(pi.writePermission, uid)
4016 != PackageManager.PERMISSION_GRANTED)) {
4017 return false;
4018 }
4019 }
4020 return true;
4021 } catch (RemoteException e) {
4022 return false;
4023 }
4024 }
4025
4026 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4027 int modeFlags) {
4028 // Root gets to do everything.
4029 if (uid == 0 || !Process.supportsProcesses()) {
4030 return true;
4031 }
4032 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4033 if (perms == null) return false;
4034 UriPermission perm = perms.get(uri);
4035 if (perm == null) return false;
4036 return (modeFlags&perm.modeFlags) == modeFlags;
4037 }
4038
4039 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4040 // Another redirected-binder-call permissions check as in
4041 // {@link checkComponentPermission}.
4042 Identity tlsIdentity = sCallerIdentity.get();
4043 if (tlsIdentity != null) {
4044 uid = tlsIdentity.uid;
4045 pid = tlsIdentity.pid;
4046 }
4047
4048 // Our own process gets to do everything.
4049 if (pid == MY_PID) {
4050 return PackageManager.PERMISSION_GRANTED;
4051 }
4052 synchronized(this) {
4053 return checkUriPermissionLocked(uri, uid, modeFlags)
4054 ? PackageManager.PERMISSION_GRANTED
4055 : PackageManager.PERMISSION_DENIED;
4056 }
4057 }
4058
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004059 void grantUriPermissionLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004060 String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4062 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4063 if (modeFlags == 0) {
4064 return;
4065 }
4066
Joe Onorato8a9b2202010-02-26 18:56:32 -08004067 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004068 "Requested grant " + targetPkg + " permission to " + uri);
4069
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004070 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004071
4072 // If this is not a content: uri, we can't do anything with it.
4073 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004074 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004075 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004076 return;
4077 }
4078
4079 String name = uri.getAuthority();
4080 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004081 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004082 if (cpr != null) {
4083 pi = cpr.info;
4084 } else {
4085 try {
4086 pi = pm.resolveContentProvider(name,
4087 PackageManager.GET_URI_PERMISSION_PATTERNS);
4088 } catch (RemoteException ex) {
4089 }
4090 }
4091 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004092 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093 return;
4094 }
4095
4096 int targetUid;
4097 try {
4098 targetUid = pm.getPackageUid(targetPkg);
4099 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004100 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004101 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004102 return;
4103 }
4104 } catch (RemoteException ex) {
4105 return;
4106 }
4107
4108 // First... does the target actually need this permission?
4109 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4110 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004111 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004112 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004113 return;
4114 }
4115
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004116 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004117 if (!pi.grantUriPermissions) {
4118 throw new SecurityException("Provider " + pi.packageName
4119 + "/" + pi.name
4120 + " does not allow granting of Uri permissions (uri "
4121 + uri + ")");
4122 }
4123 if (pi.uriPermissionPatterns != null) {
4124 final int N = pi.uriPermissionPatterns.length;
4125 boolean allowed = false;
4126 for (int i=0; i<N; i++) {
4127 if (pi.uriPermissionPatterns[i] != null
4128 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4129 allowed = true;
4130 break;
4131 }
4132 }
4133 if (!allowed) {
4134 throw new SecurityException("Provider " + pi.packageName
4135 + "/" + pi.name
4136 + " does not allow granting of permission to path of Uri "
4137 + uri);
4138 }
4139 }
4140
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004141 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004142 // this uri?
4143 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4144 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4145 throw new SecurityException("Uid " + callingUid
4146 + " does not have permission to uri " + uri);
4147 }
4148 }
4149
4150 // Okay! So here we are: the caller has the assumed permission
4151 // to the uri, and the target doesn't. Let's now give this to
4152 // the target.
4153
Joe Onorato8a9b2202010-02-26 18:56:32 -08004154 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004155 "Granting " + targetPkg + " permission to " + uri);
4156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 HashMap<Uri, UriPermission> targetUris
4158 = mGrantedUriPermissions.get(targetUid);
4159 if (targetUris == null) {
4160 targetUris = new HashMap<Uri, UriPermission>();
4161 mGrantedUriPermissions.put(targetUid, targetUris);
4162 }
4163
4164 UriPermission perm = targetUris.get(uri);
4165 if (perm == null) {
4166 perm = new UriPermission(targetUid, uri);
4167 targetUris.put(uri, perm);
4168
4169 }
4170 perm.modeFlags |= modeFlags;
4171 if (activity == null) {
4172 perm.globalModeFlags |= modeFlags;
4173 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4174 perm.readActivities.add(activity);
4175 if (activity.readUriPermissions == null) {
4176 activity.readUriPermissions = new HashSet<UriPermission>();
4177 }
4178 activity.readUriPermissions.add(perm);
4179 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4180 perm.writeActivities.add(activity);
4181 if (activity.writeUriPermissions == null) {
4182 activity.writeUriPermissions = new HashSet<UriPermission>();
4183 }
4184 activity.writeUriPermissions.add(perm);
4185 }
4186 }
4187
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004188 void grantUriPermissionFromIntentLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004189 String targetPkg, Intent intent, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 if (intent == null) {
4191 return;
4192 }
4193 Uri data = intent.getData();
4194 if (data == null) {
4195 return;
4196 }
4197 grantUriPermissionLocked(callingUid, targetPkg, data,
4198 intent.getFlags(), activity);
4199 }
4200
4201 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4202 Uri uri, int modeFlags) {
4203 synchronized(this) {
4204 final ProcessRecord r = getRecordForAppLocked(caller);
4205 if (r == null) {
4206 throw new SecurityException("Unable to find app for caller "
4207 + caller
4208 + " when granting permission to uri " + uri);
4209 }
4210 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004211 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004212 return;
4213 }
4214 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004215 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004216 return;
4217 }
4218
4219 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4220 null);
4221 }
4222 }
4223
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004224 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4226 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4227 HashMap<Uri, UriPermission> perms
4228 = mGrantedUriPermissions.get(perm.uid);
4229 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004230 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004231 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232 perms.remove(perm.uri);
4233 if (perms.size() == 0) {
4234 mGrantedUriPermissions.remove(perm.uid);
4235 }
4236 }
4237 }
4238 }
4239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4241 int modeFlags) {
4242 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4243 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4244 if (modeFlags == 0) {
4245 return;
4246 }
4247
Joe Onorato8a9b2202010-02-26 18:56:32 -08004248 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004249 "Revoking all granted permissions to " + uri);
4250
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004251 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004252
4253 final String authority = uri.getAuthority();
4254 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004255 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004256 if (cpr != null) {
4257 pi = cpr.info;
4258 } else {
4259 try {
4260 pi = pm.resolveContentProvider(authority,
4261 PackageManager.GET_URI_PERMISSION_PATTERNS);
4262 } catch (RemoteException ex) {
4263 }
4264 }
4265 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004266 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 return;
4268 }
4269
4270 // Does the caller have this permission on the URI?
4271 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4272 // Right now, if you are not the original owner of the permission,
4273 // you are not allowed to revoke it.
4274 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4275 throw new SecurityException("Uid " + callingUid
4276 + " does not have permission to uri " + uri);
4277 //}
4278 }
4279
4280 // Go through all of the permissions and remove any that match.
4281 final List<String> SEGMENTS = uri.getPathSegments();
4282 if (SEGMENTS != null) {
4283 final int NS = SEGMENTS.size();
4284 int N = mGrantedUriPermissions.size();
4285 for (int i=0; i<N; i++) {
4286 HashMap<Uri, UriPermission> perms
4287 = mGrantedUriPermissions.valueAt(i);
4288 Iterator<UriPermission> it = perms.values().iterator();
4289 toploop:
4290 while (it.hasNext()) {
4291 UriPermission perm = it.next();
4292 Uri targetUri = perm.uri;
4293 if (!authority.equals(targetUri.getAuthority())) {
4294 continue;
4295 }
4296 List<String> targetSegments = targetUri.getPathSegments();
4297 if (targetSegments == null) {
4298 continue;
4299 }
4300 if (targetSegments.size() < NS) {
4301 continue;
4302 }
4303 for (int j=0; j<NS; j++) {
4304 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4305 continue toploop;
4306 }
4307 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004308 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004309 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 perm.clearModes(modeFlags);
4311 if (perm.modeFlags == 0) {
4312 it.remove();
4313 }
4314 }
4315 if (perms.size() == 0) {
4316 mGrantedUriPermissions.remove(
4317 mGrantedUriPermissions.keyAt(i));
4318 N--;
4319 i--;
4320 }
4321 }
4322 }
4323 }
4324
4325 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4326 int modeFlags) {
4327 synchronized(this) {
4328 final ProcessRecord r = getRecordForAppLocked(caller);
4329 if (r == null) {
4330 throw new SecurityException("Unable to find app for caller "
4331 + caller
4332 + " when revoking permission to uri " + uri);
4333 }
4334 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004335 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004336 return;
4337 }
4338
4339 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4340 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4341 if (modeFlags == 0) {
4342 return;
4343 }
4344
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004345 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346
4347 final String authority = uri.getAuthority();
4348 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004349 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 if (cpr != null) {
4351 pi = cpr.info;
4352 } else {
4353 try {
4354 pi = pm.resolveContentProvider(authority,
4355 PackageManager.GET_URI_PERMISSION_PATTERNS);
4356 } catch (RemoteException ex) {
4357 }
4358 }
4359 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004360 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004361 return;
4362 }
4363
4364 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4365 }
4366 }
4367
4368 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4369 synchronized (this) {
4370 ProcessRecord app =
4371 who != null ? getRecordForAppLocked(who) : null;
4372 if (app == null) return;
4373
4374 Message msg = Message.obtain();
4375 msg.what = WAIT_FOR_DEBUGGER_MSG;
4376 msg.obj = app;
4377 msg.arg1 = waiting ? 1 : 0;
4378 mHandler.sendMessage(msg);
4379 }
4380 }
4381
4382 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4383 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004384 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004386 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004387 }
4388
4389 // =========================================================
4390 // TASK MANAGEMENT
4391 // =========================================================
4392
4393 public List getTasks(int maxNum, int flags,
4394 IThumbnailReceiver receiver) {
4395 ArrayList list = new ArrayList();
4396
4397 PendingThumbnailsRecord pending = null;
4398 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004399 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004400
4401 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004402 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4404 + ", receiver=" + receiver);
4405
4406 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4407 != PackageManager.PERMISSION_GRANTED) {
4408 if (receiver != null) {
4409 // If the caller wants to wait for pending thumbnails,
4410 // it ain't gonna get them.
4411 try {
4412 receiver.finished();
4413 } catch (RemoteException ex) {
4414 }
4415 }
4416 String msg = "Permission Denial: getTasks() from pid="
4417 + Binder.getCallingPid()
4418 + ", uid=" + Binder.getCallingUid()
4419 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004420 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004421 throw new SecurityException(msg);
4422 }
4423
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004424 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004425 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004426 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004427 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004428 CharSequence topDescription = null;
4429 TaskRecord curTask = null;
4430 int numActivities = 0;
4431 int numRunning = 0;
4432 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004433 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004434 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004435 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436
4437 // Initialize state for next task if needed.
4438 if (top == null ||
4439 (top.state == ActivityState.INITIALIZING
4440 && top.task == r.task)) {
4441 top = r;
4442 topDescription = r.description;
4443 curTask = r.task;
4444 numActivities = numRunning = 0;
4445 }
4446
4447 // Add 'r' into the current task.
4448 numActivities++;
4449 if (r.app != null && r.app.thread != null) {
4450 numRunning++;
4451 }
4452 if (topDescription == null) {
4453 topDescription = r.description;
4454 }
4455
Joe Onorato8a9b2202010-02-26 18:56:32 -08004456 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 TAG, r.intent.getComponent().flattenToShortString()
4458 + ": task=" + r.task);
4459
4460 // If the next one is a different task, generate a new
4461 // TaskInfo entry for what we have.
4462 if (next == null || next.task != curTask) {
4463 ActivityManager.RunningTaskInfo ci
4464 = new ActivityManager.RunningTaskInfo();
4465 ci.id = curTask.taskId;
4466 ci.baseActivity = r.intent.getComponent();
4467 ci.topActivity = top.intent.getComponent();
4468 ci.thumbnail = top.thumbnail;
4469 ci.description = topDescription;
4470 ci.numActivities = numActivities;
4471 ci.numRunning = numRunning;
4472 //System.out.println(
4473 // "#" + maxNum + ": " + " descr=" + ci.description);
4474 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004475 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 TAG, "State=" + top.state + "Idle=" + top.idle
4477 + " app=" + top.app
4478 + " thr=" + (top.app != null ? top.app.thread : null));
4479 if (top.state == ActivityState.RESUMED
4480 || top.state == ActivityState.PAUSING) {
4481 if (top.idle && top.app != null
4482 && top.app.thread != null) {
4483 topRecord = top;
4484 topThumbnail = top.app.thread;
4485 } else {
4486 top.thumbnailNeeded = true;
4487 }
4488 }
4489 if (pending == null) {
4490 pending = new PendingThumbnailsRecord(receiver);
4491 }
4492 pending.pendingRecords.add(top);
4493 }
4494 list.add(ci);
4495 maxNum--;
4496 top = null;
4497 }
4498 }
4499
4500 if (pending != null) {
4501 mPendingThumbnails.add(pending);
4502 }
4503 }
4504
Joe Onorato8a9b2202010-02-26 18:56:32 -08004505 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506
4507 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004508 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004509 try {
4510 topThumbnail.requestThumbnail(topRecord);
4511 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004512 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 sendPendingThumbnail(null, topRecord, null, null, true);
4514 }
4515 }
4516
4517 if (pending == null && receiver != null) {
4518 // In this case all thumbnails were available and the client
4519 // is being asked to be told when the remaining ones come in...
4520 // which is unusually, since the top-most currently running
4521 // activity should never have a canned thumbnail! Oh well.
4522 try {
4523 receiver.finished();
4524 } catch (RemoteException ex) {
4525 }
4526 }
4527
4528 return list;
4529 }
4530
4531 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4532 int flags) {
4533 synchronized (this) {
4534 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4535 "getRecentTasks()");
4536
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004537 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004539 final int N = mRecentTasks.size();
4540 ArrayList<ActivityManager.RecentTaskInfo> res
4541 = new ArrayList<ActivityManager.RecentTaskInfo>(
4542 maxNum < N ? maxNum : N);
4543 for (int i=0; i<N && maxNum > 0; i++) {
4544 TaskRecord tr = mRecentTasks.get(i);
4545 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4546 || (tr.intent == null)
4547 || ((tr.intent.getFlags()
4548 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4549 ActivityManager.RecentTaskInfo rti
4550 = new ActivityManager.RecentTaskInfo();
4551 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4552 rti.baseIntent = new Intent(
4553 tr.intent != null ? tr.intent : tr.affinityIntent);
4554 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004555
4556 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4557 // Check whether this activity is currently available.
4558 try {
4559 if (rti.origActivity != null) {
4560 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4561 continue;
4562 }
4563 } else if (rti.baseIntent != null) {
4564 if (pm.queryIntentActivities(rti.baseIntent,
4565 null, 0) == null) {
4566 continue;
4567 }
4568 }
4569 } catch (RemoteException e) {
4570 // Will never happen.
4571 }
4572 }
4573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004574 res.add(rti);
4575 maxNum--;
4576 }
4577 }
4578 return res;
4579 }
4580 }
4581
4582 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4583 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004584 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 TaskRecord jt = startTask;
4586
4587 // First look backwards
4588 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004589 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004590 if (r.task != jt) {
4591 jt = r.task;
4592 if (affinity.equals(jt.affinity)) {
4593 return j;
4594 }
4595 }
4596 }
4597
4598 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004599 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004600 jt = startTask;
4601 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004602 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 if (r.task != jt) {
4604 if (affinity.equals(jt.affinity)) {
4605 return j;
4606 }
4607 jt = r.task;
4608 }
4609 }
4610
4611 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004612 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004613 return N-1;
4614 }
4615
4616 return -1;
4617 }
4618
4619 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004620 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004621 */
4622 public void moveTaskToFront(int task) {
4623 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4624 "moveTaskToFront()");
4625
4626 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004627 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4628 Binder.getCallingUid(), "Task to front")) {
4629 return;
4630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004631 final long origId = Binder.clearCallingIdentity();
4632 try {
4633 int N = mRecentTasks.size();
4634 for (int i=0; i<N; i++) {
4635 TaskRecord tr = mRecentTasks.get(i);
4636 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004637 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004638 return;
4639 }
4640 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004641 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4642 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004644 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 return;
4646 }
4647 }
4648 } finally {
4649 Binder.restoreCallingIdentity(origId);
4650 }
4651 }
4652 }
4653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004654 public void moveTaskToBack(int task) {
4655 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4656 "moveTaskToBack()");
4657
4658 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004659 if (mMainStack.mResumedActivity != null
4660 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004661 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4662 Binder.getCallingUid(), "Task to back")) {
4663 return;
4664 }
4665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004667 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004668 Binder.restoreCallingIdentity(origId);
4669 }
4670 }
4671
4672 /**
4673 * Moves an activity, and all of the other activities within the same task, to the bottom
4674 * of the history stack. The activity's order within the task is unchanged.
4675 *
4676 * @param token A reference to the activity we wish to move
4677 * @param nonRoot If false then this only works if the activity is the root
4678 * of a task; if true it will work for any activity in a task.
4679 * @return Returns true if the move completed, false if not.
4680 */
4681 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4682 synchronized(this) {
4683 final long origId = Binder.clearCallingIdentity();
4684 int taskId = getTaskForActivityLocked(token, !nonRoot);
4685 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004686 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004687 }
4688 Binder.restoreCallingIdentity(origId);
4689 }
4690 return false;
4691 }
4692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004693 public void moveTaskBackwards(int task) {
4694 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4695 "moveTaskBackwards()");
4696
4697 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004698 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4699 Binder.getCallingUid(), "Task backwards")) {
4700 return;
4701 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 final long origId = Binder.clearCallingIdentity();
4703 moveTaskBackwardsLocked(task);
4704 Binder.restoreCallingIdentity(origId);
4705 }
4706 }
4707
4708 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004709 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004710 }
4711
4712 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4713 synchronized(this) {
4714 return getTaskForActivityLocked(token, onlyRoot);
4715 }
4716 }
4717
4718 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004719 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720 TaskRecord lastTask = null;
4721 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004722 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004723 if (r == token) {
4724 if (!onlyRoot || lastTask != r.task) {
4725 return r.task.taskId;
4726 }
4727 return -1;
4728 }
4729 lastTask = r.task;
4730 }
4731
4732 return -1;
4733 }
4734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004735 public void finishOtherInstances(IBinder token, ComponentName className) {
4736 synchronized(this) {
4737 final long origId = Binder.clearCallingIdentity();
4738
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004739 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 TaskRecord lastTask = null;
4741 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004742 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004743 if (r.realActivity.equals(className)
4744 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004745 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 null, "others")) {
4747 i--;
4748 N--;
4749 }
4750 }
4751 lastTask = r.task;
4752 }
4753
4754 Binder.restoreCallingIdentity(origId);
4755 }
4756 }
4757
4758 // =========================================================
4759 // THUMBNAILS
4760 // =========================================================
4761
4762 public void reportThumbnail(IBinder token,
4763 Bitmap thumbnail, CharSequence description) {
4764 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4765 final long origId = Binder.clearCallingIdentity();
4766 sendPendingThumbnail(null, token, thumbnail, description, true);
4767 Binder.restoreCallingIdentity(origId);
4768 }
4769
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004770 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004771 Bitmap thumbnail, CharSequence description, boolean always) {
4772 TaskRecord task = null;
4773 ArrayList receivers = null;
4774
4775 //System.out.println("Send pending thumbnail: " + r);
4776
4777 synchronized(this) {
4778 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004779 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 if (index < 0) {
4781 return;
4782 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004783 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004784 }
4785 if (thumbnail == null) {
4786 thumbnail = r.thumbnail;
4787 description = r.description;
4788 }
4789 if (thumbnail == null && !always) {
4790 // If there is no thumbnail, and this entry is not actually
4791 // going away, then abort for now and pick up the next
4792 // thumbnail we get.
4793 return;
4794 }
4795 task = r.task;
4796
4797 int N = mPendingThumbnails.size();
4798 int i=0;
4799 while (i<N) {
4800 PendingThumbnailsRecord pr =
4801 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
4802 //System.out.println("Looking in " + pr.pendingRecords);
4803 if (pr.pendingRecords.remove(r)) {
4804 if (receivers == null) {
4805 receivers = new ArrayList();
4806 }
4807 receivers.add(pr);
4808 if (pr.pendingRecords.size() == 0) {
4809 pr.finished = true;
4810 mPendingThumbnails.remove(i);
4811 N--;
4812 continue;
4813 }
4814 }
4815 i++;
4816 }
4817 }
4818
4819 if (receivers != null) {
4820 final int N = receivers.size();
4821 for (int i=0; i<N; i++) {
4822 try {
4823 PendingThumbnailsRecord pr =
4824 (PendingThumbnailsRecord)receivers.get(i);
4825 pr.receiver.newThumbnail(
4826 task != null ? task.taskId : -1, thumbnail, description);
4827 if (pr.finished) {
4828 pr.receiver.finished();
4829 }
4830 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004831 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 }
4833 }
4834 }
4835 }
4836
4837 // =========================================================
4838 // CONTENT PROVIDERS
4839 // =========================================================
4840
4841 private final List generateApplicationProvidersLocked(ProcessRecord app) {
4842 List providers = null;
4843 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004844 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004846 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004847 } catch (RemoteException ex) {
4848 }
4849 if (providers != null) {
4850 final int N = providers.size();
4851 for (int i=0; i<N; i++) {
4852 ProviderInfo cpi =
4853 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004854 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 if (cpr == null) {
4856 cpr = new ContentProviderRecord(cpi, app.info);
4857 mProvidersByClass.put(cpi.name, cpr);
4858 }
4859 app.pubProviders.put(cpi.name, cpr);
4860 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004861 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004862 }
4863 }
4864 return providers;
4865 }
4866
4867 private final String checkContentProviderPermissionLocked(
4868 ProviderInfo cpi, ProcessRecord r, int mode) {
4869 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
4870 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
4871 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
4872 cpi.exported ? -1 : cpi.applicationInfo.uid)
4873 == PackageManager.PERMISSION_GRANTED
4874 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4875 return null;
4876 }
4877 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
4878 cpi.exported ? -1 : cpi.applicationInfo.uid)
4879 == PackageManager.PERMISSION_GRANTED) {
4880 return null;
4881 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004882
4883 PathPermission[] pps = cpi.pathPermissions;
4884 if (pps != null) {
4885 int i = pps.length;
4886 while (i > 0) {
4887 i--;
4888 PathPermission pp = pps[i];
4889 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
4890 cpi.exported ? -1 : cpi.applicationInfo.uid)
4891 == PackageManager.PERMISSION_GRANTED
4892 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4893 return null;
4894 }
4895 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
4896 cpi.exported ? -1 : cpi.applicationInfo.uid)
4897 == PackageManager.PERMISSION_GRANTED) {
4898 return null;
4899 }
4900 }
4901 }
4902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004903 String msg = "Permission Denial: opening provider " + cpi.name
4904 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
4905 + ", uid=" + callingUid + ") requires "
4906 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004907 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 return msg;
4909 }
4910
4911 private final ContentProviderHolder getContentProviderImpl(
4912 IApplicationThread caller, String name) {
4913 ContentProviderRecord cpr;
4914 ProviderInfo cpi = null;
4915
4916 synchronized(this) {
4917 ProcessRecord r = null;
4918 if (caller != null) {
4919 r = getRecordForAppLocked(caller);
4920 if (r == null) {
4921 throw new SecurityException(
4922 "Unable to find app for caller " + caller
4923 + " (pid=" + Binder.getCallingPid()
4924 + ") when getting content provider " + name);
4925 }
4926 }
4927
4928 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07004929 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004930 if (cpr != null) {
4931 cpi = cpr.info;
4932 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
4933 return new ContentProviderHolder(cpi,
4934 cpi.readPermission != null
4935 ? cpi.readPermission : cpi.writePermission);
4936 }
4937
4938 if (r != null && cpr.canRunHere(r)) {
4939 // This provider has been published or is in the process
4940 // of being published... but it is also allowed to run
4941 // in the caller's process, so don't make a connection
4942 // and just let the caller instantiate its own instance.
4943 if (cpr.provider != null) {
4944 // don't give caller the provider object, it needs
4945 // to make its own.
4946 cpr = new ContentProviderRecord(cpr);
4947 }
4948 return cpr;
4949 }
4950
4951 final long origId = Binder.clearCallingIdentity();
4952
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004953 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004954 // return it right away.
4955 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004956 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004957 "Adding provider requested by "
4958 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004959 + cpr.info.processName);
4960 Integer cnt = r.conProviders.get(cpr);
4961 if (cnt == null) {
4962 r.conProviders.put(cpr, new Integer(1));
4963 } else {
4964 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
4965 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004966 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07004967 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
4968 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07004969 // make sure to count it as being accessed and thus
4970 // back up on the LRU list. This is good because
4971 // content providers are often expensive to start.
4972 updateLruProcessLocked(cpr.app, false, true);
4973 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07004974 } else {
4975 cpr.externals++;
4976 }
4977
4978 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004979 updateOomAdjLocked(cpr.app);
4980 }
4981
4982 Binder.restoreCallingIdentity(origId);
4983
4984 } else {
4985 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004986 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07004987 resolveContentProvider(name,
4988 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 } catch (RemoteException ex) {
4990 }
4991 if (cpi == null) {
4992 return null;
4993 }
4994
4995 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
4996 return new ContentProviderHolder(cpi,
4997 cpi.readPermission != null
4998 ? cpi.readPermission : cpi.writePermission);
4999 }
5000
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005001 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5002 && !cpi.processName.equals("system")) {
5003 // If this content provider does not run in the system
5004 // process, and the system is not yet ready to run other
5005 // processes, then fail fast instead of hanging.
5006 throw new IllegalArgumentException(
5007 "Attempt to launch content provider before system ready");
5008 }
5009
Dianne Hackborn860755f2010-06-03 18:47:52 -07005010 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005011 final boolean firstClass = cpr == null;
5012 if (firstClass) {
5013 try {
5014 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005015 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 getApplicationInfo(
5017 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005018 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005019 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005020 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005021 + cpi.name);
5022 return null;
5023 }
5024 cpr = new ContentProviderRecord(cpi, ai);
5025 } catch (RemoteException ex) {
5026 // pm is in same process, this will never happen.
5027 }
5028 }
5029
5030 if (r != null && cpr.canRunHere(r)) {
5031 // If this is a multiprocess provider, then just return its
5032 // info and allow the caller to instantiate it. Only do
5033 // this if the provider is the same user as the caller's
5034 // process, or can run as root (so can be in any process).
5035 return cpr;
5036 }
5037
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005038 if (DEBUG_PROVIDER) {
5039 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005040 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005041 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005042 }
5043
5044 // This is single process, and our app is now connecting to it.
5045 // See if we are already in the process of launching this
5046 // provider.
5047 final int N = mLaunchingProviders.size();
5048 int i;
5049 for (i=0; i<N; i++) {
5050 if (mLaunchingProviders.get(i) == cpr) {
5051 break;
5052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 }
5054
5055 // If the provider is not already being launched, then get it
5056 // started.
5057 if (i >= N) {
5058 final long origId = Binder.clearCallingIdentity();
5059 ProcessRecord proc = startProcessLocked(cpi.processName,
5060 cpr.appInfo, false, 0, "content provider",
5061 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005062 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005064 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 + cpi.applicationInfo.packageName + "/"
5066 + cpi.applicationInfo.uid + " for provider "
5067 + name + ": process is bad");
5068 return null;
5069 }
5070 cpr.launchingApp = proc;
5071 mLaunchingProviders.add(cpr);
5072 Binder.restoreCallingIdentity(origId);
5073 }
5074
5075 // Make sure the provider is published (the same provider class
5076 // may be published under multiple names).
5077 if (firstClass) {
5078 mProvidersByClass.put(cpi.name, cpr);
5079 }
5080 mProvidersByName.put(name, cpr);
5081
5082 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005083 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005084 "Adding provider requested by "
5085 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005086 + cpr.info.processName);
5087 Integer cnt = r.conProviders.get(cpr);
5088 if (cnt == null) {
5089 r.conProviders.put(cpr, new Integer(1));
5090 } else {
5091 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 cpr.clients.add(r);
5094 } else {
5095 cpr.externals++;
5096 }
5097 }
5098 }
5099
5100 // Wait for the provider to be published...
5101 synchronized (cpr) {
5102 while (cpr.provider == null) {
5103 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005104 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 + cpi.applicationInfo.packageName + "/"
5106 + cpi.applicationInfo.uid + " for provider "
5107 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005108 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005109 cpi.applicationInfo.packageName,
5110 cpi.applicationInfo.uid, name);
5111 return null;
5112 }
5113 try {
5114 cpr.wait();
5115 } catch (InterruptedException ex) {
5116 }
5117 }
5118 }
5119 return cpr;
5120 }
5121
5122 public final ContentProviderHolder getContentProvider(
5123 IApplicationThread caller, String name) {
5124 if (caller == null) {
5125 String msg = "null IApplicationThread when getting content provider "
5126 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005127 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 throw new SecurityException(msg);
5129 }
5130
5131 return getContentProviderImpl(caller, name);
5132 }
5133
5134 private ContentProviderHolder getContentProviderExternal(String name) {
5135 return getContentProviderImpl(null, name);
5136 }
5137
5138 /**
5139 * Drop a content provider from a ProcessRecord's bookkeeping
5140 * @param cpr
5141 */
5142 public void removeContentProvider(IApplicationThread caller, String name) {
5143 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005144 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005146 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005147 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005148 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 return;
5150 }
5151 final ProcessRecord r = getRecordForAppLocked(caller);
5152 if (r == null) {
5153 throw new SecurityException(
5154 "Unable to find app for caller " + caller +
5155 " when removing content provider " + name);
5156 }
5157 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005158 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005159 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005160 + r.info.processName + " from process "
5161 + localCpr.appInfo.processName);
5162 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005163 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005164 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005165 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005166 return;
5167 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005168 Integer cnt = r.conProviders.get(localCpr);
5169 if (cnt == null || cnt.intValue() <= 1) {
5170 localCpr.clients.remove(r);
5171 r.conProviders.remove(localCpr);
5172 } else {
5173 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175 }
5176 updateOomAdjLocked();
5177 }
5178 }
5179
5180 private void removeContentProviderExternal(String name) {
5181 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005182 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005183 if(cpr == null) {
5184 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005185 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 return;
5187 }
5188
5189 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005190 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 localCpr.externals--;
5192 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005193 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005194 }
5195 updateOomAdjLocked();
5196 }
5197 }
5198
5199 public final void publishContentProviders(IApplicationThread caller,
5200 List<ContentProviderHolder> providers) {
5201 if (providers == null) {
5202 return;
5203 }
5204
5205 synchronized(this) {
5206 final ProcessRecord r = getRecordForAppLocked(caller);
5207 if (r == null) {
5208 throw new SecurityException(
5209 "Unable to find app for caller " + caller
5210 + " (pid=" + Binder.getCallingPid()
5211 + ") when publishing content providers");
5212 }
5213
5214 final long origId = Binder.clearCallingIdentity();
5215
5216 final int N = providers.size();
5217 for (int i=0; i<N; i++) {
5218 ContentProviderHolder src = providers.get(i);
5219 if (src == null || src.info == null || src.provider == null) {
5220 continue;
5221 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005222 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223 if (dst != null) {
5224 mProvidersByClass.put(dst.info.name, dst);
5225 String names[] = dst.info.authority.split(";");
5226 for (int j = 0; j < names.length; j++) {
5227 mProvidersByName.put(names[j], dst);
5228 }
5229
5230 int NL = mLaunchingProviders.size();
5231 int j;
5232 for (j=0; j<NL; j++) {
5233 if (mLaunchingProviders.get(j) == dst) {
5234 mLaunchingProviders.remove(j);
5235 j--;
5236 NL--;
5237 }
5238 }
5239 synchronized (dst) {
5240 dst.provider = src.provider;
5241 dst.app = r;
5242 dst.notifyAll();
5243 }
5244 updateOomAdjLocked(r);
5245 }
5246 }
5247
5248 Binder.restoreCallingIdentity(origId);
5249 }
5250 }
5251
5252 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005253 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005254 synchronized (mSelf) {
5255 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5256 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005257 if (providers != null) {
5258 for (int i=providers.size()-1; i>=0; i--) {
5259 ProviderInfo pi = (ProviderInfo)providers.get(i);
5260 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5261 Slog.w(TAG, "Not installing system proc provider " + pi.name
5262 + ": not system .apk");
5263 providers.remove(i);
5264 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005265 }
5266 }
5267 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005268 if (providers != null) {
5269 mSystemThread.installSystemProviders(providers);
5270 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 }
5272
5273 // =========================================================
5274 // GLOBAL MANAGEMENT
5275 // =========================================================
5276
5277 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5278 ApplicationInfo info, String customProcess) {
5279 String proc = customProcess != null ? customProcess : info.processName;
5280 BatteryStatsImpl.Uid.Proc ps = null;
5281 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5282 synchronized (stats) {
5283 ps = stats.getProcessStatsLocked(info.uid, proc);
5284 }
5285 return new ProcessRecord(ps, thread, info, proc);
5286 }
5287
5288 final ProcessRecord addAppLocked(ApplicationInfo info) {
5289 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5290
5291 if (app == null) {
5292 app = newProcessRecordLocked(null, info, null);
5293 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005294 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 }
5296
5297 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5298 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5299 app.persistent = true;
5300 app.maxAdj = CORE_SERVER_ADJ;
5301 }
5302 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5303 mPersistentStartingProcesses.add(app);
5304 startProcessLocked(app, "added application", app.processName);
5305 }
5306
5307 return app;
5308 }
5309
5310 public void unhandledBack() {
5311 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5312 "unhandledBack()");
5313
5314 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005315 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005316 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 TAG, "Performing unhandledBack(): stack size = " + count);
5318 if (count > 1) {
5319 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005320 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5322 Binder.restoreCallingIdentity(origId);
5323 }
5324 }
5325 }
5326
5327 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5328 String name = uri.getAuthority();
5329 ContentProviderHolder cph = getContentProviderExternal(name);
5330 ParcelFileDescriptor pfd = null;
5331 if (cph != null) {
5332 // We record the binder invoker's uid in thread-local storage before
5333 // going to the content provider to open the file. Later, in the code
5334 // that handles all permissions checks, we look for this uid and use
5335 // that rather than the Activity Manager's own uid. The effect is that
5336 // we do the check against the caller's permissions even though it looks
5337 // to the content provider like the Activity Manager itself is making
5338 // the request.
5339 sCallerIdentity.set(new Identity(
5340 Binder.getCallingPid(), Binder.getCallingUid()));
5341 try {
5342 pfd = cph.provider.openFile(uri, "r");
5343 } catch (FileNotFoundException e) {
5344 // do nothing; pfd will be returned null
5345 } finally {
5346 // Ensure that whatever happens, we clean up the identity state
5347 sCallerIdentity.remove();
5348 }
5349
5350 // We've got the fd now, so we're done with the provider.
5351 removeContentProviderExternal(name);
5352 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005353 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 }
5355 return pfd;
5356 }
5357
5358 public void goingToSleep() {
5359 synchronized(this) {
5360 mSleeping = true;
5361 mWindowManager.setEventDispatching(false);
5362
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005363 if (mMainStack.mResumedActivity != null) {
5364 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005366 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005367 }
5368 }
5369 }
5370
Dianne Hackborn55280a92009-05-07 15:53:46 -07005371 public boolean shutdown(int timeout) {
5372 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5373 != PackageManager.PERMISSION_GRANTED) {
5374 throw new SecurityException("Requires permission "
5375 + android.Manifest.permission.SHUTDOWN);
5376 }
5377
5378 boolean timedout = false;
5379
5380 synchronized(this) {
5381 mShuttingDown = true;
5382 mWindowManager.setEventDispatching(false);
5383
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005384 if (mMainStack.mResumedActivity != null) {
5385 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005386 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005387 while (mMainStack.mResumedActivity != null
5388 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005389 long delay = endTime - System.currentTimeMillis();
5390 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005391 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005392 timedout = true;
5393 break;
5394 }
5395 try {
5396 this.wait();
5397 } catch (InterruptedException e) {
5398 }
5399 }
5400 }
5401 }
5402
5403 mUsageStatsService.shutdown();
5404 mBatteryStatsService.shutdown();
5405
5406 return timedout;
5407 }
5408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005409 public void wakingUp() {
5410 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005411 if (mMainStack.mGoingToSleep.isHeld()) {
5412 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005413 }
5414 mWindowManager.setEventDispatching(true);
5415 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005416 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005417 }
5418 }
5419
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005420 public void stopAppSwitches() {
5421 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5422 != PackageManager.PERMISSION_GRANTED) {
5423 throw new SecurityException("Requires permission "
5424 + android.Manifest.permission.STOP_APP_SWITCHES);
5425 }
5426
5427 synchronized(this) {
5428 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5429 + APP_SWITCH_DELAY_TIME;
5430 mDidAppSwitch = false;
5431 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5432 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5433 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5434 }
5435 }
5436
5437 public void resumeAppSwitches() {
5438 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5439 != PackageManager.PERMISSION_GRANTED) {
5440 throw new SecurityException("Requires permission "
5441 + android.Manifest.permission.STOP_APP_SWITCHES);
5442 }
5443
5444 synchronized(this) {
5445 // Note that we don't execute any pending app switches... we will
5446 // let those wait until either the timeout, or the next start
5447 // activity request.
5448 mAppSwitchesAllowedTime = 0;
5449 }
5450 }
5451
5452 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5453 String name) {
5454 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5455 return true;
5456 }
5457
5458 final int perm = checkComponentPermission(
5459 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5460 callingUid, -1);
5461 if (perm == PackageManager.PERMISSION_GRANTED) {
5462 return true;
5463 }
5464
Joe Onorato8a9b2202010-02-26 18:56:32 -08005465 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005466 return false;
5467 }
5468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 public void setDebugApp(String packageName, boolean waitForDebugger,
5470 boolean persistent) {
5471 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5472 "setDebugApp()");
5473
5474 // Note that this is not really thread safe if there are multiple
5475 // callers into it at the same time, but that's not a situation we
5476 // care about.
5477 if (persistent) {
5478 final ContentResolver resolver = mContext.getContentResolver();
5479 Settings.System.putString(
5480 resolver, Settings.System.DEBUG_APP,
5481 packageName);
5482 Settings.System.putInt(
5483 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5484 waitForDebugger ? 1 : 0);
5485 }
5486
5487 synchronized (this) {
5488 if (!persistent) {
5489 mOrigDebugApp = mDebugApp;
5490 mOrigWaitForDebugger = mWaitForDebugger;
5491 }
5492 mDebugApp = packageName;
5493 mWaitForDebugger = waitForDebugger;
5494 mDebugTransient = !persistent;
5495 if (packageName != null) {
5496 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005497 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 Binder.restoreCallingIdentity(origId);
5499 }
5500 }
5501 }
5502
5503 public void setAlwaysFinish(boolean enabled) {
5504 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5505 "setAlwaysFinish()");
5506
5507 Settings.System.putInt(
5508 mContext.getContentResolver(),
5509 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5510
5511 synchronized (this) {
5512 mAlwaysFinishActivities = enabled;
5513 }
5514 }
5515
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005516 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005517 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005518 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005520 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521 }
5522 }
5523
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005524 public boolean isUserAMonkey() {
5525 // For now the fact that there is a controller implies
5526 // we have a monkey.
5527 synchronized (this) {
5528 return mController != null;
5529 }
5530 }
5531
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005532 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005533 synchronized (this) {
5534 mWatchers.register(watcher);
5535 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005536 }
5537
5538 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005539 synchronized (this) {
5540 mWatchers.unregister(watcher);
5541 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005542 }
5543
Daniel Sandler69a48172010-06-23 16:29:36 -04005544 public void setImmersive(IBinder token, boolean immersive) {
5545 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005546 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005547 if (index < 0) {
5548 throw new IllegalArgumentException();
5549 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005550 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005551 r.immersive = immersive;
5552 }
5553 }
5554
5555 public boolean isImmersive(IBinder token) {
5556 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005557 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005558 if (index < 0) {
5559 throw new IllegalArgumentException();
5560 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005561 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005562 return r.immersive;
5563 }
5564 }
5565
5566 public boolean isTopActivityImmersive() {
5567 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005568 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005569 return (r != null) ? r.immersive : false;
5570 }
5571 }
5572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005573 public final void enterSafeMode() {
5574 synchronized(this) {
5575 // It only makes sense to do this before the system is ready
5576 // and started launching other packages.
5577 if (!mSystemReady) {
5578 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005579 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005580 } catch (RemoteException e) {
5581 }
5582
5583 View v = LayoutInflater.from(mContext).inflate(
5584 com.android.internal.R.layout.safe_mode, null);
5585 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5586 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5587 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5588 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5589 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5590 lp.format = v.getBackground().getOpacity();
5591 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5592 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5593 ((WindowManager)mContext.getSystemService(
5594 Context.WINDOW_SERVICE)).addView(v, lp);
5595 }
5596 }
5597 }
5598
5599 public void noteWakeupAlarm(IIntentSender sender) {
5600 if (!(sender instanceof PendingIntentRecord)) {
5601 return;
5602 }
5603 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5604 synchronized (stats) {
5605 if (mBatteryStatsService.isOnBattery()) {
5606 mBatteryStatsService.enforceCallingPermission();
5607 PendingIntentRecord rec = (PendingIntentRecord)sender;
5608 int MY_UID = Binder.getCallingUid();
5609 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5610 BatteryStatsImpl.Uid.Pkg pkg =
5611 stats.getPackageStatsLocked(uid, rec.key.packageName);
5612 pkg.incWakeupsLocked();
5613 }
5614 }
5615 }
5616
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005617 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005618 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005619 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005621 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 // XXX Note: don't acquire main activity lock here, because the window
5623 // manager calls in with its locks held.
5624
5625 boolean killed = false;
5626 synchronized (mPidsSelfLocked) {
5627 int[] types = new int[pids.length];
5628 int worstType = 0;
5629 for (int i=0; i<pids.length; i++) {
5630 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5631 if (proc != null) {
5632 int type = proc.setAdj;
5633 types[i] = type;
5634 if (type > worstType) {
5635 worstType = type;
5636 }
5637 }
5638 }
5639
5640 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5641 // then constrain it so we will kill all hidden procs.
5642 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5643 worstType = HIDDEN_APP_MIN_ADJ;
5644 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005645 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005646 for (int i=0; i<pids.length; i++) {
5647 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5648 if (proc == null) {
5649 continue;
5650 }
5651 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005652 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005653 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005654 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5655 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005656 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005657 proc.killedBackground = true;
5658 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005659 }
5660 }
5661 }
5662 return killed;
5663 }
5664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005665 public final void startRunning(String pkg, String cls, String action,
5666 String data) {
5667 synchronized(this) {
5668 if (mStartRunning) {
5669 return;
5670 }
5671 mStartRunning = true;
5672 mTopComponent = pkg != null && cls != null
5673 ? new ComponentName(pkg, cls) : null;
5674 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5675 mTopData = data;
5676 if (!mSystemReady) {
5677 return;
5678 }
5679 }
5680
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005681 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 }
5683
5684 private void retrieveSettings() {
5685 final ContentResolver resolver = mContext.getContentResolver();
5686 String debugApp = Settings.System.getString(
5687 resolver, Settings.System.DEBUG_APP);
5688 boolean waitForDebugger = Settings.System.getInt(
5689 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5690 boolean alwaysFinishActivities = Settings.System.getInt(
5691 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5692
5693 Configuration configuration = new Configuration();
5694 Settings.System.getConfiguration(resolver, configuration);
5695
5696 synchronized (this) {
5697 mDebugApp = mOrigDebugApp = debugApp;
5698 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5699 mAlwaysFinishActivities = alwaysFinishActivities;
5700 // This happens before any activities are started, so we can
5701 // change mConfiguration in-place.
5702 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005703 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005704 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005705 }
5706 }
5707
5708 public boolean testIsSystemReady() {
5709 // no need to synchronize(this) just to read & return the value
5710 return mSystemReady;
5711 }
5712
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005713 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 // In the simulator, startRunning will never have been called, which
5715 // normally sets a few crucial variables. Do it here instead.
5716 if (!Process.supportsProcesses()) {
5717 mStartRunning = true;
5718 mTopAction = Intent.ACTION_MAIN;
5719 }
5720
5721 synchronized(this) {
5722 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005723 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 return;
5725 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005726
5727 // Check to see if there are any update receivers to run.
5728 if (!mDidUpdate) {
5729 if (mWaitingUpdate) {
5730 return;
5731 }
5732 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5733 List<ResolveInfo> ris = null;
5734 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005735 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005736 intent, null, 0);
5737 } catch (RemoteException e) {
5738 }
5739 if (ris != null) {
5740 for (int i=ris.size()-1; i>=0; i--) {
5741 if ((ris.get(i).activityInfo.applicationInfo.flags
5742 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5743 ris.remove(i);
5744 }
5745 }
5746 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5747 for (int i=0; i<ris.size(); i++) {
5748 ActivityInfo ai = ris.get(i).activityInfo;
5749 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5750 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005751 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005752 finisher = new IIntentReceiver.Stub() {
5753 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005754 String data, Bundle extras, boolean ordered,
5755 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005756 throws RemoteException {
5757 synchronized (ActivityManagerService.this) {
5758 mDidUpdate = true;
5759 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005760 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005761 }
5762 };
5763 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005764 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005765 broadcastIntentLocked(null, null, intent, null, finisher,
5766 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005767 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005768 mWaitingUpdate = true;
5769 }
5770 }
5771 }
5772 if (mWaitingUpdate) {
5773 return;
5774 }
5775 mDidUpdate = true;
5776 }
5777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005778 mSystemReady = true;
5779 if (!mStartRunning) {
5780 return;
5781 }
5782 }
5783
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005784 ArrayList<ProcessRecord> procsToKill = null;
5785 synchronized(mPidsSelfLocked) {
5786 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5787 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5788 if (!isAllowedWhileBooting(proc.info)){
5789 if (procsToKill == null) {
5790 procsToKill = new ArrayList<ProcessRecord>();
5791 }
5792 procsToKill.add(proc);
5793 }
5794 }
5795 }
5796
5797 if (procsToKill != null) {
5798 synchronized(this) {
5799 for (int i=procsToKill.size()-1; i>=0; i--) {
5800 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005801 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005802 removeProcessLocked(proc, true);
5803 }
5804 }
5805 }
5806
Joe Onorato8a9b2202010-02-26 18:56:32 -08005807 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005808 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005809 SystemClock.uptimeMillis());
5810
5811 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005812 // Make sure we have no pre-ready processes sitting around.
5813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005814 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
5815 ResolveInfo ri = mContext.getPackageManager()
5816 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07005817 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818 CharSequence errorMsg = null;
5819 if (ri != null) {
5820 ActivityInfo ai = ri.activityInfo;
5821 ApplicationInfo app = ai.applicationInfo;
5822 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5823 mTopAction = Intent.ACTION_FACTORY_TEST;
5824 mTopData = null;
5825 mTopComponent = new ComponentName(app.packageName,
5826 ai.name);
5827 } else {
5828 errorMsg = mContext.getResources().getText(
5829 com.android.internal.R.string.factorytest_not_system);
5830 }
5831 } else {
5832 errorMsg = mContext.getResources().getText(
5833 com.android.internal.R.string.factorytest_no_action);
5834 }
5835 if (errorMsg != null) {
5836 mTopAction = null;
5837 mTopData = null;
5838 mTopComponent = null;
5839 Message msg = Message.obtain();
5840 msg.what = SHOW_FACTORY_ERROR_MSG;
5841 msg.getData().putCharSequence("msg", errorMsg);
5842 mHandler.sendMessage(msg);
5843 }
5844 }
5845 }
5846
5847 retrieveSettings();
5848
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005849 if (goingCallback != null) goingCallback.run();
5850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 synchronized (this) {
5852 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5853 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005854 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005855 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005856 if (apps != null) {
5857 int N = apps.size();
5858 int i;
5859 for (i=0; i<N; i++) {
5860 ApplicationInfo info
5861 = (ApplicationInfo)apps.get(i);
5862 if (info != null &&
5863 !info.packageName.equals("android")) {
5864 addAppLocked(info);
5865 }
5866 }
5867 }
5868 } catch (RemoteException ex) {
5869 // pm is in same process, this will never happen.
5870 }
5871 }
5872
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005873 // Start up initial activity.
5874 mBooting = true;
5875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005876 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005877 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 Message msg = Message.obtain();
5879 msg.what = SHOW_UID_ERROR_MSG;
5880 mHandler.sendMessage(msg);
5881 }
5882 } catch (RemoteException e) {
5883 }
5884
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005885 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005886 }
5887 }
5888
Dan Egnorb7f03672009-12-09 16:22:32 -08005889 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005890 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005891 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005892 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005893 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005894 startAppProblemLocked(app);
5895 app.stopFreezingAllLocked();
5896 return handleAppCrashLocked(app);
5897 }
5898
Dan Egnorb7f03672009-12-09 16:22:32 -08005899 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005900 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005901 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005902 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005903 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
5904 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005905 startAppProblemLocked(app);
5906 app.stopFreezingAllLocked();
5907 }
5908
5909 /**
5910 * Generate a process error record, suitable for attachment to a ProcessRecord.
5911 *
5912 * @param app The ProcessRecord in which the error occurred.
5913 * @param condition Crashing, Application Not Responding, etc. Values are defined in
5914 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08005915 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005916 * @param shortMsg Short message describing the crash.
5917 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08005918 * @param stackTrace Full crash stack trace, may be null.
5919 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005920 * @return Returns a fully-formed AppErrorStateInfo record.
5921 */
5922 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005923 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005924 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08005925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005926 report.condition = condition;
5927 report.processName = app.processName;
5928 report.pid = app.pid;
5929 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08005930 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 report.shortMsg = shortMsg;
5932 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08005933 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005934
5935 return report;
5936 }
5937
Dan Egnor42471dd2010-01-07 17:25:22 -08005938 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005939 synchronized (this) {
5940 app.crashing = false;
5941 app.crashingReport = null;
5942 app.notResponding = false;
5943 app.notRespondingReport = null;
5944 if (app.anrDialog == fromDialog) {
5945 app.anrDialog = null;
5946 }
5947 if (app.waitDialog == fromDialog) {
5948 app.waitDialog = null;
5949 }
5950 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005951 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07005952 Slog.i(ActivityManagerService.TAG, "Killing "
5953 + app.processName + " (pid=" + app.pid + "): user's request");
5954 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
5955 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005956 Process.killProcess(app.pid);
5957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005958 }
5959 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005960
Dan Egnorb7f03672009-12-09 16:22:32 -08005961 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 long now = SystemClock.uptimeMillis();
5963
5964 Long crashTime = mProcessCrashTimes.get(app.info.processName,
5965 app.info.uid);
5966 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
5967 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005968 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005969 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005970 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005971 app.info.processName, app.info.uid);
5972 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005973 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5974 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005975 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005976 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005977 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005978 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005979 }
5980 }
5981 if (!app.persistent) {
5982 // We don't want to start this process again until the user
5983 // explicitly does so... but for persistent process, we really
5984 // need to keep it running. If a persistent process is actually
5985 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08005986 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005987 app.info.processName);
5988 mBadProcesses.put(app.info.processName, app.info.uid, now);
5989 app.bad = true;
5990 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
5991 app.removed = true;
5992 removeProcessLocked(app, false);
5993 return false;
5994 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07005995 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005996 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07005997 if (r.app == app) {
5998 // If the top running activity is from this crashing
5999 // process, then terminate it to avoid getting in a loop.
6000 Slog.w(TAG, " Force finishing activity "
6001 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006002 int index = mMainStack.indexOfTokenLocked(r);
6003 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006004 Activity.RESULT_CANCELED, null, "crashed");
6005 // Also terminate an activities below it that aren't yet
6006 // stopped, to avoid a situation where one will get
6007 // re-start our crashing activity once it gets resumed again.
6008 index--;
6009 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006010 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006011 if (r.state == ActivityState.RESUMED
6012 || r.state == ActivityState.PAUSING
6013 || r.state == ActivityState.PAUSED) {
6014 if (!r.isHomeActivity) {
6015 Slog.w(TAG, " Force finishing activity "
6016 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006017 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006018 Activity.RESULT_CANCELED, null, "crashed");
6019 }
6020 }
6021 }
6022 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006023 }
6024
6025 // Bump up the crash count of any services currently running in the proc.
6026 if (app.services.size() != 0) {
6027 // Any services running in the application need to be placed
6028 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006029 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006030 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006031 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 sr.crashCount++;
6033 }
6034 }
6035
6036 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6037 return true;
6038 }
6039
6040 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006041 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6042 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 skipCurrentReceiverLocked(app);
6044 }
6045
6046 void skipCurrentReceiverLocked(ProcessRecord app) {
6047 boolean reschedule = false;
6048 BroadcastRecord r = app.curReceiver;
6049 if (r != null) {
6050 // The current broadcast is waiting for this app's receiver
6051 // to be finished. Looks like that's not going to happen, so
6052 // let the broadcast continue.
6053 logBroadcastReceiverDiscard(r);
6054 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6055 r.resultExtras, r.resultAbort, true);
6056 reschedule = true;
6057 }
6058 r = mPendingBroadcast;
6059 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006060 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006061 "skip & discard pending app " + r);
6062 logBroadcastReceiverDiscard(r);
6063 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6064 r.resultExtras, r.resultAbort, true);
6065 reschedule = true;
6066 }
6067 if (reschedule) {
6068 scheduleBroadcastsLocked();
6069 }
6070 }
6071
Dan Egnor60d87622009-12-16 16:32:58 -08006072 /**
6073 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6074 * The application process will exit immediately after this call returns.
6075 * @param app object of the crashing app, null for the system server
6076 * @param crashInfo describing the exception
6077 */
6078 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6079 ProcessRecord r = findAppProcess(app);
6080
6081 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6082 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006083 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006084 crashInfo.exceptionClassName,
6085 crashInfo.exceptionMessage,
6086 crashInfo.throwFileName,
6087 crashInfo.throwLineNumber);
6088
Dan Egnor42471dd2010-01-07 17:25:22 -08006089 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006090
6091 crashApplication(r, crashInfo);
6092 }
6093
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006094 public void handleApplicationStrictModeViolation(
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006095 IBinder app, int violationMask, ApplicationErrorReport.CrashInfo crashInfo) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006096 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006097
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006098 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006099 Integer stackFingerprint = crashInfo.stackTrace.hashCode();
6100 boolean logIt = true;
6101 synchronized (mAlreadyLoggedViolatedStacks) {
6102 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6103 logIt = false;
6104 // TODO: sub-sample into EventLog for these, with
6105 // the crashInfo.durationMillis? Then we'd get
6106 // the relative pain numbers, without logging all
6107 // the stack traces repeatedly. We'd want to do
6108 // likewise in the client code, which also does
6109 // dup suppression, before the Binder call.
6110 } else {
6111 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6112 mAlreadyLoggedViolatedStacks.clear();
6113 }
6114 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6115 }
6116 }
6117 if (logIt) {
6118 addErrorToDropBox("strictmode", r, null, null, null, null, null, crashInfo);
6119 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006120 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006121
6122 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6123 AppErrorResult result = new AppErrorResult();
6124 synchronized (this) {
6125 final long origId = Binder.clearCallingIdentity();
6126
6127 Message msg = Message.obtain();
6128 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6129 HashMap<String, Object> data = new HashMap<String, Object>();
6130 data.put("result", result);
6131 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006132 data.put("violationMask", violationMask);
6133 data.put("crashInfo", crashInfo);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006134 msg.obj = data;
6135 mHandler.sendMessage(msg);
6136
6137 Binder.restoreCallingIdentity(origId);
6138 }
6139 int res = result.get();
6140 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
6141 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006142 }
6143
Dan Egnor60d87622009-12-16 16:32:58 -08006144 /**
6145 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6146 * @param app object of the crashing app, null for the system server
6147 * @param tag reported by the caller
6148 * @param crashInfo describing the context of the error
6149 * @return true if the process should exit immediately (WTF is fatal)
6150 */
6151 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006152 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006153 ProcessRecord r = findAppProcess(app);
6154
6155 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6156 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006157 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006158 tag, crashInfo.exceptionMessage);
6159
Dan Egnor42471dd2010-01-07 17:25:22 -08006160 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006161
Doug Zongker43866e02010-01-07 12:09:54 -08006162 if (Settings.Secure.getInt(mContext.getContentResolver(),
6163 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006164 crashApplication(r, crashInfo);
6165 return true;
6166 } else {
6167 return false;
6168 }
6169 }
6170
6171 /**
6172 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6173 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6174 */
6175 private ProcessRecord findAppProcess(IBinder app) {
6176 if (app == null) {
6177 return null;
6178 }
6179
6180 synchronized (this) {
6181 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6182 final int NA = apps.size();
6183 for (int ia=0; ia<NA; ia++) {
6184 ProcessRecord p = apps.valueAt(ia);
6185 if (p.thread != null && p.thread.asBinder() == app) {
6186 return p;
6187 }
6188 }
6189 }
6190
Joe Onorato8a9b2202010-02-26 18:56:32 -08006191 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006192 return null;
6193 }
6194 }
6195
6196 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08006197 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08006198 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08006199 * @param process which caused the error, null means the system server
6200 * @param activity which triggered the error, null if unknown
6201 * @param parent activity related to the error, null if unknown
6202 * @param subject line related to the error, null if absent
6203 * @param report in long form describing the error, null if absent
6204 * @param logFile to include in the report, null if none
6205 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08006206 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08006207 public void addErrorToDropBox(String eventType,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006208 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
Dan Egnora455d192010-03-12 08:52:28 -08006209 final String report, final File logFile,
6210 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08006211 // NOTE -- this must never acquire the ActivityManagerService lock,
6212 // otherwise the watchdog may be prevented from resetting the system.
6213
Dan Egnora455d192010-03-12 08:52:28 -08006214 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08006215 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08006216 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08006217 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08006218 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08006219 } else {
Dan Egnora455d192010-03-12 08:52:28 -08006220 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08006221 }
6222
Dan Egnora455d192010-03-12 08:52:28 -08006223 final String dropboxTag = prefix + eventType;
6224 final DropBoxManager dbox = (DropBoxManager)
6225 mContext.getSystemService(Context.DROPBOX_SERVICE);
6226
6227 // Exit early if the dropbox isn't configured to accept this report type.
6228 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6229
6230 final StringBuilder sb = new StringBuilder(1024);
6231 if (process == null || process.pid == MY_PID) {
6232 sb.append("Process: system_server\n");
6233 } else {
6234 sb.append("Process: ").append(process.processName).append("\n");
6235 }
6236 if (process != null) {
6237 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006238 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006239 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6240 for (String pkg : process.pkgList) {
6241 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006242 try {
Dan Egnora455d192010-03-12 08:52:28 -08006243 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6244 if (pi != null) {
6245 sb.append(" v").append(pi.versionCode);
6246 if (pi.versionName != null) {
6247 sb.append(" (").append(pi.versionName).append(")");
6248 }
6249 }
6250 } catch (RemoteException e) {
6251 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006252 }
Dan Egnora455d192010-03-12 08:52:28 -08006253 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006254 }
Dan Egnora455d192010-03-12 08:52:28 -08006255 }
6256 if (activity != null) {
6257 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6258 }
6259 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6260 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6261 }
6262 if (parent != null && parent != activity) {
6263 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6264 }
6265 if (subject != null) {
6266 sb.append("Subject: ").append(subject).append("\n");
6267 }
6268 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Brad Fitzpatrick04b243d2010-06-21 08:01:13 -07006269 if (crashInfo != null && crashInfo.durationMillis != -1) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006270 sb.append("Duration-Millis: ").append(crashInfo.durationMillis).append("\n");
6271 }
Dan Egnora455d192010-03-12 08:52:28 -08006272 sb.append("\n");
6273
6274 // Do the rest in a worker thread to avoid blocking the caller on I/O
6275 // (After this point, we shouldn't access AMS internal data structures.)
6276 Thread worker = new Thread("Error dump: " + dropboxTag) {
6277 @Override
6278 public void run() {
6279 if (report != null) {
6280 sb.append(report);
6281 }
6282 if (logFile != null) {
6283 try {
6284 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6285 } catch (IOException e) {
6286 Slog.e(TAG, "Error reading " + logFile, e);
6287 }
6288 }
6289 if (crashInfo != null && crashInfo.stackTrace != null) {
6290 sb.append(crashInfo.stackTrace);
6291 }
6292
6293 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6294 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6295 if (lines > 0) {
6296 sb.append("\n");
6297
6298 // Merge several logcat streams, and take the last N lines
6299 InputStreamReader input = null;
6300 try {
6301 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6302 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6303 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6304
6305 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6306 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6307 input = new InputStreamReader(logcat.getInputStream());
6308
6309 int num;
6310 char[] buf = new char[8192];
6311 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6312 } catch (IOException e) {
6313 Slog.e(TAG, "Error running logcat", e);
6314 } finally {
6315 if (input != null) try { input.close(); } catch (IOException e) {}
6316 }
6317 }
6318
6319 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006320 }
Dan Egnora455d192010-03-12 08:52:28 -08006321 };
6322
6323 if (process == null || process.pid == MY_PID) {
6324 worker.run(); // We may be about to die -- need to run this synchronously
6325 } else {
6326 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006327 }
6328 }
6329
6330 /**
6331 * Bring up the "unexpected error" dialog box for a crashing app.
6332 * Deal with edge cases (intercepts from instrumented applications,
6333 * ActivityController, error intent receivers, that sort of thing).
6334 * @param r the application crashing
6335 * @param crashInfo describing the failure
6336 */
6337 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006338 long timeMillis = System.currentTimeMillis();
6339 String shortMsg = crashInfo.exceptionClassName;
6340 String longMsg = crashInfo.exceptionMessage;
6341 String stackTrace = crashInfo.stackTrace;
6342 if (shortMsg != null && longMsg != null) {
6343 longMsg = shortMsg + ": " + longMsg;
6344 } else if (shortMsg != null) {
6345 longMsg = shortMsg;
6346 }
6347
Dan Egnor60d87622009-12-16 16:32:58 -08006348 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006349 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006350 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 try {
6352 String name = r != null ? r.processName : null;
6353 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006354 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006355 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006356 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006357 + " at watcher's request");
6358 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006359 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006360 }
6361 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006362 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 }
6364 }
6365
6366 final long origId = Binder.clearCallingIdentity();
6367
6368 // If this process is running instrumentation, finish it.
6369 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006370 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006371 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006372 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6373 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 Bundle info = new Bundle();
6375 info.putString("shortMsg", shortMsg);
6376 info.putString("longMsg", longMsg);
6377 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6378 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006379 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 }
6381
Dan Egnor60d87622009-12-16 16:32:58 -08006382 // If we can't identify the process or it's already exceeded its crash quota,
6383 // quit right away without showing a crash dialog.
6384 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006385 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006386 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006387 }
6388
6389 Message msg = Message.obtain();
6390 msg.what = SHOW_ERROR_MSG;
6391 HashMap data = new HashMap();
6392 data.put("result", result);
6393 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006394 msg.obj = data;
6395 mHandler.sendMessage(msg);
6396
6397 Binder.restoreCallingIdentity(origId);
6398 }
6399
6400 int res = result.get();
6401
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006402 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006403 synchronized (this) {
6404 if (r != null) {
6405 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6406 SystemClock.uptimeMillis());
6407 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006408 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006409 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006410 }
6411 }
6412
6413 if (appErrorIntent != null) {
6414 try {
6415 mContext.startActivity(appErrorIntent);
6416 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006417 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006421
6422 Intent createAppErrorIntentLocked(ProcessRecord r,
6423 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6424 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006425 if (report == null) {
6426 return null;
6427 }
6428 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6429 result.setComponent(r.errorReportReceiver);
6430 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6431 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6432 return result;
6433 }
6434
Dan Egnorb7f03672009-12-09 16:22:32 -08006435 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6436 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006437 if (r.errorReportReceiver == null) {
6438 return null;
6439 }
6440
6441 if (!r.crashing && !r.notResponding) {
6442 return null;
6443 }
6444
Dan Egnorb7f03672009-12-09 16:22:32 -08006445 ApplicationErrorReport report = new ApplicationErrorReport();
6446 report.packageName = r.info.packageName;
6447 report.installerPackageName = r.errorReportReceiver.getPackageName();
6448 report.processName = r.processName;
6449 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006450 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006451
Dan Egnorb7f03672009-12-09 16:22:32 -08006452 if (r.crashing) {
6453 report.type = ApplicationErrorReport.TYPE_CRASH;
6454 report.crashInfo = crashInfo;
6455 } else if (r.notResponding) {
6456 report.type = ApplicationErrorReport.TYPE_ANR;
6457 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006458
Dan Egnorb7f03672009-12-09 16:22:32 -08006459 report.anrInfo.activity = r.notRespondingReport.tag;
6460 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6461 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006462 }
6463
Dan Egnorb7f03672009-12-09 16:22:32 -08006464 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006465 }
6466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6468 // assume our apps are happy - lazy create the list
6469 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6470
6471 synchronized (this) {
6472
6473 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006474 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6475 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006476 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6477 // This one's in trouble, so we'll generate a report for it
6478 // crashes are higher priority (in case there's a crash *and* an anr)
6479 ActivityManager.ProcessErrorStateInfo report = null;
6480 if (app.crashing) {
6481 report = app.crashingReport;
6482 } else if (app.notResponding) {
6483 report = app.notRespondingReport;
6484 }
6485
6486 if (report != null) {
6487 if (errList == null) {
6488 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6489 }
6490 errList.add(report);
6491 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006492 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006493 " crashing = " + app.crashing +
6494 " notResponding = " + app.notResponding);
6495 }
6496 }
6497 }
6498 }
6499
6500 return errList;
6501 }
6502
6503 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6504 // Lazy instantiation of list
6505 List<ActivityManager.RunningAppProcessInfo> runList = null;
6506 synchronized (this) {
6507 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006508 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6509 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006510 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6511 // Generate process state info for running application
6512 ActivityManager.RunningAppProcessInfo currApp =
6513 new ActivityManager.RunningAppProcessInfo(app.processName,
6514 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006515 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006516 if (mHeavyWeightProcess == app) {
6517 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
6518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006519 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006520 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006521 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6522 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6523 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006524 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6525 } else if (adj >= HOME_APP_ADJ) {
6526 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6527 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006528 } else if (adj >= SECONDARY_SERVER_ADJ) {
6529 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006530 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6531 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6532 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6533 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006534 } else if (adj >= VISIBLE_APP_ADJ) {
6535 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6536 } else {
6537 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6538 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006539 currApp.importanceReasonCode = app.adjTypeCode;
6540 if (app.adjSource instanceof ProcessRecord) {
6541 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006542 } else if (app.adjSource instanceof ActivityRecord) {
6543 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006544 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6545 }
6546 if (app.adjTarget instanceof ComponentName) {
6547 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6548 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006549 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006550 // + " lru=" + currApp.lru);
6551 if (runList == null) {
6552 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6553 }
6554 runList.add(currApp);
6555 }
6556 }
6557 }
6558 return runList;
6559 }
6560
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006561 public List<ApplicationInfo> getRunningExternalApplications() {
6562 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6563 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6564 if (runningApps != null && runningApps.size() > 0) {
6565 Set<String> extList = new HashSet<String>();
6566 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6567 if (app.pkgList != null) {
6568 for (String pkg : app.pkgList) {
6569 extList.add(pkg);
6570 }
6571 }
6572 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006573 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006574 for (String pkg : extList) {
6575 try {
6576 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6577 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6578 retList.add(info);
6579 }
6580 } catch (RemoteException e) {
6581 }
6582 }
6583 }
6584 return retList;
6585 }
6586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006587 @Override
6588 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006589 if (checkCallingPermission(android.Manifest.permission.DUMP)
6590 != PackageManager.PERMISSION_GRANTED) {
6591 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6592 + Binder.getCallingPid()
6593 + ", uid=" + Binder.getCallingUid()
6594 + " without permission "
6595 + android.Manifest.permission.DUMP);
6596 return;
6597 }
6598
6599 boolean dumpAll = false;
6600
6601 int opti = 0;
6602 while (opti < args.length) {
6603 String opt = args[opti];
6604 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6605 break;
6606 }
6607 opti++;
6608 if ("-a".equals(opt)) {
6609 dumpAll = true;
6610 } else if ("-h".equals(opt)) {
6611 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006612 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006613 pw.println(" cmd may be one of:");
6614 pw.println(" activities: activity stack state");
6615 pw.println(" broadcasts: broadcast state");
6616 pw.println(" intents: pending intent state");
6617 pw.println(" processes: process state");
6618 pw.println(" providers: content provider state");
6619 pw.println(" services: service state");
6620 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006621 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006622 } else {
6623 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006624 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006625 }
6626
6627 // Is the caller requesting to dump a particular piece of data?
6628 if (opti < args.length) {
6629 String cmd = args[opti];
6630 opti++;
6631 if ("activities".equals(cmd) || "a".equals(cmd)) {
6632 synchronized (this) {
6633 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006634 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006635 return;
6636 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6637 synchronized (this) {
6638 dumpBroadcastsLocked(fd, pw, args, opti, true);
6639 }
6640 return;
6641 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6642 synchronized (this) {
6643 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6644 }
6645 return;
6646 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6647 synchronized (this) {
6648 dumpProcessesLocked(fd, pw, args, opti, true);
6649 }
6650 return;
6651 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6652 synchronized (this) {
6653 dumpProvidersLocked(fd, pw, args, opti, true);
6654 }
6655 return;
6656 } else if ("service".equals(cmd)) {
6657 dumpService(fd, pw, args, opti, true);
6658 return;
6659 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6660 synchronized (this) {
6661 dumpServicesLocked(fd, pw, args, opti, true);
6662 }
6663 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006664 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006665 }
6666
6667 // No piece of data specified, dump everything.
6668 synchronized (this) {
6669 boolean needSep;
6670 if (dumpAll) {
6671 pw.println("Providers in Current Activity Manager State:");
6672 }
6673 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6674 if (needSep) {
6675 pw.println(" ");
6676 }
6677 if (dumpAll) {
6678 pw.println("-------------------------------------------------------------------------------");
6679 pw.println("Broadcasts in Current Activity Manager State:");
6680 }
6681 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
6682 if (needSep) {
6683 pw.println(" ");
6684 }
6685 if (dumpAll) {
6686 pw.println("-------------------------------------------------------------------------------");
6687 pw.println("Services in Current Activity Manager State:");
6688 }
6689 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
6690 if (needSep) {
6691 pw.println(" ");
6692 }
6693 if (dumpAll) {
6694 pw.println("-------------------------------------------------------------------------------");
6695 pw.println("PendingIntents in Current Activity Manager State:");
6696 }
6697 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
6698 if (needSep) {
6699 pw.println(" ");
6700 }
6701 if (dumpAll) {
6702 pw.println("-------------------------------------------------------------------------------");
6703 pw.println("Activities in Current Activity Manager State:");
6704 }
6705 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
6706 if (needSep) {
6707 pw.println(" ");
6708 }
6709 if (dumpAll) {
6710 pw.println("-------------------------------------------------------------------------------");
6711 pw.println("Processes in Current Activity Manager State:");
6712 }
6713 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
6714 }
6715 }
6716
6717 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6718 int opti, boolean dumpAll, boolean needHeader) {
6719 if (needHeader) {
6720 pw.println(" Activity stack:");
6721 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006722 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006723 pw.println(" ");
6724 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006725 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
6726 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006727 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006728 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006729 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006730 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006731 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006733 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006734 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006735 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006736 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006737 pw.println(" ");
6738 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006739 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006741
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006742 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006743 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
6744 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006745 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006746 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006747
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006748 if (dumpAll && mRecentTasks.size() > 0) {
6749 pw.println(" ");
6750 pw.println("Recent tasks in Current Activity Manager State:");
6751
6752 final int N = mRecentTasks.size();
6753 for (int i=0; i<N; i++) {
6754 TaskRecord tr = mRecentTasks.get(i);
6755 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
6756 pw.println(tr);
6757 mRecentTasks.get(i).dump(pw, " ");
6758 }
6759 }
6760
6761 pw.println(" ");
6762 pw.println(" mCurTask: " + mCurTask);
6763
6764 return true;
6765 }
6766
6767 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6768 int opti, boolean dumpAll) {
6769 boolean needSep = false;
6770 int numPers = 0;
6771
6772 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006773 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
6774 final int NA = procs.size();
6775 for (int ia=0; ia<NA; ia++) {
6776 if (!needSep) {
6777 pw.println(" All known processes:");
6778 needSep = true;
6779 }
6780 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006781 pw.print(r.persistent ? " *PERS*" : " *APP*");
6782 pw.print(" UID "); pw.print(procs.keyAt(ia));
6783 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006784 r.dump(pw, " ");
6785 if (r.persistent) {
6786 numPers++;
6787 }
6788 }
6789 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006790 }
6791
6792 if (mLruProcesses.size() > 0) {
6793 if (needSep) pw.println(" ");
6794 needSep = true;
6795 pw.println(" Running processes (most recent first):");
6796 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006797 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006798 needSep = true;
6799 }
6800
6801 synchronized (mPidsSelfLocked) {
6802 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006803 if (needSep) pw.println(" ");
6804 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006805 pw.println(" PID mappings:");
6806 for (int i=0; i<mPidsSelfLocked.size(); i++) {
6807 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
6808 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006809 }
6810 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006811 }
6812
6813 if (mForegroundProcesses.size() > 0) {
6814 if (needSep) pw.println(" ");
6815 needSep = true;
6816 pw.println(" Foreground Processes:");
6817 for (int i=0; i<mForegroundProcesses.size(); i++) {
6818 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
6819 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006820 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006821 }
6822
6823 if (mPersistentStartingProcesses.size() > 0) {
6824 if (needSep) pw.println(" ");
6825 needSep = true;
6826 pw.println(" Persisent processes that are starting:");
6827 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
6828 "Starting Norm", "Restarting PERS", false);
6829 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006830
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006831 if (mStartingProcesses.size() > 0) {
6832 if (needSep) pw.println(" ");
6833 needSep = true;
6834 pw.println(" Processes that are starting:");
6835 dumpProcessList(pw, this, mStartingProcesses, " ",
6836 "Starting Norm", "Starting PERS", false);
6837 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006838
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006839 if (mRemovedProcesses.size() > 0) {
6840 if (needSep) pw.println(" ");
6841 needSep = true;
6842 pw.println(" Processes that are being removed:");
6843 dumpProcessList(pw, this, mRemovedProcesses, " ",
6844 "Removed Norm", "Removed PERS", false);
6845 }
6846
6847 if (mProcessesOnHold.size() > 0) {
6848 if (needSep) pw.println(" ");
6849 needSep = true;
6850 pw.println(" Processes that are on old until the system is ready:");
6851 dumpProcessList(pw, this, mProcessesOnHold, " ",
6852 "OnHold Norm", "OnHold PERS", false);
6853 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006855 if (mProcessesToGc.size() > 0) {
6856 if (needSep) pw.println(" ");
6857 needSep = true;
6858 pw.println(" Processes that are waiting to GC:");
6859 long now = SystemClock.uptimeMillis();
6860 for (int i=0; i<mProcessesToGc.size(); i++) {
6861 ProcessRecord proc = mProcessesToGc.get(i);
6862 pw.print(" Process "); pw.println(proc);
6863 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
6864 pw.print(", last gced=");
6865 pw.print(now-proc.lastRequestedGc);
6866 pw.print(" ms ago, last lowMem=");
6867 pw.print(now-proc.lastLowMemory);
6868 pw.println(" ms ago");
6869
6870 }
6871 }
6872
6873 if (mProcessCrashTimes.getMap().size() > 0) {
6874 if (needSep) pw.println(" ");
6875 needSep = true;
6876 pw.println(" Time since processes crashed:");
6877 long now = SystemClock.uptimeMillis();
6878 for (Map.Entry<String, SparseArray<Long>> procs
6879 : mProcessCrashTimes.getMap().entrySet()) {
6880 SparseArray<Long> uids = procs.getValue();
6881 final int N = uids.size();
6882 for (int i=0; i<N; i++) {
6883 pw.print(" Process "); pw.print(procs.getKey());
6884 pw.print(" uid "); pw.print(uids.keyAt(i));
6885 pw.print(": last crashed ");
6886 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07006887 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07006888 }
6889 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006890 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006891
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006892 if (mBadProcesses.getMap().size() > 0) {
6893 if (needSep) pw.println(" ");
6894 needSep = true;
6895 pw.println(" Bad processes:");
6896 for (Map.Entry<String, SparseArray<Long>> procs
6897 : mBadProcesses.getMap().entrySet()) {
6898 SparseArray<Long> uids = procs.getValue();
6899 final int N = uids.size();
6900 for (int i=0; i<N; i++) {
6901 pw.print(" Bad process "); pw.print(procs.getKey());
6902 pw.print(" uid "); pw.print(uids.keyAt(i));
6903 pw.print(": crashed at time ");
6904 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006905 }
6906 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006908
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006909 pw.println(" ");
6910 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07006911 if (mHeavyWeightProcess != null) {
6912 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
6913 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006914 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006915 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006916 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
6917 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
6918 || mOrigWaitForDebugger) {
6919 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
6920 + " mDebugTransient=" + mDebugTransient
6921 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
6922 }
6923 if (mAlwaysFinishActivities || mController != null) {
6924 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
6925 + " mController=" + mController);
6926 }
6927 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006928 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006929 pw.println(" mStartRunning=" + mStartRunning
6930 + " mSystemReady=" + mSystemReady
6931 + " mBooting=" + mBooting
6932 + " mBooted=" + mBooted
6933 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006934 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
6935 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07006936 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006938
6939 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006940 }
6941
6942 /**
6943 * There are three ways to call this:
6944 * - no service specified: dump all the services
6945 * - a flattened component name that matched an existing service was specified as the
6946 * first arg: dump that one service
6947 * - the first arg isn't the flattened component name of an existing service:
6948 * dump all services whose component contains the first arg as a substring
6949 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006950 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
6951 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006952 String[] newArgs;
6953 String componentNameString;
6954 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08006955 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006956 componentNameString = null;
6957 newArgs = EMPTY_STRING_ARRAY;
6958 r = null;
6959 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006960 componentNameString = args[opti];
6961 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006962 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
6963 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006964 newArgs = new String[args.length - opti];
6965 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006966 }
6967
6968 if (r != null) {
6969 dumpService(fd, pw, r, newArgs);
6970 } else {
6971 for (ServiceRecord r1 : mServices.values()) {
6972 if (componentNameString == null
6973 || r1.name.flattenToString().contains(componentNameString)) {
6974 dumpService(fd, pw, r1, newArgs);
6975 }
6976 }
6977 }
6978 }
6979
6980 /**
6981 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
6982 * there is a thread associated with the service.
6983 */
6984 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
6985 pw.println(" Service " + r.name.flattenToString());
6986 if (r.app != null && r.app.thread != null) {
6987 try {
6988 // flush anything that is already in the PrintWriter since the thread is going
6989 // to write to the file descriptor directly
6990 pw.flush();
6991 r.app.thread.dumpService(fd, r, args);
6992 pw.print("\n");
6993 } catch (RemoteException e) {
6994 pw.println("got a RemoteException while dumping the service");
6995 }
6996 }
6997 }
6998
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006999 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7000 int opti, boolean dumpAll) {
7001 boolean needSep = false;
7002
7003 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007004 if (mRegisteredReceivers.size() > 0) {
7005 pw.println(" ");
7006 pw.println(" Registered Receivers:");
7007 Iterator it = mRegisteredReceivers.values().iterator();
7008 while (it.hasNext()) {
7009 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007010 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007011 r.dump(pw, " ");
7012 }
7013 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007015 pw.println(" ");
7016 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007017 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007018 needSep = true;
7019 }
7020
7021 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7022 || mPendingBroadcast != null) {
7023 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007024 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007025 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007026 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007027 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7028 pw.println(" Broadcast #" + i + ":");
7029 mParallelBroadcasts.get(i).dump(pw, " ");
7030 }
7031 if (mOrderedBroadcasts.size() > 0) {
7032 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007033 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007034 }
7035 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7036 pw.println(" Serialized Broadcast #" + i + ":");
7037 mOrderedBroadcasts.get(i).dump(pw, " ");
7038 }
7039 pw.println(" ");
7040 pw.println(" Pending broadcast:");
7041 if (mPendingBroadcast != null) {
7042 mPendingBroadcast.dump(pw, " ");
7043 } else {
7044 pw.println(" (null)");
7045 }
7046 needSep = true;
7047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007048
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007049 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007050 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007051 pw.println(" Historical broadcasts:");
7052 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7053 BroadcastRecord r = mBroadcastHistory[i];
7054 if (r == null) {
7055 break;
7056 }
7057 pw.println(" Historical Broadcast #" + i + ":");
7058 r.dump(pw, " ");
7059 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007060 needSep = true;
7061 }
7062
7063 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007064 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007065 pw.println(" Sticky broadcasts:");
7066 StringBuilder sb = new StringBuilder(128);
7067 for (Map.Entry<String, ArrayList<Intent>> ent
7068 : mStickyBroadcasts.entrySet()) {
7069 pw.print(" * Sticky action "); pw.print(ent.getKey());
7070 pw.println(":");
7071 ArrayList<Intent> intents = ent.getValue();
7072 final int N = intents.size();
7073 for (int i=0; i<N; i++) {
7074 sb.setLength(0);
7075 sb.append(" Intent: ");
7076 intents.get(i).toShortString(sb, true, false);
7077 pw.println(sb.toString());
7078 Bundle bundle = intents.get(i).getExtras();
7079 if (bundle != null) {
7080 pw.print(" ");
7081 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007082 }
7083 }
7084 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007085 needSep = true;
7086 }
7087
7088 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007089 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007090 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007091 pw.println(" mHandler:");
7092 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007093 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007094 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007095
7096 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007097 }
7098
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007099 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7100 int opti, boolean dumpAll) {
7101 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007102
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007103 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007104 if (mServices.size() > 0) {
7105 pw.println(" Active services:");
7106 Iterator<ServiceRecord> it = mServices.values().iterator();
7107 while (it.hasNext()) {
7108 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007109 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007110 r.dump(pw, " ");
7111 }
7112 needSep = true;
7113 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007114 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007115
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007116 if (mPendingServices.size() > 0) {
7117 if (needSep) pw.println(" ");
7118 pw.println(" Pending services:");
7119 for (int i=0; i<mPendingServices.size(); i++) {
7120 ServiceRecord r = mPendingServices.get(i);
7121 pw.print(" * Pending "); pw.println(r);
7122 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007123 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007124 needSep = true;
7125 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007126
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007127 if (mRestartingServices.size() > 0) {
7128 if (needSep) pw.println(" ");
7129 pw.println(" Restarting services:");
7130 for (int i=0; i<mRestartingServices.size(); i++) {
7131 ServiceRecord r = mRestartingServices.get(i);
7132 pw.print(" * Restarting "); pw.println(r);
7133 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007134 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007135 needSep = true;
7136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007138 if (mStoppingServices.size() > 0) {
7139 if (needSep) pw.println(" ");
7140 pw.println(" Stopping services:");
7141 for (int i=0; i<mStoppingServices.size(); i++) {
7142 ServiceRecord r = mStoppingServices.get(i);
7143 pw.print(" * Stopping "); pw.println(r);
7144 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007145 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007146 needSep = true;
7147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007148
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007149 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007150 if (mServiceConnections.size() > 0) {
7151 if (needSep) pw.println(" ");
7152 pw.println(" Connection bindings to services:");
7153 Iterator<ConnectionRecord> it
7154 = mServiceConnections.values().iterator();
7155 while (it.hasNext()) {
7156 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007157 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158 r.dump(pw, " ");
7159 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007160 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007161 }
7162 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007163
7164 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165 }
7166
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007167 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7168 int opti, boolean dumpAll) {
7169 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007170
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007171 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007172 if (mProvidersByClass.size() > 0) {
7173 if (needSep) pw.println(" ");
7174 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007175 Iterator<Map.Entry<String, ContentProviderRecord>> it
7176 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007177 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007178 Map.Entry<String, ContentProviderRecord> e = it.next();
7179 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007180 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007181 r.dump(pw, " ");
7182 }
7183 needSep = true;
7184 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007185
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007186 if (mProvidersByName.size() > 0) {
7187 pw.println(" ");
7188 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007189 Iterator<Map.Entry<String, ContentProviderRecord>> it
7190 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007191 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007192 Map.Entry<String, ContentProviderRecord> e = it.next();
7193 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007194 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7195 pw.println(r);
7196 }
7197 needSep = true;
7198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007199 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007200
7201 if (mLaunchingProviders.size() > 0) {
7202 if (needSep) pw.println(" ");
7203 pw.println(" Launching content providers:");
7204 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7205 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7206 pw.println(mLaunchingProviders.get(i));
7207 }
7208 needSep = true;
7209 }
7210
7211 if (mGrantedUriPermissions.size() > 0) {
7212 pw.println();
7213 pw.println("Granted Uri Permissions:");
7214 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7215 int uid = mGrantedUriPermissions.keyAt(i);
7216 HashMap<Uri, UriPermission> perms
7217 = mGrantedUriPermissions.valueAt(i);
7218 pw.print(" * UID "); pw.print(uid);
7219 pw.println(" holds:");
7220 for (UriPermission perm : perms.values()) {
7221 pw.print(" "); pw.println(perm);
7222 perm.dump(pw, " ");
7223 }
7224 }
7225 needSep = true;
7226 }
7227
7228 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007229 }
7230
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007231 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7232 int opti, boolean dumpAll) {
7233 boolean needSep = false;
7234
7235 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007236 if (this.mIntentSenderRecords.size() > 0) {
7237 Iterator<WeakReference<PendingIntentRecord>> it
7238 = mIntentSenderRecords.values().iterator();
7239 while (it.hasNext()) {
7240 WeakReference<PendingIntentRecord> ref = it.next();
7241 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007242 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007243 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007244 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007245 rec.dump(pw, " ");
7246 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007247 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007248 }
7249 }
7250 }
7251 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007252
7253 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007254 }
7255
7256 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007257 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007258 TaskRecord lastTask = null;
7259 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007260 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007261 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007262 if (lastTask != r.task) {
7263 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007264 pw.print(prefix);
7265 pw.print(full ? "* " : " ");
7266 pw.println(lastTask);
7267 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007268 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007270 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007271 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7272 pw.print(" #"); pw.print(i); pw.print(": ");
7273 pw.println(r);
7274 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007275 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007277 }
7278 }
7279
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007280 private static String buildOomTag(String prefix, String space, int val, int base) {
7281 if (val == base) {
7282 if (space == null) return prefix;
7283 return prefix + " ";
7284 }
7285 return prefix + "+" + Integer.toString(val-base);
7286 }
7287
7288 private static final int dumpProcessList(PrintWriter pw,
7289 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007290 String prefix, String normalLabel, String persistentLabel,
7291 boolean inclOomAdj) {
7292 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007293 final int N = list.size()-1;
7294 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295 ProcessRecord r = (ProcessRecord)list.get(i);
7296 if (false) {
7297 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7298 + " #" + i + ":");
7299 r.dump(pw, prefix + " ");
7300 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007301 String oomAdj;
7302 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007303 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007304 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007305 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7306 } else if (r.setAdj >= HOME_APP_ADJ) {
7307 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7308 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7309 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7310 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7311 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007312 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7313 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7314 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7315 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007316 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7317 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7318 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7319 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007320 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007321 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007322 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007323 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007324 } else {
7325 oomAdj = Integer.toString(r.setAdj);
7326 }
7327 String schedGroup;
7328 switch (r.setSchedGroup) {
7329 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7330 schedGroup = "B";
7331 break;
7332 case Process.THREAD_GROUP_DEFAULT:
7333 schedGroup = "F";
7334 break;
7335 default:
7336 schedGroup = Integer.toString(r.setSchedGroup);
7337 break;
7338 }
7339 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007340 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007341 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007342 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007343 pw.print(prefix);
7344 pw.print(" ");
7345 if (r.adjTarget instanceof ComponentName) {
7346 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7347 } else if (r.adjTarget != null) {
7348 pw.print(r.adjTarget.toString());
7349 } else {
7350 pw.print("{null}");
7351 }
7352 pw.print("<=");
7353 if (r.adjSource instanceof ProcessRecord) {
7354 pw.print("Proc{");
7355 pw.print(((ProcessRecord)r.adjSource).toShortString());
7356 pw.println("}");
7357 } else if (r.adjSource != null) {
7358 pw.println(r.adjSource.toString());
7359 } else {
7360 pw.println("{null}");
7361 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007363 } else {
7364 pw.println(String.format("%s%s #%2d: %s",
7365 prefix, (r.persistent ? persistentLabel : normalLabel),
7366 i, r.toString()));
7367 }
7368 if (r.persistent) {
7369 numPers++;
7370 }
7371 }
7372 return numPers;
7373 }
7374
Dianne Hackborn472ad872010-04-07 17:31:48 -07007375 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007377 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 long uptime = SystemClock.uptimeMillis();
7379 long realtime = SystemClock.elapsedRealtime();
7380
7381 if (isCheckinRequest) {
7382 // short checkin version
7383 pw.println(uptime + "," + realtime);
7384 pw.flush();
7385 } else {
7386 pw.println("Applications Memory Usage (kB):");
7387 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7388 }
7389 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7390 ProcessRecord r = (ProcessRecord)list.get(i);
7391 if (r.thread != null) {
7392 if (!isCheckinRequest) {
7393 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7394 pw.flush();
7395 }
7396 try {
7397 r.thread.asBinder().dump(fd, args);
7398 } catch (RemoteException e) {
7399 if (!isCheckinRequest) {
7400 pw.println("Got RemoteException!");
7401 pw.flush();
7402 }
7403 }
7404 }
7405 }
7406 }
7407
7408 /**
7409 * Searches array of arguments for the specified string
7410 * @param args array of argument strings
7411 * @param value value to search for
7412 * @return true if the value is contained in the array
7413 */
7414 private static boolean scanArgs(String[] args, String value) {
7415 if (args != null) {
7416 for (String arg : args) {
7417 if (value.equals(arg)) {
7418 return true;
7419 }
7420 }
7421 }
7422 return false;
7423 }
7424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007425 private final void killServicesLocked(ProcessRecord app,
7426 boolean allowRestart) {
7427 // Report disconnected services.
7428 if (false) {
7429 // XXX we are letting the client link to the service for
7430 // death notifications.
7431 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007432 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007433 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007434 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007435 if (r.connections.size() > 0) {
7436 Iterator<ConnectionRecord> jt
7437 = r.connections.values().iterator();
7438 while (jt.hasNext()) {
7439 ConnectionRecord c = jt.next();
7440 if (c.binding.client != app) {
7441 try {
7442 //c.conn.connected(r.className, null);
7443 } catch (Exception e) {
7444 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007445 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 + r.shortName
7447 + " from app " + app.processName, e);
7448 }
7449 }
7450 }
7451 }
7452 }
7453 }
7454 }
7455
7456 // Clean up any connections this application has to other services.
7457 if (app.connections.size() > 0) {
7458 Iterator<ConnectionRecord> it = app.connections.iterator();
7459 while (it.hasNext()) {
7460 ConnectionRecord r = it.next();
7461 removeConnectionLocked(r, app, null);
7462 }
7463 }
7464 app.connections.clear();
7465
7466 if (app.services.size() != 0) {
7467 // Any services running in the application need to be placed
7468 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007469 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007470 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007471 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007472 synchronized (sr.stats.getBatteryStats()) {
7473 sr.stats.stopLaunchedLocked();
7474 }
7475 sr.app = null;
7476 sr.executeNesting = 0;
7477 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007478
7479 boolean hasClients = sr.bindings.size() > 0;
7480 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 Iterator<IntentBindRecord> bindings
7482 = sr.bindings.values().iterator();
7483 while (bindings.hasNext()) {
7484 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007485 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007486 + ": shouldUnbind=" + b.hasBound);
7487 b.binder = null;
7488 b.requested = b.received = b.hasBound = false;
7489 }
7490 }
7491
7492 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007493 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007495 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007496 sr.crashCount, sr.shortName, app.pid);
7497 bringDownServiceLocked(sr, true);
7498 } else if (!allowRestart) {
7499 bringDownServiceLocked(sr, true);
7500 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007501 boolean canceled = scheduleServiceRestartLocked(sr, true);
7502
7503 // Should the service remain running? Note that in the
7504 // extreme case of so many attempts to deliver a command
7505 // that it failed, that we also will stop it here.
7506 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7507 if (sr.pendingStarts.size() == 0) {
7508 sr.startRequested = false;
7509 if (!hasClients) {
7510 // Whoops, no reason to restart!
7511 bringDownServiceLocked(sr, true);
7512 }
7513 }
7514 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 }
7516 }
7517
7518 if (!allowRestart) {
7519 app.services.clear();
7520 }
7521 }
7522
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007523 // Make sure we have no more records on the stopping list.
7524 int i = mStoppingServices.size();
7525 while (i > 0) {
7526 i--;
7527 ServiceRecord sr = mStoppingServices.get(i);
7528 if (sr.app == app) {
7529 mStoppingServices.remove(i);
7530 }
7531 }
7532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007533 app.executingServices.clear();
7534 }
7535
7536 private final void removeDyingProviderLocked(ProcessRecord proc,
7537 ContentProviderRecord cpr) {
7538 synchronized (cpr) {
7539 cpr.launchingApp = null;
7540 cpr.notifyAll();
7541 }
7542
7543 mProvidersByClass.remove(cpr.info.name);
7544 String names[] = cpr.info.authority.split(";");
7545 for (int j = 0; j < names.length; j++) {
7546 mProvidersByName.remove(names[j]);
7547 }
7548
7549 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7550 while (cit.hasNext()) {
7551 ProcessRecord capp = cit.next();
7552 if (!capp.persistent && capp.thread != null
7553 && capp.pid != 0
7554 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007555 Slog.i(TAG, "Kill " + capp.processName
7556 + " (pid " + capp.pid + "): provider " + cpr.info.name
7557 + " in dying process " + proc.processName);
7558 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7559 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007560 Process.killProcess(capp.pid);
7561 }
7562 }
7563
7564 mLaunchingProviders.remove(cpr);
7565 }
7566
7567 /**
7568 * Main code for cleaning up a process when it has gone away. This is
7569 * called both as a result of the process dying, or directly when stopping
7570 * a process when running in single process mode.
7571 */
7572 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7573 boolean restarting, int index) {
7574 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007575 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007576 }
7577
Dianne Hackborn36124872009-10-08 16:22:03 -07007578 mProcessesToGc.remove(app);
7579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 // Dismiss any open dialogs.
7581 if (app.crashDialog != null) {
7582 app.crashDialog.dismiss();
7583 app.crashDialog = null;
7584 }
7585 if (app.anrDialog != null) {
7586 app.anrDialog.dismiss();
7587 app.anrDialog = null;
7588 }
7589 if (app.waitDialog != null) {
7590 app.waitDialog.dismiss();
7591 app.waitDialog = null;
7592 }
7593
7594 app.crashing = false;
7595 app.notResponding = false;
7596
7597 app.resetPackageList();
7598 app.thread = null;
7599 app.forcingToForeground = null;
7600 app.foregroundServices = false;
7601
7602 killServicesLocked(app, true);
7603
7604 boolean restart = false;
7605
7606 int NL = mLaunchingProviders.size();
7607
7608 // Remove published content providers.
7609 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007610 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007611 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007612 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613 cpr.provider = null;
7614 cpr.app = null;
7615
7616 // See if someone is waiting for this provider... in which
7617 // case we don't remove it, but just let it restart.
7618 int i = 0;
7619 if (!app.bad) {
7620 for (; i<NL; i++) {
7621 if (mLaunchingProviders.get(i) == cpr) {
7622 restart = true;
7623 break;
7624 }
7625 }
7626 } else {
7627 i = NL;
7628 }
7629
7630 if (i >= NL) {
7631 removeDyingProviderLocked(app, cpr);
7632 NL = mLaunchingProviders.size();
7633 }
7634 }
7635 app.pubProviders.clear();
7636 }
7637
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007638 // Take care of any launching providers waiting for this process.
7639 if (checkAppInLaunchingProvidersLocked(app, false)) {
7640 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007641 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007643 // Unregister from connected content providers.
7644 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007645 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007646 while (it.hasNext()) {
7647 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7648 cpr.clients.remove(app);
7649 }
7650 app.conProviders.clear();
7651 }
7652
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007653 // At this point there may be remaining entries in mLaunchingProviders
7654 // where we were the only one waiting, so they are no longer of use.
7655 // Look for these and clean up if found.
7656 // XXX Commented out for now. Trying to figure out a way to reproduce
7657 // the actual situation to identify what is actually going on.
7658 if (false) {
7659 for (int i=0; i<NL; i++) {
7660 ContentProviderRecord cpr = (ContentProviderRecord)
7661 mLaunchingProviders.get(i);
7662 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
7663 synchronized (cpr) {
7664 cpr.launchingApp = null;
7665 cpr.notifyAll();
7666 }
7667 }
7668 }
7669 }
7670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007671 skipCurrentReceiverLocked(app);
7672
7673 // Unregister any receivers.
7674 if (app.receivers.size() > 0) {
7675 Iterator<ReceiverList> it = app.receivers.iterator();
7676 while (it.hasNext()) {
7677 removeReceiverLocked(it.next());
7678 }
7679 app.receivers.clear();
7680 }
7681
Christopher Tate181fafa2009-05-14 11:12:14 -07007682 // If the app is undergoing backup, tell the backup manager about it
7683 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007684 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07007685 try {
7686 IBackupManager bm = IBackupManager.Stub.asInterface(
7687 ServiceManager.getService(Context.BACKUP_SERVICE));
7688 bm.agentDisconnected(app.info.packageName);
7689 } catch (RemoteException e) {
7690 // can't happen; backup manager is local
7691 }
7692 }
7693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007694 // If the caller is restarting this app, then leave it in its
7695 // current lists and let the caller take care of it.
7696 if (restarting) {
7697 return;
7698 }
7699
7700 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007701 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007702 "Removing non-persistent process during cleanup: " + app);
7703 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007704 if (mHeavyWeightProcess == app) {
7705 mHeavyWeightProcess = null;
7706 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
7707 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007708 } else if (!app.removed) {
7709 // This app is persistent, so we need to keep its record around.
7710 // If it is not already on the pending app list, add it there
7711 // and start a new process for it.
7712 app.thread = null;
7713 app.forcingToForeground = null;
7714 app.foregroundServices = false;
7715 if (mPersistentStartingProcesses.indexOf(app) < 0) {
7716 mPersistentStartingProcesses.add(app);
7717 restart = true;
7718 }
7719 }
7720 mProcessesOnHold.remove(app);
7721
The Android Open Source Project4df24232009-03-05 14:34:35 -08007722 if (app == mHomeProcess) {
7723 mHomeProcess = null;
7724 }
7725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007726 if (restart) {
7727 // We have components that still need to be running in the
7728 // process, so re-launch it.
7729 mProcessNames.put(app.processName, app.info.uid, app);
7730 startProcessLocked(app, "restart", app.processName);
7731 } else if (app.pid > 0 && app.pid != MY_PID) {
7732 // Goodbye!
7733 synchronized (mPidsSelfLocked) {
7734 mPidsSelfLocked.remove(app.pid);
7735 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
7736 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007737 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007738 }
7739 }
7740
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007741 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
7742 // Look through the content providers we are waiting to have launched,
7743 // and if any run in this process then either schedule a restart of
7744 // the process or kill the client waiting for it if this process has
7745 // gone bad.
7746 int NL = mLaunchingProviders.size();
7747 boolean restart = false;
7748 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007749 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007750 if (cpr.launchingApp == app) {
7751 if (!alwaysBad && !app.bad) {
7752 restart = true;
7753 } else {
7754 removeDyingProviderLocked(app, cpr);
7755 NL = mLaunchingProviders.size();
7756 }
7757 }
7758 }
7759 return restart;
7760 }
7761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007762 // =========================================================
7763 // SERVICES
7764 // =========================================================
7765
7766 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
7767 ActivityManager.RunningServiceInfo info =
7768 new ActivityManager.RunningServiceInfo();
7769 info.service = r.name;
7770 if (r.app != null) {
7771 info.pid = r.app.pid;
7772 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007773 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774 info.process = r.processName;
7775 info.foreground = r.isForeground;
7776 info.activeSince = r.createTime;
7777 info.started = r.startRequested;
7778 info.clientCount = r.connections.size();
7779 info.crashCount = r.crashCount;
7780 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007781 if (r.isForeground) {
7782 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
7783 }
7784 if (r.startRequested) {
7785 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
7786 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007787 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007788 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
7789 }
7790 if (r.app != null && r.app.persistent) {
7791 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
7792 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007793 for (ConnectionRecord conn : r.connections.values()) {
7794 if (conn.clientLabel != 0) {
7795 info.clientPackage = conn.binding.client.info.packageName;
7796 info.clientLabel = conn.clientLabel;
7797 break;
7798 }
7799 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 return info;
7801 }
7802
7803 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
7804 int flags) {
7805 synchronized (this) {
7806 ArrayList<ActivityManager.RunningServiceInfo> res
7807 = new ArrayList<ActivityManager.RunningServiceInfo>();
7808
7809 if (mServices.size() > 0) {
7810 Iterator<ServiceRecord> it = mServices.values().iterator();
7811 while (it.hasNext() && res.size() < maxNum) {
7812 res.add(makeRunningServiceInfoLocked(it.next()));
7813 }
7814 }
7815
7816 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
7817 ServiceRecord r = mRestartingServices.get(i);
7818 ActivityManager.RunningServiceInfo info =
7819 makeRunningServiceInfoLocked(r);
7820 info.restarting = r.nextRestartTime;
7821 res.add(info);
7822 }
7823
7824 return res;
7825 }
7826 }
7827
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007828 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
7829 synchronized (this) {
7830 ServiceRecord r = mServices.get(name);
7831 if (r != null) {
7832 for (ConnectionRecord conn : r.connections.values()) {
7833 if (conn.clientIntent != null) {
7834 return conn.clientIntent;
7835 }
7836 }
7837 }
7838 }
7839 return null;
7840 }
7841
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007842 private final ServiceRecord findServiceLocked(ComponentName name,
7843 IBinder token) {
7844 ServiceRecord r = mServices.get(name);
7845 return r == token ? r : null;
7846 }
7847
7848 private final class ServiceLookupResult {
7849 final ServiceRecord record;
7850 final String permission;
7851
7852 ServiceLookupResult(ServiceRecord _record, String _permission) {
7853 record = _record;
7854 permission = _permission;
7855 }
7856 };
7857
7858 private ServiceLookupResult findServiceLocked(Intent service,
7859 String resolvedType) {
7860 ServiceRecord r = null;
7861 if (service.getComponent() != null) {
7862 r = mServices.get(service.getComponent());
7863 }
7864 if (r == null) {
7865 Intent.FilterComparison filter = new Intent.FilterComparison(service);
7866 r = mServicesByIntent.get(filter);
7867 }
7868
7869 if (r == null) {
7870 try {
7871 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007872 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007873 service, resolvedType, 0);
7874 ServiceInfo sInfo =
7875 rInfo != null ? rInfo.serviceInfo : null;
7876 if (sInfo == null) {
7877 return null;
7878 }
7879
7880 ComponentName name = new ComponentName(
7881 sInfo.applicationInfo.packageName, sInfo.name);
7882 r = mServices.get(name);
7883 } catch (RemoteException ex) {
7884 // pm is in same process, this will never happen.
7885 }
7886 }
7887 if (r != null) {
7888 int callingPid = Binder.getCallingPid();
7889 int callingUid = Binder.getCallingUid();
7890 if (checkComponentPermission(r.permission,
7891 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
7892 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007893 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007894 + " from pid=" + callingPid
7895 + ", uid=" + callingUid
7896 + " requires " + r.permission);
7897 return new ServiceLookupResult(null, r.permission);
7898 }
7899 return new ServiceLookupResult(r, null);
7900 }
7901 return null;
7902 }
7903
7904 private class ServiceRestarter implements Runnable {
7905 private ServiceRecord mService;
7906
7907 void setService(ServiceRecord service) {
7908 mService = service;
7909 }
7910
7911 public void run() {
7912 synchronized(ActivityManagerService.this) {
7913 performServiceRestartLocked(mService);
7914 }
7915 }
7916 }
7917
7918 private ServiceLookupResult retrieveServiceLocked(Intent service,
7919 String resolvedType, int callingPid, int callingUid) {
7920 ServiceRecord r = null;
7921 if (service.getComponent() != null) {
7922 r = mServices.get(service.getComponent());
7923 }
7924 Intent.FilterComparison filter = new Intent.FilterComparison(service);
7925 r = mServicesByIntent.get(filter);
7926 if (r == null) {
7927 try {
7928 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007929 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07007930 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007931 ServiceInfo sInfo =
7932 rInfo != null ? rInfo.serviceInfo : null;
7933 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007934 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935 ": not found");
7936 return null;
7937 }
7938
7939 ComponentName name = new ComponentName(
7940 sInfo.applicationInfo.packageName, sInfo.name);
7941 r = mServices.get(name);
7942 if (r == null) {
7943 filter = new Intent.FilterComparison(service.cloneFilter());
7944 ServiceRestarter res = new ServiceRestarter();
7945 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
7946 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7947 synchronized (stats) {
7948 ss = stats.getServiceStatsLocked(
7949 sInfo.applicationInfo.uid, sInfo.packageName,
7950 sInfo.name);
7951 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08007952 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007953 res.setService(r);
7954 mServices.put(name, r);
7955 mServicesByIntent.put(filter, r);
7956
7957 // Make sure this component isn't in the pending list.
7958 int N = mPendingServices.size();
7959 for (int i=0; i<N; i++) {
7960 ServiceRecord pr = mPendingServices.get(i);
7961 if (pr.name.equals(name)) {
7962 mPendingServices.remove(i);
7963 i--;
7964 N--;
7965 }
7966 }
7967 }
7968 } catch (RemoteException ex) {
7969 // pm is in same process, this will never happen.
7970 }
7971 }
7972 if (r != null) {
7973 if (checkComponentPermission(r.permission,
7974 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
7975 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007976 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007977 + " from pid=" + Binder.getCallingPid()
7978 + ", uid=" + Binder.getCallingUid()
7979 + " requires " + r.permission);
7980 return new ServiceLookupResult(null, r.permission);
7981 }
7982 return new ServiceLookupResult(r, null);
7983 }
7984 return null;
7985 }
7986
7987 private final void bumpServiceExecutingLocked(ServiceRecord r) {
7988 long now = SystemClock.uptimeMillis();
7989 if (r.executeNesting == 0 && r.app != null) {
7990 if (r.app.executingServices.size() == 0) {
7991 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
7992 msg.obj = r.app;
7993 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
7994 }
7995 r.app.executingServices.add(r);
7996 }
7997 r.executeNesting++;
7998 r.executingStart = now;
7999 }
8000
8001 private final void sendServiceArgsLocked(ServiceRecord r,
8002 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008003 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008004 if (N == 0) {
8005 return;
8006 }
8007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008008 int i = 0;
8009 while (i < N) {
8010 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008011 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008012 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008013 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -07008014 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008015 // If somehow we got a dummy start at the front, then
8016 // just drop it here.
8017 i++;
8018 continue;
8019 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008020 bumpServiceExecutingLocked(r);
8021 if (!oomAdjusted) {
8022 oomAdjusted = true;
8023 updateOomAdjLocked(r.app);
8024 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008025 int flags = 0;
8026 if (si.deliveryCount > 0) {
8027 flags |= Service.START_FLAG_RETRY;
8028 }
8029 if (si.doneExecutingCount > 0) {
8030 flags |= Service.START_FLAG_REDELIVERY;
8031 }
8032 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
8033 si.deliveredTime = SystemClock.uptimeMillis();
8034 r.deliveredStarts.add(si);
8035 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008036 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008037 } catch (RemoteException e) {
8038 // Remote process gone... we'll let the normal cleanup take
8039 // care of this.
8040 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008041 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008042 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008043 break;
8044 }
8045 }
8046 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008047 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 } else {
8049 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008050 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008051 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008052 }
8053 }
8054 }
8055
8056 private final boolean requestServiceBindingLocked(ServiceRecord r,
8057 IntentBindRecord i, boolean rebind) {
8058 if (r.app == null || r.app.thread == null) {
8059 // If service is not currently running, can't yet bind.
8060 return false;
8061 }
8062 if ((!i.requested || rebind) && i.apps.size() > 0) {
8063 try {
8064 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008065 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 + ": shouldUnbind=" + i.hasBound);
8067 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8068 if (!rebind) {
8069 i.requested = true;
8070 }
8071 i.hasBound = true;
8072 i.doRebind = false;
8073 } catch (RemoteException e) {
8074 return false;
8075 }
8076 }
8077 return true;
8078 }
8079
8080 private final void requestServiceBindingsLocked(ServiceRecord r) {
8081 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8082 while (bindings.hasNext()) {
8083 IntentBindRecord i = bindings.next();
8084 if (!requestServiceBindingLocked(r, i, false)) {
8085 break;
8086 }
8087 }
8088 }
8089
8090 private final void realStartServiceLocked(ServiceRecord r,
8091 ProcessRecord app) throws RemoteException {
8092 if (app.thread == null) {
8093 throw new RemoteException();
8094 }
8095
8096 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008097 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008098
8099 app.services.add(r);
8100 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008101 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008102
8103 boolean created = false;
8104 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008105 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008106 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008107 mStringBuilder.setLength(0);
8108 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008109 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008110 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008111 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008112 synchronized (r.stats.getBatteryStats()) {
8113 r.stats.startLaunchedLocked();
8114 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008115 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008116 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008117 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008118 created = true;
8119 } finally {
8120 if (!created) {
8121 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008122 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 }
8124 }
8125
8126 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008127
8128 // If the service is in the started state, and there are no
8129 // pending arguments, then fake up one so its onStartCommand() will
8130 // be called.
8131 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8132 r.lastStartId++;
8133 if (r.lastStartId < 1) {
8134 r.lastStartId = 1;
8135 }
8136 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
8137 }
8138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 sendServiceArgsLocked(r, true);
8140 }
8141
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008142 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8143 boolean allowCancel) {
8144 boolean canceled = false;
8145
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008146 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008147 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008148 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008149
8150 // Any delivered but not yet finished starts should be put back
8151 // on the pending list.
8152 final int N = r.deliveredStarts.size();
8153 if (N > 0) {
8154 for (int i=N-1; i>=0; i--) {
8155 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
8156 if (si.intent == null) {
8157 // We'll generate this again if needed.
8158 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8159 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8160 r.pendingStarts.add(0, si);
8161 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8162 dur *= 2;
8163 if (minDuration < dur) minDuration = dur;
8164 if (resetTime < dur) resetTime = dur;
8165 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008166 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008167 + r.name);
8168 canceled = true;
8169 }
8170 }
8171 r.deliveredStarts.clear();
8172 }
8173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008174 r.totalRestartCount++;
8175 if (r.restartDelay == 0) {
8176 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008177 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008178 } else {
8179 // If it has been a "reasonably long time" since the service
8180 // was started, then reset our restart duration back to
8181 // the beginning, so we don't infinitely increase the duration
8182 // on a service that just occasionally gets killed (which is
8183 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008184 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008186 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008187 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008188 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008189 if (r.restartDelay < minDuration) {
8190 r.restartDelay = minDuration;
8191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008192 }
8193 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008194
8195 r.nextRestartTime = now + r.restartDelay;
8196
8197 // Make sure that we don't end up restarting a bunch of services
8198 // all at the same time.
8199 boolean repeat;
8200 do {
8201 repeat = false;
8202 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8203 ServiceRecord r2 = mRestartingServices.get(i);
8204 if (r2 != r && r.nextRestartTime
8205 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8206 && r.nextRestartTime
8207 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8208 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8209 r.restartDelay = r.nextRestartTime - now;
8210 repeat = true;
8211 break;
8212 }
8213 }
8214 } while (repeat);
8215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008216 if (!mRestartingServices.contains(r)) {
8217 mRestartingServices.add(r);
8218 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008219
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008220 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008222 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008223 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008224 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008225 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008226 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008227 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008228 r.shortName, r.restartDelay);
8229
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008230 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008231 }
8232
8233 final void performServiceRestartLocked(ServiceRecord r) {
8234 if (!mRestartingServices.contains(r)) {
8235 return;
8236 }
8237 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8238 }
8239
8240 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8241 if (r.restartDelay == 0) {
8242 return false;
8243 }
8244 r.resetRestartCounter();
8245 mRestartingServices.remove(r);
8246 mHandler.removeCallbacks(r.restarter);
8247 return true;
8248 }
8249
8250 private final boolean bringUpServiceLocked(ServiceRecord r,
8251 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008252 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008253 //r.dump(" ");
8254
Dianne Hackborn36124872009-10-08 16:22:03 -07008255 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256 sendServiceArgsLocked(r, false);
8257 return true;
8258 }
8259
8260 if (!whileRestarting && r.restartDelay > 0) {
8261 // If waiting for a restart, then do nothing.
8262 return true;
8263 }
8264
Joe Onorato8a9b2202010-02-26 18:56:32 -08008265 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 + " " + r.intent);
8267
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008268 // We are now bringing the service up, so no longer in the
8269 // restarting state.
8270 mRestartingServices.remove(r);
8271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008272 final String appName = r.processName;
8273 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8274 if (app != null && app.thread != null) {
8275 try {
8276 realStartServiceLocked(r, app);
8277 return true;
8278 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008279 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008280 }
8281
8282 // If a dead object exception was thrown -- fall through to
8283 // restart the application.
8284 }
8285
Dianne Hackborn36124872009-10-08 16:22:03 -07008286 // Not running -- get it started, and enqueue this service record
8287 // to be executed when the app comes up.
8288 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8289 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008290 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008291 + r.appInfo.packageName + "/"
8292 + r.appInfo.uid + " for service "
8293 + r.intent.getIntent() + ": process is bad");
8294 bringDownServiceLocked(r, true);
8295 return false;
8296 }
8297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008298 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008299 mPendingServices.add(r);
8300 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008302 return true;
8303 }
8304
8305 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008306 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008307 //r.dump(" ");
8308
8309 // Does it still need to run?
8310 if (!force && r.startRequested) {
8311 return;
8312 }
8313 if (r.connections.size() > 0) {
8314 if (!force) {
8315 // XXX should probably keep a count of the number of auto-create
8316 // connections directly in the service.
8317 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8318 while (it.hasNext()) {
8319 ConnectionRecord cr = it.next();
8320 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
8321 return;
8322 }
8323 }
8324 }
8325
8326 // Report to all of the connections that the service is no longer
8327 // available.
8328 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8329 while (it.hasNext()) {
8330 ConnectionRecord c = it.next();
8331 try {
8332 // todo: shouldn't be a synchronous call!
8333 c.conn.connected(r.name, null);
8334 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008335 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008336 " to connection " + c.conn.asBinder() +
8337 " (in " + c.binding.client.processName + ")", e);
8338 }
8339 }
8340 }
8341
8342 // Tell the service that it has been unbound.
8343 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8344 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8345 while (it.hasNext()) {
8346 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008347 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008348 + ": hasBound=" + ibr.hasBound);
8349 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8350 try {
8351 bumpServiceExecutingLocked(r);
8352 updateOomAdjLocked(r.app);
8353 ibr.hasBound = false;
8354 r.app.thread.scheduleUnbindService(r,
8355 ibr.intent.getIntent());
8356 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008357 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008358 + r.shortName, e);
8359 serviceDoneExecutingLocked(r, true);
8360 }
8361 }
8362 }
8363 }
8364
Joe Onorato8a9b2202010-02-26 18:56:32 -08008365 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008366 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008367 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008368 System.identityHashCode(r), r.shortName,
8369 (r.app != null) ? r.app.pid : -1);
8370
8371 mServices.remove(r.name);
8372 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008373 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008374 r.totalRestartCount = 0;
8375 unscheduleServiceRestartLocked(r);
8376
8377 // Also make sure it is not on the pending list.
8378 int N = mPendingServices.size();
8379 for (int i=0; i<N; i++) {
8380 if (mPendingServices.get(i) == r) {
8381 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008382 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008383 TAG, "Removed pending service: " + r.shortName);
8384 i--;
8385 N--;
8386 }
8387 }
8388
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008389 r.cancelNotification();
8390 r.isForeground = false;
8391 r.foregroundId = 0;
8392 r.foregroundNoti = null;
8393
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008394 // Clear start entries.
8395 r.deliveredStarts.clear();
8396 r.pendingStarts.clear();
8397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008398 if (r.app != null) {
8399 synchronized (r.stats.getBatteryStats()) {
8400 r.stats.stopLaunchedLocked();
8401 }
8402 r.app.services.remove(r);
8403 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008404 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008405 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008406 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008407 bumpServiceExecutingLocked(r);
8408 mStoppingServices.add(r);
8409 updateOomAdjLocked(r.app);
8410 r.app.thread.scheduleStopService(r);
8411 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008412 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008413 + r.shortName, e);
8414 serviceDoneExecutingLocked(r, true);
8415 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008416 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008417 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008418 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008419 TAG, "Removed service that has no process: " + r.shortName);
8420 }
8421 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008422 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008423 TAG, "Removed service that is not running: " + r.shortName);
8424 }
8425 }
8426
8427 ComponentName startServiceLocked(IApplicationThread caller,
8428 Intent service, String resolvedType,
8429 int callingPid, int callingUid) {
8430 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008431 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008432 + " type=" + resolvedType + " args=" + service.getExtras());
8433
8434 if (caller != null) {
8435 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8436 if (callerApp == null) {
8437 throw new SecurityException(
8438 "Unable to find app for caller " + caller
8439 + " (pid=" + Binder.getCallingPid()
8440 + ") when starting service " + service);
8441 }
8442 }
8443
8444 ServiceLookupResult res =
8445 retrieveServiceLocked(service, resolvedType,
8446 callingPid, callingUid);
8447 if (res == null) {
8448 return null;
8449 }
8450 if (res.record == null) {
8451 return new ComponentName("!", res.permission != null
8452 ? res.permission : "private to package");
8453 }
8454 ServiceRecord r = res.record;
8455 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008456 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008457 + r.shortName);
8458 }
8459 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008460 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008461 r.lastStartId++;
8462 if (r.lastStartId < 1) {
8463 r.lastStartId = 1;
8464 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008465 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008466 r.lastActivity = SystemClock.uptimeMillis();
8467 synchronized (r.stats.getBatteryStats()) {
8468 r.stats.startRunningLocked();
8469 }
8470 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8471 return new ComponentName("!", "Service process is bad");
8472 }
8473 return r.name;
8474 }
8475 }
8476
8477 public ComponentName startService(IApplicationThread caller, Intent service,
8478 String resolvedType) {
8479 // Refuse possible leaked file descriptors
8480 if (service != null && service.hasFileDescriptors() == true) {
8481 throw new IllegalArgumentException("File descriptors passed in Intent");
8482 }
8483
8484 synchronized(this) {
8485 final int callingPid = Binder.getCallingPid();
8486 final int callingUid = Binder.getCallingUid();
8487 final long origId = Binder.clearCallingIdentity();
8488 ComponentName res = startServiceLocked(caller, service,
8489 resolvedType, callingPid, callingUid);
8490 Binder.restoreCallingIdentity(origId);
8491 return res;
8492 }
8493 }
8494
8495 ComponentName startServiceInPackage(int uid,
8496 Intent service, String resolvedType) {
8497 synchronized(this) {
8498 final long origId = Binder.clearCallingIdentity();
8499 ComponentName res = startServiceLocked(null, service,
8500 resolvedType, -1, uid);
8501 Binder.restoreCallingIdentity(origId);
8502 return res;
8503 }
8504 }
8505
8506 public int stopService(IApplicationThread caller, Intent service,
8507 String resolvedType) {
8508 // Refuse possible leaked file descriptors
8509 if (service != null && service.hasFileDescriptors() == true) {
8510 throw new IllegalArgumentException("File descriptors passed in Intent");
8511 }
8512
8513 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008514 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 + " type=" + resolvedType);
8516
8517 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8518 if (caller != null && callerApp == null) {
8519 throw new SecurityException(
8520 "Unable to find app for caller " + caller
8521 + " (pid=" + Binder.getCallingPid()
8522 + ") when stopping service " + service);
8523 }
8524
8525 // If this service is active, make sure it is stopped.
8526 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8527 if (r != null) {
8528 if (r.record != null) {
8529 synchronized (r.record.stats.getBatteryStats()) {
8530 r.record.stats.stopRunningLocked();
8531 }
8532 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008533 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008534 final long origId = Binder.clearCallingIdentity();
8535 bringDownServiceLocked(r.record, false);
8536 Binder.restoreCallingIdentity(origId);
8537 return 1;
8538 }
8539 return -1;
8540 }
8541 }
8542
8543 return 0;
8544 }
8545
8546 public IBinder peekService(Intent service, String resolvedType) {
8547 // Refuse possible leaked file descriptors
8548 if (service != null && service.hasFileDescriptors() == true) {
8549 throw new IllegalArgumentException("File descriptors passed in Intent");
8550 }
8551
8552 IBinder ret = null;
8553
8554 synchronized(this) {
8555 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8556
8557 if (r != null) {
8558 // r.record is null if findServiceLocked() failed the caller permission check
8559 if (r.record == null) {
8560 throw new SecurityException(
8561 "Permission Denial: Accessing service " + r.record.name
8562 + " from pid=" + Binder.getCallingPid()
8563 + ", uid=" + Binder.getCallingUid()
8564 + " requires " + r.permission);
8565 }
8566 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8567 if (ib != null) {
8568 ret = ib.binder;
8569 }
8570 }
8571 }
8572
8573 return ret;
8574 }
8575
8576 public boolean stopServiceToken(ComponentName className, IBinder token,
8577 int startId) {
8578 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008579 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008580 + " " + token + " startId=" + startId);
8581 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008582 if (r != null) {
8583 if (startId >= 0) {
8584 // Asked to only stop if done with all work. Note that
8585 // to avoid leaks, we will take this as dropping all
8586 // start items up to and including this one.
8587 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8588 if (si != null) {
8589 while (r.deliveredStarts.size() > 0) {
8590 if (r.deliveredStarts.remove(0) == si) {
8591 break;
8592 }
8593 }
8594 }
8595
8596 if (r.lastStartId != startId) {
8597 return false;
8598 }
8599
8600 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008601 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008602 + " is last, but have " + r.deliveredStarts.size()
8603 + " remaining args");
8604 }
8605 }
8606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008607 synchronized (r.stats.getBatteryStats()) {
8608 r.stats.stopRunningLocked();
8609 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008610 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008611 }
8612 final long origId = Binder.clearCallingIdentity();
8613 bringDownServiceLocked(r, false);
8614 Binder.restoreCallingIdentity(origId);
8615 return true;
8616 }
8617 }
8618 return false;
8619 }
8620
8621 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008622 int id, Notification notification, boolean removeNotification) {
8623 final long origId = Binder.clearCallingIdentity();
8624 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008625 synchronized(this) {
8626 ServiceRecord r = findServiceLocked(className, token);
8627 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008628 if (id != 0) {
8629 if (notification == null) {
8630 throw new IllegalArgumentException("null notification");
8631 }
8632 if (r.foregroundId != id) {
8633 r.cancelNotification();
8634 r.foregroundId = id;
8635 }
8636 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8637 r.foregroundNoti = notification;
8638 r.isForeground = true;
8639 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008640 if (r.app != null) {
8641 updateServiceForegroundLocked(r.app, true);
8642 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008643 } else {
8644 if (r.isForeground) {
8645 r.isForeground = false;
8646 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008647 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008648 updateServiceForegroundLocked(r.app, true);
8649 }
8650 }
8651 if (removeNotification) {
8652 r.cancelNotification();
8653 r.foregroundId = 0;
8654 r.foregroundNoti = null;
8655 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008656 }
8657 }
8658 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008659 } finally {
8660 Binder.restoreCallingIdentity(origId);
8661 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008662 }
8663
8664 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
8665 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07008666 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008667 if (sr.isForeground) {
8668 anyForeground = true;
8669 break;
8670 }
8671 }
8672 if (anyForeground != proc.foregroundServices) {
8673 proc.foregroundServices = anyForeground;
8674 if (oomAdj) {
8675 updateOomAdjLocked();
8676 }
8677 }
8678 }
8679
8680 public int bindService(IApplicationThread caller, IBinder token,
8681 Intent service, String resolvedType,
8682 IServiceConnection connection, int flags) {
8683 // Refuse possible leaked file descriptors
8684 if (service != null && service.hasFileDescriptors() == true) {
8685 throw new IllegalArgumentException("File descriptors passed in Intent");
8686 }
8687
8688 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008689 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008690 + " type=" + resolvedType + " conn=" + connection.asBinder()
8691 + " flags=0x" + Integer.toHexString(flags));
8692 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8693 if (callerApp == null) {
8694 throw new SecurityException(
8695 "Unable to find app for caller " + caller
8696 + " (pid=" + Binder.getCallingPid()
8697 + ") when binding service " + service);
8698 }
8699
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008700 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008701 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008702 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008703 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008704 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008705 return 0;
8706 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008707 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008708 }
8709
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008710 int clientLabel = 0;
8711 PendingIntent clientIntent = null;
8712
8713 if (callerApp.info.uid == Process.SYSTEM_UID) {
8714 // Hacky kind of thing -- allow system stuff to tell us
8715 // what they are, so we can report this elsewhere for
8716 // others to know why certain services are running.
8717 try {
8718 clientIntent = (PendingIntent)service.getParcelableExtra(
8719 Intent.EXTRA_CLIENT_INTENT);
8720 } catch (RuntimeException e) {
8721 }
8722 if (clientIntent != null) {
8723 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
8724 if (clientLabel != 0) {
8725 // There are no useful extras in the intent, trash them.
8726 // System code calling with this stuff just needs to know
8727 // this will happen.
8728 service = service.cloneFilter();
8729 }
8730 }
8731 }
8732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008733 ServiceLookupResult res =
8734 retrieveServiceLocked(service, resolvedType,
8735 Binder.getCallingPid(), Binder.getCallingUid());
8736 if (res == null) {
8737 return 0;
8738 }
8739 if (res.record == null) {
8740 return -1;
8741 }
8742 ServiceRecord s = res.record;
8743
8744 final long origId = Binder.clearCallingIdentity();
8745
8746 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008747 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008748 + s.shortName);
8749 }
8750
8751 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
8752 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008753 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008754
8755 IBinder binder = connection.asBinder();
8756 s.connections.put(binder, c);
8757 b.connections.add(c);
8758 if (activity != null) {
8759 if (activity.connections == null) {
8760 activity.connections = new HashSet<ConnectionRecord>();
8761 }
8762 activity.connections.add(c);
8763 }
8764 b.client.connections.add(c);
8765 mServiceConnections.put(binder, c);
8766
8767 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
8768 s.lastActivity = SystemClock.uptimeMillis();
8769 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
8770 return 0;
8771 }
8772 }
8773
8774 if (s.app != null) {
8775 // This could have made the service more important.
8776 updateOomAdjLocked(s.app);
8777 }
8778
Joe Onorato8a9b2202010-02-26 18:56:32 -08008779 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008780 + ": received=" + b.intent.received
8781 + " apps=" + b.intent.apps.size()
8782 + " doRebind=" + b.intent.doRebind);
8783
8784 if (s.app != null && b.intent.received) {
8785 // Service is already running, so we can immediately
8786 // publish the connection.
8787 try {
8788 c.conn.connected(s.name, b.intent.binder);
8789 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008790 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008791 + " to connection " + c.conn.asBinder()
8792 + " (in " + c.binding.client.processName + ")", e);
8793 }
8794
8795 // If this is the first app connected back to this binding,
8796 // and the service had previously asked to be told when
8797 // rebound, then do so.
8798 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
8799 requestServiceBindingLocked(s, b.intent, true);
8800 }
8801 } else if (!b.intent.requested) {
8802 requestServiceBindingLocked(s, b.intent, false);
8803 }
8804
8805 Binder.restoreCallingIdentity(origId);
8806 }
8807
8808 return 1;
8809 }
8810
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008811 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008812 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008813 IBinder binder = c.conn.asBinder();
8814 AppBindRecord b = c.binding;
8815 ServiceRecord s = b.service;
8816 s.connections.remove(binder);
8817 b.connections.remove(c);
8818 if (c.activity != null && c.activity != skipAct) {
8819 if (c.activity.connections != null) {
8820 c.activity.connections.remove(c);
8821 }
8822 }
8823 if (b.client != skipApp) {
8824 b.client.connections.remove(c);
8825 }
8826 mServiceConnections.remove(binder);
8827
8828 if (b.connections.size() == 0) {
8829 b.intent.apps.remove(b.client);
8830 }
8831
Joe Onorato8a9b2202010-02-26 18:56:32 -08008832 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008833 + ": shouldUnbind=" + b.intent.hasBound);
8834 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
8835 && b.intent.hasBound) {
8836 try {
8837 bumpServiceExecutingLocked(s);
8838 updateOomAdjLocked(s.app);
8839 b.intent.hasBound = false;
8840 // Assume the client doesn't want to know about a rebind;
8841 // we will deal with that later if it asks for one.
8842 b.intent.doRebind = false;
8843 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
8844 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008845 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008846 serviceDoneExecutingLocked(s, true);
8847 }
8848 }
8849
8850 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
8851 bringDownServiceLocked(s, false);
8852 }
8853 }
8854
8855 public boolean unbindService(IServiceConnection connection) {
8856 synchronized (this) {
8857 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008858 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008859 ConnectionRecord r = mServiceConnections.get(binder);
8860 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008861 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008862 + connection.asBinder());
8863 return false;
8864 }
8865
8866 final long origId = Binder.clearCallingIdentity();
8867
8868 removeConnectionLocked(r, null, null);
8869
8870 if (r.binding.service.app != null) {
8871 // This could have made the service less important.
8872 updateOomAdjLocked(r.binding.service.app);
8873 }
8874
8875 Binder.restoreCallingIdentity(origId);
8876 }
8877
8878 return true;
8879 }
8880
8881 public void publishService(IBinder token, Intent intent, IBinder service) {
8882 // Refuse possible leaked file descriptors
8883 if (intent != null && intent.hasFileDescriptors() == true) {
8884 throw new IllegalArgumentException("File descriptors passed in Intent");
8885 }
8886
8887 synchronized(this) {
8888 if (!(token instanceof ServiceRecord)) {
8889 throw new IllegalArgumentException("Invalid service token");
8890 }
8891 ServiceRecord r = (ServiceRecord)token;
8892
8893 final long origId = Binder.clearCallingIdentity();
8894
Joe Onorato8a9b2202010-02-26 18:56:32 -08008895 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008896 + " " + intent + ": " + service);
8897 if (r != null) {
8898 Intent.FilterComparison filter
8899 = new Intent.FilterComparison(intent);
8900 IntentBindRecord b = r.bindings.get(filter);
8901 if (b != null && !b.received) {
8902 b.binder = service;
8903 b.requested = true;
8904 b.received = true;
8905 if (r.connections.size() > 0) {
8906 Iterator<ConnectionRecord> it
8907 = r.connections.values().iterator();
8908 while (it.hasNext()) {
8909 ConnectionRecord c = it.next();
8910 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008911 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008912 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008913 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008914 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008915 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008916 TAG, "Published intent: " + intent);
8917 continue;
8918 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008919 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008920 try {
8921 c.conn.connected(r.name, service);
8922 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008923 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008924 " to connection " + c.conn.asBinder() +
8925 " (in " + c.binding.client.processName + ")", e);
8926 }
8927 }
8928 }
8929 }
8930
8931 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
8932
8933 Binder.restoreCallingIdentity(origId);
8934 }
8935 }
8936 }
8937
8938 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
8939 // Refuse possible leaked file descriptors
8940 if (intent != null && intent.hasFileDescriptors() == true) {
8941 throw new IllegalArgumentException("File descriptors passed in Intent");
8942 }
8943
8944 synchronized(this) {
8945 if (!(token instanceof ServiceRecord)) {
8946 throw new IllegalArgumentException("Invalid service token");
8947 }
8948 ServiceRecord r = (ServiceRecord)token;
8949
8950 final long origId = Binder.clearCallingIdentity();
8951
8952 if (r != null) {
8953 Intent.FilterComparison filter
8954 = new Intent.FilterComparison(intent);
8955 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008956 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008957 + " at " + b + ": apps="
8958 + (b != null ? b.apps.size() : 0));
8959 if (b != null) {
8960 if (b.apps.size() > 0) {
8961 // Applications have already bound since the last
8962 // unbind, so just rebind right here.
8963 requestServiceBindingLocked(r, b, true);
8964 } else {
8965 // Note to tell the service the next time there is
8966 // a new client.
8967 b.doRebind = true;
8968 }
8969 }
8970
8971 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
8972
8973 Binder.restoreCallingIdentity(origId);
8974 }
8975 }
8976 }
8977
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008978 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008979 synchronized(this) {
8980 if (!(token instanceof ServiceRecord)) {
8981 throw new IllegalArgumentException("Invalid service token");
8982 }
8983 ServiceRecord r = (ServiceRecord)token;
8984 boolean inStopping = mStoppingServices.contains(token);
8985 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008986 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008987 + ": nesting=" + r.executeNesting
8988 + ", inStopping=" + inStopping);
8989 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008990 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008991 + " with incorrect token: given " + token
8992 + ", expected " + r);
8993 return;
8994 }
8995
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008996 if (type == 1) {
8997 // This is a call from a service start... take care of
8998 // book-keeping.
8999 r.callStart = true;
9000 switch (res) {
9001 case Service.START_STICKY_COMPATIBILITY:
9002 case Service.START_STICKY: {
9003 // We are done with the associated start arguments.
9004 r.findDeliveredStart(startId, true);
9005 // Don't stop if killed.
9006 r.stopIfKilled = false;
9007 break;
9008 }
9009 case Service.START_NOT_STICKY: {
9010 // We are done with the associated start arguments.
9011 r.findDeliveredStart(startId, true);
9012 if (r.lastStartId == startId) {
9013 // There is no more work, and this service
9014 // doesn't want to hang around if killed.
9015 r.stopIfKilled = true;
9016 }
9017 break;
9018 }
9019 case Service.START_REDELIVER_INTENT: {
9020 // We'll keep this item until they explicitly
9021 // call stop for it, but keep track of the fact
9022 // that it was delivered.
9023 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9024 if (si != null) {
9025 si.deliveryCount = 0;
9026 si.doneExecutingCount++;
9027 // Don't stop if killed.
9028 r.stopIfKilled = true;
9029 }
9030 break;
9031 }
9032 default:
9033 throw new IllegalArgumentException(
9034 "Unknown service start result: " + res);
9035 }
9036 if (res == Service.START_STICKY_COMPATIBILITY) {
9037 r.callStart = false;
9038 }
9039 }
9040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 final long origId = Binder.clearCallingIdentity();
9042 serviceDoneExecutingLocked(r, inStopping);
9043 Binder.restoreCallingIdentity(origId);
9044 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009045 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009046 + " with token " + token);
9047 }
9048 }
9049 }
9050
9051 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
9052 r.executeNesting--;
9053 if (r.executeNesting <= 0 && r.app != null) {
9054 r.app.executingServices.remove(r);
9055 if (r.app.executingServices.size() == 0) {
9056 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9057 }
9058 if (inStopping) {
9059 mStoppingServices.remove(r);
9060 }
9061 updateOomAdjLocked(r.app);
9062 }
9063 }
9064
9065 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009066 String anrMessage = null;
9067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009068 synchronized(this) {
9069 if (proc.executingServices.size() == 0 || proc.thread == null) {
9070 return;
9071 }
9072 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9073 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9074 ServiceRecord timeout = null;
9075 long nextTime = 0;
9076 while (it.hasNext()) {
9077 ServiceRecord sr = it.next();
9078 if (sr.executingStart < maxTime) {
9079 timeout = sr;
9080 break;
9081 }
9082 if (sr.executingStart > nextTime) {
9083 nextTime = sr.executingStart;
9084 }
9085 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009086 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009087 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009088 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009089 } else {
9090 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9091 msg.obj = proc;
9092 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9093 }
9094 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009095
9096 if (anrMessage != null) {
9097 appNotResponding(proc, null, null, anrMessage);
9098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009099 }
9100
9101 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009102 // BACKUP AND RESTORE
9103 // =========================================================
9104
9105 // Cause the target app to be launched if necessary and its backup agent
9106 // instantiated. The backup agent will invoke backupAgentCreated() on the
9107 // activity manager to announce its creation.
9108 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009109 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009110 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9111
9112 synchronized(this) {
9113 // !!! TODO: currently no check here that we're already bound
9114 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9115 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9116 synchronized (stats) {
9117 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9118 }
9119
9120 BackupRecord r = new BackupRecord(ss, app, backupMode);
9121 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9122 // startProcessLocked() returns existing proc's record if it's already running
9123 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009124 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009125 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009126 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009127 return false;
9128 }
9129
9130 r.app = proc;
9131 mBackupTarget = r;
9132 mBackupAppName = app.packageName;
9133
Christopher Tate6fa95972009-06-05 18:43:55 -07009134 // Try not to kill the process during backup
9135 updateOomAdjLocked(proc);
9136
Christopher Tate181fafa2009-05-14 11:12:14 -07009137 // If the process is already attached, schedule the creation of the backup agent now.
9138 // If it is not yet live, this will be done when it attaches to the framework.
9139 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009140 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009141 try {
9142 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9143 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009144 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009145 }
9146 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009147 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009148 }
9149 // Invariants: at this point, the target app process exists and the application
9150 // is either already running or in the process of coming up. mBackupTarget and
9151 // mBackupAppName describe the app, so that when it binds back to the AM we
9152 // know that it's scheduled for a backup-agent operation.
9153 }
9154
9155 return true;
9156 }
9157
9158 // A backup agent has just come up
9159 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009160 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009161 + " = " + agent);
9162
9163 synchronized(this) {
9164 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009165 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009166 return;
9167 }
9168
Christopher Tate043dadc2009-06-02 16:11:00 -07009169 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009170 try {
9171 IBackupManager bm = IBackupManager.Stub.asInterface(
9172 ServiceManager.getService(Context.BACKUP_SERVICE));
9173 bm.agentConnected(agentPackageName, agent);
9174 } catch (RemoteException e) {
9175 // can't happen; the backup manager service is local
9176 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009177 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009178 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009179 } finally {
9180 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009181 }
9182 }
9183 }
9184
9185 // done with this agent
9186 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009187 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009188 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009189 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009190 return;
9191 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009192
9193 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009194 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009195 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009196 return;
9197 }
9198
Christopher Tate181fafa2009-05-14 11:12:14 -07009199 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009200 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009201 return;
9202 }
9203
Christopher Tate6fa95972009-06-05 18:43:55 -07009204 ProcessRecord proc = mBackupTarget.app;
9205 mBackupTarget = null;
9206 mBackupAppName = null;
9207
9208 // Not backing this app up any more; reset its OOM adjustment
9209 updateOomAdjLocked(proc);
9210
Christopher Tatec7b31e32009-06-10 15:49:30 -07009211 // If the app crashed during backup, 'thread' will be null here
9212 if (proc.thread != null) {
9213 try {
9214 proc.thread.scheduleDestroyBackupAgent(appInfo);
9215 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009216 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009217 e.printStackTrace();
9218 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009219 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009220 }
9221 }
9222 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009223 // BROADCASTS
9224 // =========================================================
9225
Josh Bartel7f208742010-02-25 11:01:44 -06009226 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009227 List cur) {
9228 final ContentResolver resolver = mContext.getContentResolver();
9229 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9230 if (list == null) {
9231 return cur;
9232 }
9233 int N = list.size();
9234 for (int i=0; i<N; i++) {
9235 Intent intent = list.get(i);
9236 if (filter.match(resolver, intent, true, TAG) >= 0) {
9237 if (cur == null) {
9238 cur = new ArrayList<Intent>();
9239 }
9240 cur.add(intent);
9241 }
9242 }
9243 return cur;
9244 }
9245
9246 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009247 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009248 + mBroadcastsScheduled);
9249
9250 if (mBroadcastsScheduled) {
9251 return;
9252 }
9253 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9254 mBroadcastsScheduled = true;
9255 }
9256
9257 public Intent registerReceiver(IApplicationThread caller,
9258 IIntentReceiver receiver, IntentFilter filter, String permission) {
9259 synchronized(this) {
9260 ProcessRecord callerApp = null;
9261 if (caller != null) {
9262 callerApp = getRecordForAppLocked(caller);
9263 if (callerApp == null) {
9264 throw new SecurityException(
9265 "Unable to find app for caller " + caller
9266 + " (pid=" + Binder.getCallingPid()
9267 + ") when registering receiver " + receiver);
9268 }
9269 }
9270
9271 List allSticky = null;
9272
9273 // Look for any matching sticky broadcasts...
9274 Iterator actions = filter.actionsIterator();
9275 if (actions != null) {
9276 while (actions.hasNext()) {
9277 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009278 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009279 }
9280 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009281 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009282 }
9283
9284 // The first sticky in the list is returned directly back to
9285 // the client.
9286 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9287
Joe Onorato8a9b2202010-02-26 18:56:32 -08009288 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009289 + ": " + sticky);
9290
9291 if (receiver == null) {
9292 return sticky;
9293 }
9294
9295 ReceiverList rl
9296 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9297 if (rl == null) {
9298 rl = new ReceiverList(this, callerApp,
9299 Binder.getCallingPid(),
9300 Binder.getCallingUid(), receiver);
9301 if (rl.app != null) {
9302 rl.app.receivers.add(rl);
9303 } else {
9304 try {
9305 receiver.asBinder().linkToDeath(rl, 0);
9306 } catch (RemoteException e) {
9307 return sticky;
9308 }
9309 rl.linkedToDeath = true;
9310 }
9311 mRegisteredReceivers.put(receiver.asBinder(), rl);
9312 }
9313 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9314 rl.add(bf);
9315 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009316 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009317 }
9318 mReceiverResolver.addFilter(bf);
9319
9320 // Enqueue broadcasts for all existing stickies that match
9321 // this filter.
9322 if (allSticky != null) {
9323 ArrayList receivers = new ArrayList();
9324 receivers.add(bf);
9325
9326 int N = allSticky.size();
9327 for (int i=0; i<N; i++) {
9328 Intent intent = (Intent)allSticky.get(i);
9329 BroadcastRecord r = new BroadcastRecord(intent, null,
9330 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009331 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009332 if (mParallelBroadcasts.size() == 0) {
9333 scheduleBroadcastsLocked();
9334 }
9335 mParallelBroadcasts.add(r);
9336 }
9337 }
9338
9339 return sticky;
9340 }
9341 }
9342
9343 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009344 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009345
9346 boolean doNext = false;
9347
9348 synchronized(this) {
9349 ReceiverList rl
9350 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9351 if (rl != null) {
9352 if (rl.curBroadcast != null) {
9353 BroadcastRecord r = rl.curBroadcast;
9354 doNext = finishReceiverLocked(
9355 receiver.asBinder(), r.resultCode, r.resultData,
9356 r.resultExtras, r.resultAbort, true);
9357 }
9358
9359 if (rl.app != null) {
9360 rl.app.receivers.remove(rl);
9361 }
9362 removeReceiverLocked(rl);
9363 if (rl.linkedToDeath) {
9364 rl.linkedToDeath = false;
9365 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9366 }
9367 }
9368 }
9369
9370 if (!doNext) {
9371 return;
9372 }
9373
9374 final long origId = Binder.clearCallingIdentity();
9375 processNextBroadcast(false);
9376 trimApplications();
9377 Binder.restoreCallingIdentity(origId);
9378 }
9379
9380 void removeReceiverLocked(ReceiverList rl) {
9381 mRegisteredReceivers.remove(rl.receiver.asBinder());
9382 int N = rl.size();
9383 for (int i=0; i<N; i++) {
9384 mReceiverResolver.removeFilter(rl.get(i));
9385 }
9386 }
9387
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009388 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9389 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9390 ProcessRecord r = mLruProcesses.get(i);
9391 if (r.thread != null) {
9392 try {
9393 r.thread.dispatchPackageBroadcast(cmd, packages);
9394 } catch (RemoteException ex) {
9395 }
9396 }
9397 }
9398 }
9399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009400 private final int broadcastIntentLocked(ProcessRecord callerApp,
9401 String callerPackage, Intent intent, String resolvedType,
9402 IIntentReceiver resultTo, int resultCode, String resultData,
9403 Bundle map, String requiredPermission,
9404 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9405 intent = new Intent(intent);
9406
Joe Onorato8a9b2202010-02-26 18:56:32 -08009407 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009408 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9409 + " ordered=" + ordered);
9410 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009411 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009412 }
9413
9414 // Handle special intents: if this broadcast is from the package
9415 // manager about a package being removed, we need to remove all of
9416 // its activities from the history stack.
9417 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9418 intent.getAction());
9419 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9420 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009421 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009422 || uidRemoved) {
9423 if (checkComponentPermission(
9424 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9425 callingPid, callingUid, -1)
9426 == PackageManager.PERMISSION_GRANTED) {
9427 if (uidRemoved) {
9428 final Bundle intentExtras = intent.getExtras();
9429 final int uid = intentExtras != null
9430 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9431 if (uid >= 0) {
9432 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9433 synchronized (bs) {
9434 bs.removeUidStatsLocked(uid);
9435 }
9436 }
9437 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009438 // If resources are unvailble just force stop all
9439 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009440 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009441 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9442 if (list != null && (list.length > 0)) {
9443 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009444 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009445 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009446 sendPackageBroadcastLocked(
9447 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009448 }
9449 } else {
9450 Uri data = intent.getData();
9451 String ssp;
9452 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9453 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9454 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009455 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009456 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009457 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9458 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9459 new String[] {ssp});
9460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009461 }
9462 }
9463 }
9464 } else {
9465 String msg = "Permission Denial: " + intent.getAction()
9466 + " broadcast from " + callerPackage + " (pid=" + callingPid
9467 + ", uid=" + callingUid + ")"
9468 + " requires "
9469 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009470 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471 throw new SecurityException(msg);
9472 }
9473 }
9474
9475 /*
9476 * If this is the time zone changed action, queue up a message that will reset the timezone
9477 * of all currently running processes. This message will get queued up before the broadcast
9478 * happens.
9479 */
9480 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9481 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9482 }
9483
Dianne Hackborn854060af2009-07-09 18:14:31 -07009484 /*
9485 * Prevent non-system code (defined here to be non-persistent
9486 * processes) from sending protected broadcasts.
9487 */
9488 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9489 || callingUid == Process.SHELL_UID || callingUid == 0) {
9490 // Always okay.
9491 } else if (callerApp == null || !callerApp.persistent) {
9492 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009493 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009494 intent.getAction())) {
9495 String msg = "Permission Denial: not allowed to send broadcast "
9496 + intent.getAction() + " from pid="
9497 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009498 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009499 throw new SecurityException(msg);
9500 }
9501 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009502 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009503 return BROADCAST_SUCCESS;
9504 }
9505 }
9506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009507 // Add to the sticky list if requested.
9508 if (sticky) {
9509 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9510 callingPid, callingUid)
9511 != PackageManager.PERMISSION_GRANTED) {
9512 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9513 + callingPid + ", uid=" + callingUid
9514 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009515 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009516 throw new SecurityException(msg);
9517 }
9518 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009519 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009520 + " and enforce permission " + requiredPermission);
9521 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9522 }
9523 if (intent.getComponent() != null) {
9524 throw new SecurityException(
9525 "Sticky broadcasts can't target a specific component");
9526 }
9527 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9528 if (list == null) {
9529 list = new ArrayList<Intent>();
9530 mStickyBroadcasts.put(intent.getAction(), list);
9531 }
9532 int N = list.size();
9533 int i;
9534 for (i=0; i<N; i++) {
9535 if (intent.filterEquals(list.get(i))) {
9536 // This sticky already exists, replace it.
9537 list.set(i, new Intent(intent));
9538 break;
9539 }
9540 }
9541 if (i >= N) {
9542 list.add(new Intent(intent));
9543 }
9544 }
9545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009546 // Figure out who all will receive this broadcast.
9547 List receivers = null;
9548 List<BroadcastFilter> registeredReceivers = null;
9549 try {
9550 if (intent.getComponent() != null) {
9551 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009552 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009553 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009554 if (ai != null) {
9555 receivers = new ArrayList();
9556 ResolveInfo ri = new ResolveInfo();
9557 ri.activityInfo = ai;
9558 receivers.add(ri);
9559 }
9560 } else {
9561 // Need to resolve the intent to interested receivers...
9562 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9563 == 0) {
9564 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009565 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009566 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009567 }
Mihai Preda074edef2009-05-18 17:13:31 +02009568 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009569 }
9570 } catch (RemoteException ex) {
9571 // pm is in same process, this will never happen.
9572 }
9573
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009574 final boolean replacePending =
9575 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9576
Joe Onorato8a9b2202010-02-26 18:56:32 -08009577 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009578 + " replacePending=" + replacePending);
9579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009580 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9581 if (!ordered && NR > 0) {
9582 // If we are not serializing this broadcast, then send the
9583 // registered receivers separately so they don't wait for the
9584 // components to be launched.
9585 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9586 callerPackage, callingPid, callingUid, requiredPermission,
9587 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009588 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009589 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009590 TAG, "Enqueueing parallel broadcast " + r
9591 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009592 boolean replaced = false;
9593 if (replacePending) {
9594 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9595 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009596 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009597 "***** DROPPING PARALLEL: " + intent);
9598 mParallelBroadcasts.set(i, r);
9599 replaced = true;
9600 break;
9601 }
9602 }
9603 }
9604 if (!replaced) {
9605 mParallelBroadcasts.add(r);
9606 scheduleBroadcastsLocked();
9607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009608 registeredReceivers = null;
9609 NR = 0;
9610 }
9611
9612 // Merge into one list.
9613 int ir = 0;
9614 if (receivers != null) {
9615 // A special case for PACKAGE_ADDED: do not allow the package
9616 // being added to see this broadcast. This prevents them from
9617 // using this as a back door to get run as soon as they are
9618 // installed. Maybe in the future we want to have a special install
9619 // broadcast or such for apps, but we'd like to deliberately make
9620 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009621 String skipPackages[] = null;
9622 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
9623 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
9624 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
9625 Uri data = intent.getData();
9626 if (data != null) {
9627 String pkgName = data.getSchemeSpecificPart();
9628 if (pkgName != null) {
9629 skipPackages = new String[] { pkgName };
9630 }
9631 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009632 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009633 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -07009634 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009635 if (skipPackages != null && (skipPackages.length > 0)) {
9636 for (String skipPackage : skipPackages) {
9637 if (skipPackage != null) {
9638 int NT = receivers.size();
9639 for (int it=0; it<NT; it++) {
9640 ResolveInfo curt = (ResolveInfo)receivers.get(it);
9641 if (curt.activityInfo.packageName.equals(skipPackage)) {
9642 receivers.remove(it);
9643 it--;
9644 NT--;
9645 }
9646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009647 }
9648 }
9649 }
9650
9651 int NT = receivers != null ? receivers.size() : 0;
9652 int it = 0;
9653 ResolveInfo curt = null;
9654 BroadcastFilter curr = null;
9655 while (it < NT && ir < NR) {
9656 if (curt == null) {
9657 curt = (ResolveInfo)receivers.get(it);
9658 }
9659 if (curr == null) {
9660 curr = registeredReceivers.get(ir);
9661 }
9662 if (curr.getPriority() >= curt.priority) {
9663 // Insert this broadcast record into the final list.
9664 receivers.add(it, curr);
9665 ir++;
9666 curr = null;
9667 it++;
9668 NT++;
9669 } else {
9670 // Skip to the next ResolveInfo in the final list.
9671 it++;
9672 curt = null;
9673 }
9674 }
9675 }
9676 while (ir < NR) {
9677 if (receivers == null) {
9678 receivers = new ArrayList();
9679 }
9680 receivers.add(registeredReceivers.get(ir));
9681 ir++;
9682 }
9683
9684 if ((receivers != null && receivers.size() > 0)
9685 || resultTo != null) {
9686 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9687 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009688 receivers, resultTo, resultCode, resultData, map, ordered,
9689 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009690 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009691 TAG, "Enqueueing ordered broadcast " + r
9692 + ": prev had " + mOrderedBroadcasts.size());
9693 if (DEBUG_BROADCAST) {
9694 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009695 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009696 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009697 boolean replaced = false;
9698 if (replacePending) {
9699 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9700 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009701 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009702 "***** DROPPING ORDERED: " + intent);
9703 mOrderedBroadcasts.set(i, r);
9704 replaced = true;
9705 break;
9706 }
9707 }
9708 }
9709 if (!replaced) {
9710 mOrderedBroadcasts.add(r);
9711 scheduleBroadcastsLocked();
9712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009713 }
9714
9715 return BROADCAST_SUCCESS;
9716 }
9717
9718 public final int broadcastIntent(IApplicationThread caller,
9719 Intent intent, String resolvedType, IIntentReceiver resultTo,
9720 int resultCode, String resultData, Bundle map,
9721 String requiredPermission, boolean serialized, boolean sticky) {
9722 // Refuse possible leaked file descriptors
9723 if (intent != null && intent.hasFileDescriptors() == true) {
9724 throw new IllegalArgumentException("File descriptors passed in Intent");
9725 }
9726
9727 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009728 int flags = intent.getFlags();
9729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009730 if (!mSystemReady) {
9731 // if the caller really truly claims to know what they're doing, go
9732 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009733 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
9734 intent = new Intent(intent);
9735 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
9736 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -08009737 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009738 + " before boot completion");
9739 throw new IllegalStateException("Cannot broadcast before boot completed");
9740 }
9741 }
9742
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009743 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
9744 throw new IllegalArgumentException(
9745 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
9746 }
9747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009748 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9749 final int callingPid = Binder.getCallingPid();
9750 final int callingUid = Binder.getCallingUid();
9751 final long origId = Binder.clearCallingIdentity();
9752 int res = broadcastIntentLocked(callerApp,
9753 callerApp != null ? callerApp.info.packageName : null,
9754 intent, resolvedType, resultTo,
9755 resultCode, resultData, map, requiredPermission, serialized,
9756 sticky, callingPid, callingUid);
9757 Binder.restoreCallingIdentity(origId);
9758 return res;
9759 }
9760 }
9761
9762 int broadcastIntentInPackage(String packageName, int uid,
9763 Intent intent, String resolvedType, IIntentReceiver resultTo,
9764 int resultCode, String resultData, Bundle map,
9765 String requiredPermission, boolean serialized, boolean sticky) {
9766 synchronized(this) {
9767 final long origId = Binder.clearCallingIdentity();
9768 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
9769 resultTo, resultCode, resultData, map, requiredPermission,
9770 serialized, sticky, -1, uid);
9771 Binder.restoreCallingIdentity(origId);
9772 return res;
9773 }
9774 }
9775
9776 public final void unbroadcastIntent(IApplicationThread caller,
9777 Intent intent) {
9778 // Refuse possible leaked file descriptors
9779 if (intent != null && intent.hasFileDescriptors() == true) {
9780 throw new IllegalArgumentException("File descriptors passed in Intent");
9781 }
9782
9783 synchronized(this) {
9784 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
9785 != PackageManager.PERMISSION_GRANTED) {
9786 String msg = "Permission Denial: unbroadcastIntent() from pid="
9787 + Binder.getCallingPid()
9788 + ", uid=" + Binder.getCallingUid()
9789 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009790 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 throw new SecurityException(msg);
9792 }
9793 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9794 if (list != null) {
9795 int N = list.size();
9796 int i;
9797 for (i=0; i<N; i++) {
9798 if (intent.filterEquals(list.get(i))) {
9799 list.remove(i);
9800 break;
9801 }
9802 }
9803 }
9804 }
9805 }
9806
9807 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
9808 String resultData, Bundle resultExtras, boolean resultAbort,
9809 boolean explicit) {
9810 if (mOrderedBroadcasts.size() == 0) {
9811 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009812 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 }
9814 return false;
9815 }
9816 BroadcastRecord r = mOrderedBroadcasts.get(0);
9817 if (r.receiver == null) {
9818 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009819 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009820 }
9821 return false;
9822 }
9823 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009824 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009825 return false;
9826 }
9827 int state = r.state;
9828 r.state = r.IDLE;
9829 if (state == r.IDLE) {
9830 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009831 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832 }
9833 }
9834 r.receiver = null;
9835 r.intent.setComponent(null);
9836 if (r.curApp != null) {
9837 r.curApp.curReceiver = null;
9838 }
9839 if (r.curFilter != null) {
9840 r.curFilter.receiverList.curBroadcast = null;
9841 }
9842 r.curFilter = null;
9843 r.curApp = null;
9844 r.curComponent = null;
9845 r.curReceiver = null;
9846 mPendingBroadcast = null;
9847
9848 r.resultCode = resultCode;
9849 r.resultData = resultData;
9850 r.resultExtras = resultExtras;
9851 r.resultAbort = resultAbort;
9852
9853 // We will process the next receiver right now if this is finishing
9854 // an app receiver (which is always asynchronous) or after we have
9855 // come back from calling a receiver.
9856 return state == BroadcastRecord.APP_RECEIVE
9857 || state == BroadcastRecord.CALL_DONE_RECEIVE;
9858 }
9859
9860 public void finishReceiver(IBinder who, int resultCode, String resultData,
9861 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009862 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009863
9864 // Refuse possible leaked file descriptors
9865 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
9866 throw new IllegalArgumentException("File descriptors passed in Bundle");
9867 }
9868
9869 boolean doNext;
9870
9871 final long origId = Binder.clearCallingIdentity();
9872
9873 synchronized(this) {
9874 doNext = finishReceiverLocked(
9875 who, resultCode, resultData, resultExtras, resultAbort, true);
9876 }
9877
9878 if (doNext) {
9879 processNextBroadcast(false);
9880 }
9881 trimApplications();
9882
9883 Binder.restoreCallingIdentity(origId);
9884 }
9885
9886 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
9887 if (r.nextReceiver > 0) {
9888 Object curReceiver = r.receivers.get(r.nextReceiver-1);
9889 if (curReceiver instanceof BroadcastFilter) {
9890 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -08009891 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 System.identityHashCode(r),
9893 r.intent.getAction(),
9894 r.nextReceiver - 1,
9895 System.identityHashCode(bf));
9896 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08009897 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009898 System.identityHashCode(r),
9899 r.intent.getAction(),
9900 r.nextReceiver - 1,
9901 ((ResolveInfo)curReceiver).toString());
9902 }
9903 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009904 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009906 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009907 System.identityHashCode(r),
9908 r.intent.getAction(),
9909 r.nextReceiver,
9910 "NONE");
9911 }
9912 }
9913
9914 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009915 ProcessRecord app = null;
9916 String anrMessage = null;
9917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009918 synchronized (this) {
9919 if (mOrderedBroadcasts.size() == 0) {
9920 return;
9921 }
9922 long now = SystemClock.uptimeMillis();
9923 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -08009924 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009925 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009926 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -08009927 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009928 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -08009929 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009930 return;
9931 }
9932
Joe Onorato8a9b2202010-02-26 18:56:32 -08009933 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -08009934 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009935 r.anrCount++;
9936
9937 // Current receiver has passed its expiration date.
9938 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009939 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009940 return;
9941 }
9942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009944 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009945 logBroadcastReceiverDiscard(r);
9946 if (curReceiver instanceof BroadcastFilter) {
9947 BroadcastFilter bf = (BroadcastFilter)curReceiver;
9948 if (bf.receiverList.pid != 0
9949 && bf.receiverList.pid != MY_PID) {
9950 synchronized (this.mPidsSelfLocked) {
9951 app = this.mPidsSelfLocked.get(
9952 bf.receiverList.pid);
9953 }
9954 }
9955 } else {
9956 app = r.curApp;
9957 }
9958
9959 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009960 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009961 }
9962
9963 if (mPendingBroadcast == r) {
9964 mPendingBroadcast = null;
9965 }
9966
9967 // Move on to the next receiver.
9968 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9969 r.resultExtras, r.resultAbort, true);
9970 scheduleBroadcastsLocked();
9971 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009972
9973 if (anrMessage != null) {
9974 appNotResponding(app, null, null, anrMessage);
9975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 }
9977
9978 private final void processCurBroadcastLocked(BroadcastRecord r,
9979 ProcessRecord app) throws RemoteException {
9980 if (app.thread == null) {
9981 throw new RemoteException();
9982 }
9983 r.receiver = app.thread.asBinder();
9984 r.curApp = app;
9985 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009986 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009987
9988 // Tell the application to launch this receiver.
9989 r.intent.setComponent(r.curComponent);
9990
9991 boolean started = false;
9992 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009993 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009994 "Delivering to component " + r.curComponent
9995 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009996 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009997 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
9998 r.resultCode, r.resultData, r.resultExtras, r.ordered);
9999 started = true;
10000 } finally {
10001 if (!started) {
10002 r.receiver = null;
10003 r.curApp = null;
10004 app.curReceiver = null;
10005 }
10006 }
10007
10008 }
10009
10010 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010011 Intent intent, int resultCode, String data, Bundle extras,
10012 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010013 if (app != null && app.thread != null) {
10014 // If we have an app thread, do the call through that so it is
10015 // correctly ordered with other one-way calls.
10016 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010017 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010018 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010019 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010020 }
10021 }
10022
10023 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10024 BroadcastFilter filter, boolean ordered) {
10025 boolean skip = false;
10026 if (filter.requiredPermission != null) {
10027 int perm = checkComponentPermission(filter.requiredPermission,
10028 r.callingPid, r.callingUid, -1);
10029 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010030 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010031 + r.intent.toString()
10032 + " from " + r.callerPackage + " (pid="
10033 + r.callingPid + ", uid=" + r.callingUid + ")"
10034 + " requires " + filter.requiredPermission
10035 + " due to registered receiver " + filter);
10036 skip = true;
10037 }
10038 }
10039 if (r.requiredPermission != null) {
10040 int perm = checkComponentPermission(r.requiredPermission,
10041 filter.receiverList.pid, filter.receiverList.uid, -1);
10042 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010043 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010044 + r.intent.toString()
10045 + " to " + filter.receiverList.app
10046 + " (pid=" + filter.receiverList.pid
10047 + ", uid=" + filter.receiverList.uid + ")"
10048 + " requires " + r.requiredPermission
10049 + " due to sender " + r.callerPackage
10050 + " (uid " + r.callingUid + ")");
10051 skip = true;
10052 }
10053 }
10054
10055 if (!skip) {
10056 // If this is not being sent as an ordered broadcast, then we
10057 // don't want to touch the fields that keep track of the current
10058 // state of ordered broadcasts.
10059 if (ordered) {
10060 r.receiver = filter.receiverList.receiver.asBinder();
10061 r.curFilter = filter;
10062 filter.receiverList.curBroadcast = r;
10063 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010064 if (filter.receiverList.app != null) {
10065 // Bump hosting application to no longer be in background
10066 // scheduling class. Note that we can't do that if there
10067 // isn't an app... but we can only be in that case for
10068 // things that directly call the IActivityManager API, which
10069 // are already core system stuff so don't matter for this.
10070 r.curApp = filter.receiverList.app;
10071 filter.receiverList.app.curReceiver = r;
10072 updateOomAdjLocked();
10073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010074 }
10075 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010076 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010077 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010078 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010079 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010080 }
10081 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10082 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010083 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010084 if (ordered) {
10085 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10086 }
10087 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010088 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010089 if (ordered) {
10090 r.receiver = null;
10091 r.curFilter = null;
10092 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010093 if (filter.receiverList.app != null) {
10094 filter.receiverList.app.curReceiver = null;
10095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010096 }
10097 }
10098 }
10099 }
10100
Dianne Hackborn12527f92009-11-11 17:39:50 -080010101 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10102 if (r.callingUid < 0) {
10103 // This was from a registerReceiver() call; ignore it.
10104 return;
10105 }
10106 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10107 MAX_BROADCAST_HISTORY-1);
10108 r.finishTime = SystemClock.uptimeMillis();
10109 mBroadcastHistory[0] = r;
10110 }
10111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010112 private final void processNextBroadcast(boolean fromMsg) {
10113 synchronized(this) {
10114 BroadcastRecord r;
10115
Joe Onorato8a9b2202010-02-26 18:56:32 -080010116 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010117 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010118 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010119
10120 updateCpuStats();
10121
10122 if (fromMsg) {
10123 mBroadcastsScheduled = false;
10124 }
10125
10126 // First, deliver any non-serialized broadcasts right away.
10127 while (mParallelBroadcasts.size() > 0) {
10128 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010129 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010130 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010131 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010132 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010133 for (int i=0; i<N; i++) {
10134 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010135 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010136 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010137 + target + ": " + r);
10138 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10139 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010140 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010141 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010142 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010143 }
10144
10145 // Now take care of the next serialized one...
10146
10147 // If we are waiting for a process to come up to handle the next
10148 // broadcast, then do nothing at this point. Just in case, we
10149 // check that the process we're waiting for still exists.
10150 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010151 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010152 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010153 + mPendingBroadcast.curApp);
10154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010155
10156 boolean isDead;
10157 synchronized (mPidsSelfLocked) {
10158 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10159 }
10160 if (!isDead) {
10161 // It's still alive, so keep waiting
10162 return;
10163 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010164 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010165 + " died before responding to broadcast");
10166 mPendingBroadcast = null;
10167 }
10168 }
10169
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010170 boolean looped = false;
10171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010172 do {
10173 if (mOrderedBroadcasts.size() == 0) {
10174 // No more broadcasts pending, so all done!
10175 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010176 if (looped) {
10177 // If we had finished the last ordered broadcast, then
10178 // make sure all processes have correct oom and sched
10179 // adjustments.
10180 updateOomAdjLocked();
10181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 return;
10183 }
10184 r = mOrderedBroadcasts.get(0);
10185 boolean forceReceive = false;
10186
10187 // Ensure that even if something goes awry with the timeout
10188 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010189 // and continue to make progress.
10190 //
10191 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10192 // receivers don't get executed with with timeouts. They're intended for
10193 // one time heavy lifting after system upgrades and can take
10194 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010195 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010196 if (mSystemReady && r.dispatchTime > 0) {
10197 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010198 if ((numReceivers > 0) &&
10199 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010200 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010201 + " now=" + now
10202 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010203 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010204 + " intent=" + r.intent
10205 + " numReceivers=" + numReceivers
10206 + " nextReceiver=" + r.nextReceiver
10207 + " state=" + r.state);
10208 broadcastTimeout(); // forcibly finish this broadcast
10209 forceReceive = true;
10210 r.state = BroadcastRecord.IDLE;
10211 }
10212 }
10213
10214 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010215 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010216 "processNextBroadcast() called when not idle (state="
10217 + r.state + ")");
10218 return;
10219 }
10220
10221 if (r.receivers == null || r.nextReceiver >= numReceivers
10222 || r.resultAbort || forceReceive) {
10223 // No more receivers for this broadcast! Send the final
10224 // result if requested...
10225 if (r.resultTo != null) {
10226 try {
10227 if (DEBUG_BROADCAST) {
10228 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010229 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 + " seq=" + seq + " app=" + r.callerApp);
10231 }
10232 performReceive(r.callerApp, r.resultTo,
10233 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010234 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010235 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010236 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010237 }
10238 }
10239
Joe Onorato8a9b2202010-02-26 18:56:32 -080010240 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010241 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10242
Joe Onorato8a9b2202010-02-26 18:56:32 -080010243 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010244 + r);
10245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010246 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010247 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010248 mOrderedBroadcasts.remove(0);
10249 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010250 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 continue;
10252 }
10253 } while (r == null);
10254
10255 // Get the next receiver...
10256 int recIdx = r.nextReceiver++;
10257
10258 // Keep track of when this receiver started, and make sure there
10259 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010260 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010261 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010262 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010263
Joe Onorato8a9b2202010-02-26 18:56:32 -080010264 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010265 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010266 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010267 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010268 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010269 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010270 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010271 }
10272
10273 Object nextReceiver = r.receivers.get(recIdx);
10274 if (nextReceiver instanceof BroadcastFilter) {
10275 // Simple case: this is a registered receiver who gets
10276 // a direct call.
10277 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010278 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010279 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010280 + filter + ": " + r);
10281 deliverToRegisteredReceiver(r, filter, r.ordered);
10282 if (r.receiver == null || !r.ordered) {
10283 // The receiver has already finished, so schedule to
10284 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010285 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10286 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010287 r.state = BroadcastRecord.IDLE;
10288 scheduleBroadcastsLocked();
10289 }
10290 return;
10291 }
10292
10293 // Hard case: need to instantiate the receiver, possibly
10294 // starting its application process to host it.
10295
10296 ResolveInfo info =
10297 (ResolveInfo)nextReceiver;
10298
10299 boolean skip = false;
10300 int perm = checkComponentPermission(info.activityInfo.permission,
10301 r.callingPid, r.callingUid,
10302 info.activityInfo.exported
10303 ? -1 : info.activityInfo.applicationInfo.uid);
10304 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010305 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010306 + r.intent.toString()
10307 + " from " + r.callerPackage + " (pid=" + r.callingPid
10308 + ", uid=" + r.callingUid + ")"
10309 + " requires " + info.activityInfo.permission
10310 + " due to receiver " + info.activityInfo.packageName
10311 + "/" + info.activityInfo.name);
10312 skip = true;
10313 }
10314 if (r.callingUid != Process.SYSTEM_UID &&
10315 r.requiredPermission != null) {
10316 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010317 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010318 checkPermission(r.requiredPermission,
10319 info.activityInfo.applicationInfo.packageName);
10320 } catch (RemoteException e) {
10321 perm = PackageManager.PERMISSION_DENIED;
10322 }
10323 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010324 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010325 + r.intent + " to "
10326 + info.activityInfo.applicationInfo.packageName
10327 + " requires " + r.requiredPermission
10328 + " due to sender " + r.callerPackage
10329 + " (uid " + r.callingUid + ")");
10330 skip = true;
10331 }
10332 }
10333 if (r.curApp != null && r.curApp.crashing) {
10334 // If the target process is crashing, just skip it.
10335 skip = true;
10336 }
10337
10338 if (skip) {
10339 r.receiver = null;
10340 r.curFilter = null;
10341 r.state = BroadcastRecord.IDLE;
10342 scheduleBroadcastsLocked();
10343 return;
10344 }
10345
10346 r.state = BroadcastRecord.APP_RECEIVE;
10347 String targetProcess = info.activityInfo.processName;
10348 r.curComponent = new ComponentName(
10349 info.activityInfo.applicationInfo.packageName,
10350 info.activityInfo.name);
10351 r.curReceiver = info.activityInfo;
10352
10353 // Is this receiver's application already running?
10354 ProcessRecord app = getProcessRecordLocked(targetProcess,
10355 info.activityInfo.applicationInfo.uid);
10356 if (app != null && app.thread != null) {
10357 try {
10358 processCurBroadcastLocked(r, app);
10359 return;
10360 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010361 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010362 + r.curComponent, e);
10363 }
10364
10365 // If a dead object exception was thrown -- fall through to
10366 // restart the application.
10367 }
10368
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010369 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010370 if ((r.curApp=startProcessLocked(targetProcess,
10371 info.activityInfo.applicationInfo, true,
10372 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010373 "broadcast", r.curComponent,
10374 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10375 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010376 // Ah, this recipient is unavailable. Finish it if necessary,
10377 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010378 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010379 + info.activityInfo.applicationInfo.packageName + "/"
10380 + info.activityInfo.applicationInfo.uid + " for broadcast "
10381 + r.intent + ": process is bad");
10382 logBroadcastReceiverDiscard(r);
10383 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10384 r.resultExtras, r.resultAbort, true);
10385 scheduleBroadcastsLocked();
10386 r.state = BroadcastRecord.IDLE;
10387 return;
10388 }
10389
10390 mPendingBroadcast = r;
10391 }
10392 }
10393
10394 // =========================================================
10395 // INSTRUMENTATION
10396 // =========================================================
10397
10398 public boolean startInstrumentation(ComponentName className,
10399 String profileFile, int flags, Bundle arguments,
10400 IInstrumentationWatcher watcher) {
10401 // Refuse possible leaked file descriptors
10402 if (arguments != null && arguments.hasFileDescriptors()) {
10403 throw new IllegalArgumentException("File descriptors passed in Bundle");
10404 }
10405
10406 synchronized(this) {
10407 InstrumentationInfo ii = null;
10408 ApplicationInfo ai = null;
10409 try {
10410 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010411 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010412 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010413 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010414 } catch (PackageManager.NameNotFoundException e) {
10415 }
10416 if (ii == null) {
10417 reportStartInstrumentationFailure(watcher, className,
10418 "Unable to find instrumentation info for: " + className);
10419 return false;
10420 }
10421 if (ai == null) {
10422 reportStartInstrumentationFailure(watcher, className,
10423 "Unable to find instrumentation target package: " + ii.targetPackage);
10424 return false;
10425 }
10426
10427 int match = mContext.getPackageManager().checkSignatures(
10428 ii.targetPackage, ii.packageName);
10429 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10430 String msg = "Permission Denial: starting instrumentation "
10431 + className + " from pid="
10432 + Binder.getCallingPid()
10433 + ", uid=" + Binder.getCallingPid()
10434 + " not allowed because package " + ii.packageName
10435 + " does not have a signature matching the target "
10436 + ii.targetPackage;
10437 reportStartInstrumentationFailure(watcher, className, msg);
10438 throw new SecurityException(msg);
10439 }
10440
10441 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010442 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 ProcessRecord app = addAppLocked(ai);
10444 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010445 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446 app.instrumentationProfileFile = profileFile;
10447 app.instrumentationArguments = arguments;
10448 app.instrumentationWatcher = watcher;
10449 app.instrumentationResultClass = className;
10450 Binder.restoreCallingIdentity(origId);
10451 }
10452
10453 return true;
10454 }
10455
10456 /**
10457 * Report errors that occur while attempting to start Instrumentation. Always writes the
10458 * error to the logs, but if somebody is watching, send the report there too. This enables
10459 * the "am" command to report errors with more information.
10460 *
10461 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10462 * @param cn The component name of the instrumentation.
10463 * @param report The error report.
10464 */
10465 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10466 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010467 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010468 try {
10469 if (watcher != null) {
10470 Bundle results = new Bundle();
10471 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10472 results.putString("Error", report);
10473 watcher.instrumentationStatus(cn, -1, results);
10474 }
10475 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010476 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010477 }
10478 }
10479
10480 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10481 if (app.instrumentationWatcher != null) {
10482 try {
10483 // NOTE: IInstrumentationWatcher *must* be oneway here
10484 app.instrumentationWatcher.instrumentationFinished(
10485 app.instrumentationClass,
10486 resultCode,
10487 results);
10488 } catch (RemoteException e) {
10489 }
10490 }
10491 app.instrumentationWatcher = null;
10492 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010493 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010494 app.instrumentationProfileFile = null;
10495 app.instrumentationArguments = null;
10496
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010497 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010498 }
10499
10500 public void finishInstrumentation(IApplicationThread target,
10501 int resultCode, Bundle results) {
10502 // Refuse possible leaked file descriptors
10503 if (results != null && results.hasFileDescriptors()) {
10504 throw new IllegalArgumentException("File descriptors passed in Intent");
10505 }
10506
10507 synchronized(this) {
10508 ProcessRecord app = getRecordForAppLocked(target);
10509 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010510 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010511 return;
10512 }
10513 final long origId = Binder.clearCallingIdentity();
10514 finishInstrumentationLocked(app, resultCode, results);
10515 Binder.restoreCallingIdentity(origId);
10516 }
10517 }
10518
10519 // =========================================================
10520 // CONFIGURATION
10521 // =========================================================
10522
10523 public ConfigurationInfo getDeviceConfigurationInfo() {
10524 ConfigurationInfo config = new ConfigurationInfo();
10525 synchronized (this) {
10526 config.reqTouchScreen = mConfiguration.touchscreen;
10527 config.reqKeyboardType = mConfiguration.keyboard;
10528 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010529 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10530 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010531 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10532 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010533 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10534 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010535 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10536 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010537 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010538 }
10539 return config;
10540 }
10541
10542 public Configuration getConfiguration() {
10543 Configuration ci;
10544 synchronized(this) {
10545 ci = new Configuration(mConfiguration);
10546 }
10547 return ci;
10548 }
10549
10550 public void updateConfiguration(Configuration values) {
10551 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10552 "updateConfiguration()");
10553
10554 synchronized(this) {
10555 if (values == null && mWindowManager != null) {
10556 // sentinel: fetch the current configuration from the window manager
10557 values = mWindowManager.computeNewConfiguration();
10558 }
10559
10560 final long origId = Binder.clearCallingIdentity();
10561 updateConfigurationLocked(values, null);
10562 Binder.restoreCallingIdentity(origId);
10563 }
10564 }
10565
10566 /**
10567 * Do either or both things: (1) change the current configuration, and (2)
10568 * make sure the given activity is running with the (now) current
10569 * configuration. Returns true if the activity has been left running, or
10570 * false if <var>starting</var> is being destroyed to match the new
10571 * configuration.
10572 */
10573 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010574 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010575 int changes = 0;
10576
10577 boolean kept = true;
10578
10579 if (values != null) {
10580 Configuration newConfig = new Configuration(mConfiguration);
10581 changes = newConfig.updateFrom(values);
10582 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010583 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010584 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 }
10586
Doug Zongker2bec3d42009-12-04 12:52:44 -080010587 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010588
10589 if (values.locale != null) {
10590 saveLocaleLocked(values.locale,
10591 !values.locale.equals(mConfiguration.locale),
10592 values.userSetLocale);
10593 }
10594
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010595 mConfigurationSeq++;
10596 if (mConfigurationSeq <= 0) {
10597 mConfigurationSeq = 1;
10598 }
10599 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010600 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010601 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010602
10603 AttributeCache ac = AttributeCache.instance();
10604 if (ac != null) {
10605 ac.updateConfiguration(mConfiguration);
10606 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010607
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010608 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10609 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10610 msg.obj = new Configuration(mConfiguration);
10611 mHandler.sendMessage(msg);
10612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010613
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010614 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10615 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010616 try {
10617 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010618 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010619 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010620 app.thread.scheduleConfigurationChanged(mConfiguration);
10621 }
10622 } catch (Exception e) {
10623 }
10624 }
10625 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010626 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
10627 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010628 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
10629 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080010630 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
10631 broadcastIntentLocked(null, null,
10632 new Intent(Intent.ACTION_LOCALE_CHANGED),
10633 null, null, 0, null, null,
10634 null, false, false, MY_PID, Process.SYSTEM_UID);
10635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010636 }
10637 }
10638
10639 if (changes != 0 && starting == null) {
10640 // If the configuration changed, and the caller is not already
10641 // in the process of starting an activity, then find the top
10642 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010643 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010644 }
10645
10646 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010647 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010648 if (kept) {
10649 // If this didn't result in the starting activity being
10650 // destroyed, then we need to make sure at this point that all
10651 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010652 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010653 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010654 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010655 }
10656 }
10657
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010658 if (values != null && mWindowManager != null) {
10659 mWindowManager.setNewConfiguration(mConfiguration);
10660 }
10661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010662 return kept;
10663 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010664
10665 /**
10666 * Save the locale. You must be inside a synchronized (this) block.
10667 */
10668 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
10669 if(isDiff) {
10670 SystemProperties.set("user.language", l.getLanguage());
10671 SystemProperties.set("user.region", l.getCountry());
10672 }
10673
10674 if(isPersist) {
10675 SystemProperties.set("persist.sys.language", l.getLanguage());
10676 SystemProperties.set("persist.sys.country", l.getCountry());
10677 SystemProperties.set("persist.sys.localevar", l.getVariant());
10678 }
10679 }
10680
10681 // =========================================================
10682 // LIFETIME MANAGEMENT
10683 // =========================================================
10684
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010685 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
10686 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010687 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010688 // This adjustment has already been computed. If we are calling
10689 // from the top, we may have already computed our adjustment with
10690 // an earlier hidden adjustment that isn't really for us... if
10691 // so, use the new hidden adjustment.
10692 if (!recursed && app.hidden) {
10693 app.curAdj = hiddenAdj;
10694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010695 return app.curAdj;
10696 }
10697
10698 if (app.thread == null) {
10699 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010700 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010701 return (app.curAdj=EMPTY_APP_ADJ);
10702 }
10703
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010704 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
10705 // The max adjustment doesn't allow this app to be anything
10706 // below foreground, so it is not worth doing work for it.
10707 app.adjType = "fixed";
10708 app.adjSeq = mAdjSeq;
10709 app.curRawAdj = app.maxAdj;
10710 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
10711 return (app.curAdj=app.maxAdj);
10712 }
10713
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010714 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010715 app.adjSource = null;
10716 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010717 app.empty = false;
10718 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010719
The Android Open Source Project4df24232009-03-05 14:34:35 -080010720 // Determine the importance of the process, starting with most
10721 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010722 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010723 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010724 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010725 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010726 // The last app on the list is the foreground app.
10727 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010728 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010729 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010730 } else if (app.instrumentationClass != null) {
10731 // Don't want to kill running instrumentation.
10732 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010733 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010734 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010735 } else if (app.persistentActivities > 0) {
10736 // Special persistent activities... shouldn't be used these days.
10737 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010738 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010739 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010740 } else if (app.curReceiver != null ||
10741 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
10742 // An app that is currently receiving a broadcast also
10743 // counts as being in the foreground.
10744 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010745 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010746 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010747 } else if (app.executingServices.size() > 0) {
10748 // An app that is currently executing a service callback also
10749 // counts as being in the foreground.
10750 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010751 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010752 app.adjType = "exec-service";
10753 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010754 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010755 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010756 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010757 app.adjType = "foreground-service";
10758 } else if (app.forcingToForeground != null) {
10759 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010760 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010761 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010762 app.adjType = "force-foreground";
10763 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010764 } else if (app == mHeavyWeightProcess) {
10765 // We don't want to kill the current heavy-weight process.
10766 adj = HEAVY_WEIGHT_APP_ADJ;
10767 schedGroup = Process.THREAD_GROUP_DEFAULT;
10768 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080010769 } else if (app == mHomeProcess) {
10770 // This process is hosting what we currently consider to be the
10771 // home app, so we don't want to let it go into the background.
10772 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010773 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010774 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010775 } else if ((N=app.activities.size()) != 0) {
10776 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010777 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010778 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010779 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010780 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010781 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010783 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010784 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010785 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010786 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010787 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010788 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789 break;
10790 }
10791 }
10792 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010793 // A very not-needed process. If this is lower in the lru list,
10794 // we will push it in to the empty bucket.
10795 app.hidden = true;
10796 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010797 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010798 adj = hiddenAdj;
10799 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010800 }
10801
Joe Onorato8a9b2202010-02-26 18:56:32 -080010802 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010803
The Android Open Source Project4df24232009-03-05 14:34:35 -080010804 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 // there are applications dependent on our services or providers, but
10806 // this gives us a baseline and makes sure we don't get into an
10807 // infinite recursion.
10808 app.adjSeq = mAdjSeq;
10809 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010810
Christopher Tate6fa95972009-06-05 18:43:55 -070010811 if (mBackupTarget != null && app == mBackupTarget.app) {
10812 // If possible we want to avoid killing apps while they're being backed up
10813 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010814 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070010815 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010816 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010817 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070010818 }
10819 }
10820
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010821 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
10822 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010823 final long now = SystemClock.uptimeMillis();
10824 // This process is more important if the top activity is
10825 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010826 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010828 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829 if (s.startRequested) {
10830 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
10831 // This service has seen some activity within
10832 // recent memory, so we will keep its process ahead
10833 // of the background processes.
10834 if (adj > SECONDARY_SERVER_ADJ) {
10835 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010836 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010837 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010838 }
10839 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080010840 // If we have let the service slide into the background
10841 // state, still have some text describing what it is doing
10842 // even though the service no longer has an impact.
10843 if (adj > SECONDARY_SERVER_ADJ) {
10844 app.adjType = "started-bg-services";
10845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010846 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010847 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
10848 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010849 Iterator<ConnectionRecord> kt
10850 = s.connections.values().iterator();
10851 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
10852 // XXX should compute this based on the max of
10853 // all connected clients.
10854 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070010855 if (cr.binding.client == app) {
10856 // Binding to ourself is not interesting.
10857 continue;
10858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10860 ProcessRecord client = cr.binding.client;
10861 int myHiddenAdj = hiddenAdj;
10862 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010863 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 myHiddenAdj = client.hiddenAdj;
10865 } else {
10866 myHiddenAdj = VISIBLE_APP_ADJ;
10867 }
10868 }
10869 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010870 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010871 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010872 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010873 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010874 if (!client.hidden) {
10875 app.hidden = false;
10876 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010877 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010878 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
10879 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010880 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070010881 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010883 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
10884 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
10885 schedGroup = Process.THREAD_GROUP_DEFAULT;
10886 }
10887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010888 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010889 ActivityRecord a = cr.activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010890 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010891 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010892 //}
10893 if (a != null && adj > FOREGROUND_APP_ADJ &&
10894 (a.state == ActivityState.RESUMED
10895 || a.state == ActivityState.PAUSING)) {
10896 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010897 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010898 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010899 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010900 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
10901 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010902 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070010903 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010904 }
10905 }
10906 }
10907 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010908
10909 // Finally, f this process has active services running in it, we
10910 // would like to avoid killing it unless it would prevent the current
10911 // application from running. By default we put the process in
10912 // with the rest of the background processes; as we scan through
10913 // its services we may bump it up from there.
10914 if (adj > hiddenAdj) {
10915 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010916 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010917 app.adjType = "bg-services";
10918 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010919 }
10920
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010921 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
10922 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010923 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010924 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
10925 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010926 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927 if (cpr.clients.size() != 0) {
10928 Iterator<ProcessRecord> kt = cpr.clients.iterator();
10929 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
10930 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070010931 if (client == app) {
10932 // Being our own client is not interesting.
10933 continue;
10934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010935 int myHiddenAdj = hiddenAdj;
10936 if (myHiddenAdj > client.hiddenAdj) {
10937 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
10938 myHiddenAdj = client.hiddenAdj;
10939 } else {
10940 myHiddenAdj = FOREGROUND_APP_ADJ;
10941 }
10942 }
10943 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010944 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010945 if (adj > clientAdj) {
10946 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010947 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010948 if (!client.hidden) {
10949 app.hidden = false;
10950 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010951 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010952 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
10953 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010954 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070010955 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010956 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010957 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
10958 schedGroup = Process.THREAD_GROUP_DEFAULT;
10959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 }
10961 }
10962 // If the provider has external (non-framework) process
10963 // dependencies, ensure that its adjustment is at least
10964 // FOREGROUND_APP_ADJ.
10965 if (cpr.externals != 0) {
10966 if (adj > FOREGROUND_APP_ADJ) {
10967 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010968 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010969 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010970 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070010971 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010972 }
10973 }
10974 }
10975 }
10976
10977 app.curRawAdj = adj;
10978
Joe Onorato8a9b2202010-02-26 18:56:32 -080010979 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
10981 if (adj > app.maxAdj) {
10982 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010983 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010984 schedGroup = Process.THREAD_GROUP_DEFAULT;
10985 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010986 }
10987
10988 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010989 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070010990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010991 return adj;
10992 }
10993
10994 /**
10995 * Ask a given process to GC right now.
10996 */
10997 final void performAppGcLocked(ProcessRecord app) {
10998 try {
10999 app.lastRequestedGc = SystemClock.uptimeMillis();
11000 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011001 if (app.reportLowMemory) {
11002 app.reportLowMemory = false;
11003 app.thread.scheduleLowMemory();
11004 } else {
11005 app.thread.processInBackground();
11006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011007 }
11008 } catch (Exception e) {
11009 // whatever.
11010 }
11011 }
11012
11013 /**
11014 * Returns true if things are idle enough to perform GCs.
11015 */
Josh Bartel7f208742010-02-25 11:01:44 -060011016 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017 return mParallelBroadcasts.size() == 0
11018 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011019 && (mSleeping || (mMainStack.mResumedActivity != null &&
11020 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011021 }
11022
11023 /**
11024 * Perform GCs on all processes that are waiting for it, but only
11025 * if things are idle.
11026 */
11027 final void performAppGcsLocked() {
11028 final int N = mProcessesToGc.size();
11029 if (N <= 0) {
11030 return;
11031 }
Josh Bartel7f208742010-02-25 11:01:44 -060011032 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011033 while (mProcessesToGc.size() > 0) {
11034 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011035 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011036 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11037 <= SystemClock.uptimeMillis()) {
11038 // To avoid spamming the system, we will GC processes one
11039 // at a time, waiting a few seconds between each.
11040 performAppGcLocked(proc);
11041 scheduleAppGcsLocked();
11042 return;
11043 } else {
11044 // It hasn't been long enough since we last GCed this
11045 // process... put it in the list to wait for its time.
11046 addProcessToGcListLocked(proc);
11047 break;
11048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049 }
11050 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011051
11052 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 }
11054 }
11055
11056 /**
11057 * If all looks good, perform GCs on all processes waiting for them.
11058 */
11059 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011060 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011061 performAppGcsLocked();
11062 return;
11063 }
11064 // Still not idle, wait some more.
11065 scheduleAppGcsLocked();
11066 }
11067
11068 /**
11069 * Schedule the execution of all pending app GCs.
11070 */
11071 final void scheduleAppGcsLocked() {
11072 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011073
11074 if (mProcessesToGc.size() > 0) {
11075 // Schedule a GC for the time to the next process.
11076 ProcessRecord proc = mProcessesToGc.get(0);
11077 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11078
11079 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11080 long now = SystemClock.uptimeMillis();
11081 if (when < (now+GC_TIMEOUT)) {
11082 when = now + GC_TIMEOUT;
11083 }
11084 mHandler.sendMessageAtTime(msg, when);
11085 }
11086 }
11087
11088 /**
11089 * Add a process to the array of processes waiting to be GCed. Keeps the
11090 * list in sorted order by the last GC time. The process can't already be
11091 * on the list.
11092 */
11093 final void addProcessToGcListLocked(ProcessRecord proc) {
11094 boolean added = false;
11095 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11096 if (mProcessesToGc.get(i).lastRequestedGc <
11097 proc.lastRequestedGc) {
11098 added = true;
11099 mProcessesToGc.add(i+1, proc);
11100 break;
11101 }
11102 }
11103 if (!added) {
11104 mProcessesToGc.add(0, proc);
11105 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011106 }
11107
11108 /**
11109 * Set up to ask a process to GC itself. This will either do it
11110 * immediately, or put it on the list of processes to gc the next
11111 * time things are idle.
11112 */
11113 final void scheduleAppGcLocked(ProcessRecord app) {
11114 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011115 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011116 return;
11117 }
11118 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011119 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011120 scheduleAppGcsLocked();
11121 }
11122 }
11123
11124 private final boolean updateOomAdjLocked(
11125 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11126 app.hiddenAdj = hiddenAdj;
11127
11128 if (app.thread == null) {
11129 return true;
11130 }
11131
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011132 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011133
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011134 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011135 if (app.curRawAdj != app.setRawAdj) {
11136 if (app.curRawAdj > FOREGROUND_APP_ADJ
11137 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11138 // If this app is transitioning from foreground to
11139 // non-foreground, have it do a gc.
11140 scheduleAppGcLocked(app);
11141 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11142 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11143 // Likewise do a gc when an app is moving in to the
11144 // background (such as a service stopping).
11145 scheduleAppGcLocked(app);
11146 }
11147 app.setRawAdj = app.curRawAdj;
11148 }
11149 if (adj != app.setAdj) {
11150 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011151 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 TAG, "Set app " + app.processName +
11153 " oom adj to " + adj);
11154 app.setAdj = adj;
11155 } else {
11156 return false;
11157 }
11158 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011159 if (app.setSchedGroup != app.curSchedGroup) {
11160 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011161 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011162 "Setting process group of " + app.processName
11163 + " to " + app.curSchedGroup);
11164 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011165 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011166 try {
11167 Process.setProcessGroup(app.pid, app.curSchedGroup);
11168 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011169 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011170 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011171 e.printStackTrace();
11172 } finally {
11173 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011174 }
11175 }
11176 if (false) {
11177 if (app.thread != null) {
11178 try {
11179 app.thread.setSchedulingGroup(app.curSchedGroup);
11180 } catch (RemoteException e) {
11181 }
11182 }
11183 }
11184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 }
11186
11187 return true;
11188 }
11189
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011190 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011191 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011193 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011195 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011196 }
11197 }
11198 return resumedActivity;
11199 }
11200
11201 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011202 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011203 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11204 int curAdj = app.curAdj;
11205 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11206 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11207
11208 mAdjSeq++;
11209
11210 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11211 if (res) {
11212 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11213 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11214 if (nowHidden != wasHidden) {
11215 // Changed to/from hidden state, so apps after it in the LRU
11216 // list may also be changed.
11217 updateOomAdjLocked();
11218 }
11219 }
11220 return res;
11221 }
11222
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011223 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011224 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011225 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011226 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11227
11228 if (false) {
11229 RuntimeException e = new RuntimeException();
11230 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011231 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011232 }
11233
11234 mAdjSeq++;
11235
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011236 // Let's determine how many processes we have running vs.
11237 // how many slots we have for background processes; we may want
11238 // to put multiple processes in a slot of there are enough of
11239 // them.
11240 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11241 int factor = (mLruProcesses.size()-4)/numSlots;
11242 if (factor < 1) factor = 1;
11243 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011244 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011246 // First try updating the OOM adjustment for each of the
11247 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011248 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011249 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11250 while (i > 0) {
11251 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011252 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011253 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011254 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011255 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011256 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011257 step++;
11258 if (step >= factor) {
11259 step = 0;
11260 curHiddenAdj++;
11261 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011262 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011263 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011264 if (!app.killedBackground) {
11265 numHidden++;
11266 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011267 Slog.i(TAG, "No longer want " + app.processName
11268 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011269 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11270 app.processName, app.setAdj, "too many background");
11271 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011272 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011273 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011274 }
11275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011276 } else {
11277 didOomAdj = false;
11278 }
11279 }
11280
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011281 // If we return false, we will fall back on killing processes to
11282 // have a fixed limit. Do this if a limit has been requested; else
11283 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011284 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11285 }
11286
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011287 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011288 synchronized (this) {
11289 int i;
11290
11291 // First remove any unused application processes whose package
11292 // has been removed.
11293 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11294 final ProcessRecord app = mRemovedProcesses.get(i);
11295 if (app.activities.size() == 0
11296 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011297 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011298 TAG, "Exiting empty application process "
11299 + app.processName + " ("
11300 + (app.thread != null ? app.thread.asBinder() : null)
11301 + ")\n");
11302 if (app.pid > 0 && app.pid != MY_PID) {
11303 Process.killProcess(app.pid);
11304 } else {
11305 try {
11306 app.thread.scheduleExit();
11307 } catch (Exception e) {
11308 // Ignore exceptions.
11309 }
11310 }
11311 cleanUpApplicationRecordLocked(app, false, -1);
11312 mRemovedProcesses.remove(i);
11313
11314 if (app.persistent) {
11315 if (app.persistent) {
11316 addAppLocked(app.info);
11317 }
11318 }
11319 }
11320 }
11321
11322 // Now try updating the OOM adjustment for each of the
11323 // application processes based on their current state.
11324 // If the setOomAdj() API is not supported, then go with our
11325 // back-up plan...
11326 if (!updateOomAdjLocked()) {
11327
11328 // Count how many processes are running services.
11329 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011330 for (i=mLruProcesses.size()-1; i>=0; i--) {
11331 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011332
11333 if (app.persistent || app.services.size() != 0
11334 || app.curReceiver != null
11335 || app.persistentActivities > 0) {
11336 // Don't count processes holding services against our
11337 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011338 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011339 TAG, "Not trimming app " + app + " with services: "
11340 + app.services);
11341 numServiceProcs++;
11342 }
11343 }
11344
11345 int curMaxProcs = mProcessLimit;
11346 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11347 if (mAlwaysFinishActivities) {
11348 curMaxProcs = 1;
11349 }
11350 curMaxProcs += numServiceProcs;
11351
11352 // Quit as many processes as we can to get down to the desired
11353 // process count. First remove any processes that no longer
11354 // have activites running in them.
11355 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011356 i<mLruProcesses.size()
11357 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011358 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011359 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 // Quit an application only if it is not currently
11361 // running any activities.
11362 if (!app.persistent && app.activities.size() == 0
11363 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011364 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011365 TAG, "Exiting empty application process "
11366 + app.processName + " ("
11367 + (app.thread != null ? app.thread.asBinder() : null)
11368 + ")\n");
11369 if (app.pid > 0 && app.pid != MY_PID) {
11370 Process.killProcess(app.pid);
11371 } else {
11372 try {
11373 app.thread.scheduleExit();
11374 } catch (Exception e) {
11375 // Ignore exceptions.
11376 }
11377 }
11378 // todo: For now we assume the application is not buggy
11379 // or evil, and will quit as a result of our request.
11380 // Eventually we need to drive this off of the death
11381 // notification, and kill the process if it takes too long.
11382 cleanUpApplicationRecordLocked(app, false, i);
11383 i--;
11384 }
11385 }
11386
11387 // If we still have too many processes, now from the least
11388 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011389 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011390 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011391 " of " + curMaxProcs + " processes");
11392 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011393 i<mLruProcesses.size()
11394 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011395 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011396 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011397 // Quit the application only if we have a state saved for
11398 // all of its activities.
11399 boolean canQuit = !app.persistent && app.curReceiver == null
11400 && app.services.size() == 0
11401 && app.persistentActivities == 0;
11402 int NUMA = app.activities.size();
11403 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011404 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011405 TAG, "Looking to quit " + app.processName);
11406 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011407 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011408 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011409 TAG, " " + r.intent.getComponent().flattenToShortString()
11410 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11411 canQuit = (r.haveState || !r.stateNotNeeded)
11412 && !r.visible && r.stopped;
11413 }
11414 if (canQuit) {
11415 // Finish all of the activities, and then the app itself.
11416 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011417 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011419 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011420 }
11421 r.resultTo = null;
11422 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011423 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011424 + app.processName + " ("
11425 + (app.thread != null ? app.thread.asBinder() : null)
11426 + ")\n");
11427 if (app.pid > 0 && app.pid != MY_PID) {
11428 Process.killProcess(app.pid);
11429 } else {
11430 try {
11431 app.thread.scheduleExit();
11432 } catch (Exception e) {
11433 // Ignore exceptions.
11434 }
11435 }
11436 // todo: For now we assume the application is not buggy
11437 // or evil, and will quit as a result of our request.
11438 // Eventually we need to drive this off of the death
11439 // notification, and kill the process if it takes too long.
11440 cleanUpApplicationRecordLocked(app, false, i);
11441 i--;
11442 //dump();
11443 }
11444 }
11445
11446 }
11447
11448 int curMaxActivities = MAX_ACTIVITIES;
11449 if (mAlwaysFinishActivities) {
11450 curMaxActivities = 1;
11451 }
11452
11453 // Finally, if there are too many activities now running, try to
11454 // finish as many as we can to get back down to the limit.
11455 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011456 i<mMainStack.mLRUActivities.size()
11457 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011458 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011459 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011460 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011461
11462 // We can finish this one if we have its icicle saved and
11463 // it is not persistent.
11464 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11465 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011466 final int origSize = mMainStack.mLRUActivities.size();
11467 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011468
11469 // This will remove it from the LRU list, so keep
11470 // our index at the same value. Note that this check to
11471 // see if the size changes is just paranoia -- if
11472 // something unexpected happens, we don't want to end up
11473 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011474 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011475 i--;
11476 }
11477 }
11478 }
11479 }
11480 }
11481
11482 /** This method sends the specified signal to each of the persistent apps */
11483 public void signalPersistentProcesses(int sig) throws RemoteException {
11484 if (sig != Process.SIGNAL_USR1) {
11485 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11486 }
11487
11488 synchronized (this) {
11489 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11490 != PackageManager.PERMISSION_GRANTED) {
11491 throw new SecurityException("Requires permission "
11492 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11493 }
11494
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011495 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11496 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011497 if (r.thread != null && r.persistent) {
11498 Process.sendSignal(r.pid, sig);
11499 }
11500 }
11501 }
11502 }
11503
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011504 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011505 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011506
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011507 try {
11508 synchronized (this) {
11509 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11510 // its own permission.
11511 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11512 != PackageManager.PERMISSION_GRANTED) {
11513 throw new SecurityException("Requires permission "
11514 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011515 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011516
11517 if (start && fd == null) {
11518 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011519 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011520
11521 ProcessRecord proc = null;
11522 try {
11523 int pid = Integer.parseInt(process);
11524 synchronized (mPidsSelfLocked) {
11525 proc = mPidsSelfLocked.get(pid);
11526 }
11527 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011528 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011529
11530 if (proc == null) {
11531 HashMap<String, SparseArray<ProcessRecord>> all
11532 = mProcessNames.getMap();
11533 SparseArray<ProcessRecord> procs = all.get(process);
11534 if (procs != null && procs.size() > 0) {
11535 proc = procs.valueAt(0);
11536 }
11537 }
11538
11539 if (proc == null || proc.thread == null) {
11540 throw new IllegalArgumentException("Unknown process: " + process);
11541 }
11542
11543 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11544 if (isSecure) {
11545 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11546 throw new SecurityException("Process not debuggable: " + proc);
11547 }
11548 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011549
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011550 proc.thread.profilerControl(start, path, fd);
11551 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011552 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011553 }
11554 } catch (RemoteException e) {
11555 throw new IllegalStateException("Process disappeared");
11556 } finally {
11557 if (fd != null) {
11558 try {
11559 fd.close();
11560 } catch (IOException e) {
11561 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011562 }
11563 }
11564 }
Andy McFadden824c5102010-07-09 16:26:57 -070011565
11566 public boolean dumpHeap(String process, boolean managed,
11567 String path, ParcelFileDescriptor fd) throws RemoteException {
11568
11569 try {
11570 synchronized (this) {
11571 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11572 // its own permission (same as profileControl).
11573 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11574 != PackageManager.PERMISSION_GRANTED) {
11575 throw new SecurityException("Requires permission "
11576 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
11577 }
11578
11579 if (fd == null) {
11580 throw new IllegalArgumentException("null fd");
11581 }
11582
11583 ProcessRecord proc = null;
11584 try {
11585 int pid = Integer.parseInt(process);
11586 synchronized (mPidsSelfLocked) {
11587 proc = mPidsSelfLocked.get(pid);
11588 }
11589 } catch (NumberFormatException e) {
11590 }
11591
11592 if (proc == null) {
11593 HashMap<String, SparseArray<ProcessRecord>> all
11594 = mProcessNames.getMap();
11595 SparseArray<ProcessRecord> procs = all.get(process);
11596 if (procs != null && procs.size() > 0) {
11597 proc = procs.valueAt(0);
11598 }
11599 }
11600
11601 if (proc == null || proc.thread == null) {
11602 throw new IllegalArgumentException("Unknown process: " + process);
11603 }
11604
11605 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11606 if (isSecure) {
11607 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11608 throw new SecurityException("Process not debuggable: " + proc);
11609 }
11610 }
11611
11612 proc.thread.dumpHeap(managed, path, fd);
11613 fd = null;
11614 return true;
11615 }
11616 } catch (RemoteException e) {
11617 throw new IllegalStateException("Process disappeared");
11618 } finally {
11619 if (fd != null) {
11620 try {
11621 fd.close();
11622 } catch (IOException e) {
11623 }
11624 }
11625 }
11626 }
11627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11629 public void monitor() {
11630 synchronized (this) { }
11631 }
11632}