blob: 252392b3f658f7495ddfd3dbfe49513c30f3efd3 [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;
29
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -080041import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.app.IActivityWatcher;
43import android.app.IApplicationThread;
44import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070045import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.app.IServiceConnection;
47import android.app.IThumbnailReceiver;
48import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070049import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070050import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.app.PendingIntent;
52import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070053import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080054import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020055import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080056import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.content.ComponentName;
58import android.content.ContentResolver;
59import android.content.Context;
60import android.content.Intent;
61import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070062import android.content.IIntentReceiver;
63import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070064import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.content.pm.ActivityInfo;
66import android.content.pm.ApplicationInfo;
67import android.content.pm.ConfigurationInfo;
68import android.content.pm.IPackageDataObserver;
69import android.content.pm.IPackageManager;
70import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080071import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070073import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import android.content.pm.ProviderInfo;
75import android.content.pm.ResolveInfo;
76import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070077import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.content.res.Configuration;
79import android.graphics.Bitmap;
80import android.net.Uri;
81import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080082import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080083import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070084import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080085import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080087import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088import android.os.FileUtils;
89import android.os.Handler;
90import android.os.IBinder;
91import android.os.IPermissionController;
92import android.os.Looper;
93import android.os.Message;
94import android.os.Parcel;
95import android.os.ParcelFileDescriptor;
96import android.os.PowerManager;
97import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070098import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.RemoteException;
100import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700101import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.SystemClock;
103import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.util.Config;
106import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800107import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800108import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.util.PrintWriterPrinter;
110import android.util.SparseArray;
111import android.view.Gravity;
112import android.view.LayoutInflater;
113import android.view.View;
114import android.view.WindowManager;
115import android.view.WindowManagerPolicy;
116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.io.File;
118import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200120import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800121import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122import java.io.PrintWriter;
123import java.lang.IllegalStateException;
124import java.lang.ref.WeakReference;
125import java.util.ArrayList;
126import java.util.HashMap;
127import java.util.HashSet;
128import java.util.Iterator;
129import java.util.List;
130import java.util.Locale;
131import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700132import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700133import java.util.concurrent.atomic.AtomicBoolean;
134import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135
136public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
137 static final String TAG = "ActivityManager";
138 static final boolean DEBUG = false;
139 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
140 static final boolean DEBUG_SWITCH = localLOGV || false;
141 static final boolean DEBUG_TASKS = localLOGV || false;
142 static final boolean DEBUG_PAUSE = localLOGV || false;
143 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
144 static final boolean DEBUG_TRANSITION = localLOGV || false;
145 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700146 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 static final boolean DEBUG_SERVICE = localLOGV || false;
148 static final boolean DEBUG_VISBILITY = localLOGV || false;
149 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700150 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800151 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700153 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700154 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700155 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 static final boolean VALIDATE_TOKENS = false;
157 static final boolean SHOW_ACTIVITY_START_TIME = true;
158
159 // Control over CPU and battery monitoring.
160 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
161 static final boolean MONITOR_CPU_USAGE = true;
162 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
163 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
164 static final boolean MONITOR_THREAD_CPU_USAGE = false;
165
Dianne Hackborn1655be42009-05-08 14:29:01 -0700166 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700167 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 private static final String SYSTEM_SECURE = "ro.secure";
170
171 // This is the maximum number of application processes we would like
172 // to have running. Due to the asynchronous nature of things, we can
173 // temporarily go beyond this limit.
174 static final int MAX_PROCESSES = 2;
175
176 // Set to false to leave processes running indefinitely, relying on
177 // the kernel killing them as resources are required.
178 static final boolean ENFORCE_PROCESS_LIMIT = false;
179
180 // This is the maximum number of activities that we would like to have
181 // running at a given time.
182 static final int MAX_ACTIVITIES = 20;
183
184 // Maximum number of recent tasks that we can remember.
185 static final int MAX_RECENT_TASKS = 20;
186
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700187 // Amount of time after a call to stopAppSwitches() during which we will
188 // prevent further untrusted switches from happening.
189 static final long APP_SWITCH_DELAY_TIME = 5*1000;
190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 // How long until we reset a task when the user returns to it. Currently
192 // 30 minutes.
193 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
194
195 // Set to true to disable the icon that is shown while a new activity
196 // is being started.
197 static final boolean SHOW_APP_STARTING_ICON = true;
198
199 // How long we wait until giving up on the last activity to pause. This
200 // is short because it directly impacts the responsiveness of starting the
201 // next activity.
202 static final int PAUSE_TIMEOUT = 500;
203
204 /**
205 * How long we can hold the launch wake lock before giving up.
206 */
207 static final int LAUNCH_TIMEOUT = 10*1000;
208
209 // How long we wait for a launched process to attach to the activity manager
210 // before we decide it's never going to come up for real.
211 static final int PROC_START_TIMEOUT = 10*1000;
212
213 // How long we wait until giving up on the last activity telling us it
214 // is idle.
215 static final int IDLE_TIMEOUT = 10*1000;
216
217 // How long to wait after going idle before forcing apps to GC.
218 static final int GC_TIMEOUT = 5*1000;
219
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700220 // The minimum amount of time between successive GC requests for a process.
221 static final int GC_MIN_INTERVAL = 60*1000;
222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 // How long we wait until giving up on an activity telling us it has
224 // finished destroying itself.
225 static final int DESTROY_TIMEOUT = 10*1000;
226
227 // How long we allow a receiver to run before giving up on it.
228 static final int BROADCAST_TIMEOUT = 10*1000;
229
230 // How long we wait for a service to finish executing.
231 static final int SERVICE_TIMEOUT = 20*1000;
232
233 // How long a service needs to be running until restarting its process
234 // is no longer considered to be a relaunch of the service.
235 static final int SERVICE_RESTART_DURATION = 5*1000;
236
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700237 // How long a service needs to be running until it will start back at
238 // SERVICE_RESTART_DURATION after being killed.
239 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
240
241 // Multiplying factor to increase restart duration time by, for each time
242 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
243 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
244
245 // The minimum amount of time between restarting services that we allow.
246 // That is, when multiple services are restarting, we won't allow each
247 // to restart less than this amount of time from the last one.
248 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 // Maximum amount of time for there to be no activity on a service before
251 // we consider it non-essential and allow its process to go on the
252 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700253 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254
255 // How long we wait until we timeout on key dispatching.
256 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
257
258 // The minimum time we allow between crashes, for us to consider this
259 // application to be bad and stop and its services and reject broadcasts.
260 static final int MIN_CRASH_INTERVAL = 60*1000;
261
262 // How long we wait until we timeout on key dispatching during instrumentation.
263 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
264
265 // OOM adjustments for processes in various states:
266
267 // This is a process without anything currently running in it. Definitely
268 // the first to go! Value set in system/rootdir/init.rc on startup.
269 // This value is initalized in the constructor, careful when refering to
270 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800271 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272
273 // This is a process only hosting activities that are not visible,
274 // so it can be killed without any disruption. Value set in
275 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800276 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 static int HIDDEN_APP_MIN_ADJ;
278
The Android Open Source Project4df24232009-03-05 14:34:35 -0800279 // This is a process holding the home application -- we want to try
280 // avoiding killing it, even if it would normally be in the background,
281 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800283
Christopher Tate6fa95972009-06-05 18:43:55 -0700284 // This is a process currently hosting a backup operation. Killing it
285 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800286 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 // This is a process holding a secondary server -- killing it will not
289 // have much of an impact as far as the user is concerned. Value set in
290 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800291 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700293 // This is a process with a heavy-weight application. It is in the
294 // background, but we want to try to avoid killing it. Value set in
295 // system/rootdir/init.rc on startup.
296 static final int HEAVY_WEIGHT_APP_ADJ;
297
298 // This is a process only hosting components that are perceptible to the
299 // user, and we really want to avoid killing them, but they are not
300 // immediately visible. An example is background music playback. Value set in
301 // system/rootdir/init.rc on startup.
302 static final int PERCEPTIBLE_APP_ADJ;
303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 // This is a process only hosting activities that are visible to the
305 // user, so we'd prefer they don't disappear. Value set in
306 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800307 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308
309 // This is the process running the current foreground app. We'd really
310 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800311 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312
313 // This is a process running a core server, such as telephony. Definitely
314 // don't want to kill it, but doing so is not completely fatal.
315 static final int CORE_SERVER_ADJ = -12;
316
317 // The system process runs at the default adjustment.
318 static final int SYSTEM_ADJ = -16;
319
320 // Memory pages are 4K.
321 static final int PAGE_SIZE = 4*1024;
322
323 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800324 static final int EMPTY_APP_MEM;
325 static final int HIDDEN_APP_MEM;
326 static final int HOME_APP_MEM;
327 static final int BACKUP_APP_MEM;
328 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700329 static final int HEAVY_WEIGHT_APP_MEM;
330 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800331 static final int VISIBLE_APP_MEM;
332 static final int FOREGROUND_APP_MEM;
333
334 // The minimum number of hidden apps we want to be able to keep around,
335 // without empty apps being able to push them out of memory.
336 static final int MIN_HIDDEN_APPS = 2;
337
Dianne Hackborn8633e682010-04-22 16:03:41 -0700338 // The maximum number of hidden processes we will keep around before
339 // killing them; this is just a control to not let us go too crazy with
340 // keeping around processes on devices with large amounts of RAM.
341 static final int MAX_HIDDEN_APPS = 15;
342
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800343 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700344 // been idle for less than 15 seconds.
345 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800346
347 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700348 // been idle for less than 120 seconds.
349 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800350
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700351 static int getIntProp(String name, boolean allowZero) {
352 String str = SystemProperties.get(name);
353 if (str == null) {
354 throw new IllegalArgumentException("Property not defined: " + name);
355 }
356 int val = Integer.valueOf(str);
357 if (val == 0 && !allowZero) {
358 throw new IllegalArgumentException("Property must not be zero: " + name);
359 }
360 return val;
361 }
362
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800363 static {
364 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700365 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
366 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
367 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
368 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
369 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
370 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
371 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
372 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
373 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
374 // These days we use the last empty slot for hidden apps as well.
375 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
376 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
377 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
378 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
379 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
380 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
381 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
382 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
383 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
384 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386
Dan Egnor42471dd2010-01-07 17:25:22 -0800387 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388
389 static final String[] EMPTY_STRING_ARRAY = new String[0];
390
391 enum ActivityState {
392 INITIALIZING,
393 RESUMED,
394 PAUSING,
395 PAUSED,
396 STOPPING,
397 STOPPED,
398 FINISHING,
399 DESTROYING,
400 DESTROYED
401 }
402
403 /**
404 * The back history of all previous (and possibly still
405 * running) activities. It contains HistoryRecord objects.
406 */
407 final ArrayList mHistory = new ArrayList();
408
409 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700410 * Description of a request to start a new activity, which has been held
411 * due to app switches being disabled.
412 */
413 class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700414 ActivityRecord r;
415 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700416 Uri[] grantedUriPermissions;
417 int grantedMode;
418 boolean onlyIfNeeded;
419 }
420
421 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
422 = new ArrayList<PendingActivityLaunch>();
423
424 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800425 * List of people waiting to find out about the next launched activity.
426 */
427 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
428 = new ArrayList<IActivityManager.WaitResult>();
429
430 /**
431 * List of people waiting to find out about the next visible activity.
432 */
433 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
434 = new ArrayList<IActivityManager.WaitResult>();
435
436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * List of all active broadcasts that are to be executed immediately
438 * (without waiting for another broadcast to finish). Currently this only
439 * contains broadcasts to registered receivers, to avoid spinning up
440 * a bunch of processes to execute IntentReceiver components.
441 */
442 final ArrayList<BroadcastRecord> mParallelBroadcasts
443 = new ArrayList<BroadcastRecord>();
444
445 /**
446 * List of all active broadcasts that are to be executed one at a time.
447 * The object at the top of the list is the currently activity broadcasts;
448 * those after it are waiting for the top to finish..
449 */
450 final ArrayList<BroadcastRecord> mOrderedBroadcasts
451 = new ArrayList<BroadcastRecord>();
452
453 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800454 * Historical data of past broadcasts, for debugging.
455 */
456 static final int MAX_BROADCAST_HISTORY = 100;
457 final BroadcastRecord[] mBroadcastHistory
458 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
459
460 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 * Set when we current have a BROADCAST_INTENT_MSG in flight.
462 */
463 boolean mBroadcastsScheduled = false;
464
465 /**
466 * Set to indicate whether to issue an onUserLeaving callback when a
467 * newly launched activity is being brought in front of us.
468 */
469 boolean mUserLeaving = false;
470
471 /**
472 * When we are in the process of pausing an activity, before starting the
473 * next one, this variable holds the activity that is currently being paused.
474 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700475 ActivityRecord mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476
477 /**
478 * Current activity that is resumed, or null if there is none.
479 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700480 ActivityRecord mResumedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481
482 /**
483 * Activity we have told the window manager to have key focus.
484 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700485 ActivityRecord mFocusedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486
487 /**
488 * This is the last activity that we put into the paused state. This is
489 * used to determine if we need to do an activity transition while sleeping,
490 * when we normally hold the top activity paused.
491 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700492 ActivityRecord mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493
494 /**
495 * List of activities that are waiting for a new activity
496 * to become visible before completing whatever operation they are
497 * supposed to do.
498 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700499 final ArrayList<ActivityRecord> mWaitingVisibleActivities
500 = new ArrayList<ActivityRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501
502 /**
503 * List of activities that are ready to be stopped, but waiting
504 * for the next activity to settle down before doing so. It contains
505 * HistoryRecord objects.
506 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700507 final ArrayList<ActivityRecord> mStoppingActivities
508 = new ArrayList<ActivityRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800509
510 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700511 * Animations that for the current transition have requested not to
512 * be considered for the transition animation.
513 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700514 final ArrayList<ActivityRecord> mNoAnimActivities
515 = new ArrayList<ActivityRecord>();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700516
517 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 * List of intents that were used to start the most recent tasks.
519 */
520 final ArrayList<TaskRecord> mRecentTasks
521 = new ArrayList<TaskRecord>();
522
523 /**
524 * List of activities that are ready to be finished, but waiting
525 * for the previous activity to settle down before doing so. It contains
526 * HistoryRecord objects.
527 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700528 final ArrayList<ActivityRecord> mFinishingActivities
529 = new ArrayList<ActivityRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530
531 /**
532 * All of the applications we currently have running organized by name.
533 * The keys are strings of the application package name (as
534 * returned by the package manager), and the keys are ApplicationRecord
535 * objects.
536 */
537 final ProcessMap<ProcessRecord> mProcessNames
538 = new ProcessMap<ProcessRecord>();
539
540 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700541 * The currently running heavy-weight process, if any.
542 */
543 ProcessRecord mHeavyWeightProcess = null;
544
545 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 * The last time that various processes have crashed.
547 */
548 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
549
550 /**
551 * Set of applications that we consider to be bad, and will reject
552 * incoming broadcasts from (which the user has no control over).
553 * Processes are added to this set when they have crashed twice within
554 * a minimum amount of time; they are removed from it when they are
555 * later restarted (hopefully due to some user action). The value is the
556 * time it was added to the list.
557 */
558 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
559
560 /**
561 * All of the processes we currently have running organized by pid.
562 * The keys are the pid running the application.
563 *
564 * <p>NOTE: This object is protected by its own lock, NOT the global
565 * activity manager lock!
566 */
567 final SparseArray<ProcessRecord> mPidsSelfLocked
568 = new SparseArray<ProcessRecord>();
569
570 /**
571 * All of the processes that have been forced to be foreground. The key
572 * is the pid of the caller who requested it (we hold a death
573 * link on it).
574 */
575 abstract class ForegroundToken implements IBinder.DeathRecipient {
576 int pid;
577 IBinder token;
578 }
579 final SparseArray<ForegroundToken> mForegroundProcesses
580 = new SparseArray<ForegroundToken>();
581
582 /**
583 * List of records for processes that someone had tried to start before the
584 * system was ready. We don't start them at that point, but ensure they
585 * are started by the time booting is complete.
586 */
587 final ArrayList<ProcessRecord> mProcessesOnHold
588 = new ArrayList<ProcessRecord>();
589
590 /**
591 * List of records for processes that we have started and are waiting
592 * for them to call back. This is really only needed when running in
593 * single processes mode, in which case we do not have a unique pid for
594 * each process.
595 */
596 final ArrayList<ProcessRecord> mStartingProcesses
597 = new ArrayList<ProcessRecord>();
598
599 /**
600 * List of persistent applications that are in the process
601 * of being started.
602 */
603 final ArrayList<ProcessRecord> mPersistentStartingProcesses
604 = new ArrayList<ProcessRecord>();
605
606 /**
607 * Processes that are being forcibly torn down.
608 */
609 final ArrayList<ProcessRecord> mRemovedProcesses
610 = new ArrayList<ProcessRecord>();
611
612 /**
613 * List of running applications, sorted by recent usage.
614 * The first entry in the list is the least recently used.
615 * It contains ApplicationRecord objects. This list does NOT include
616 * any persistent application records (since we never want to exit them).
617 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800618 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 = new ArrayList<ProcessRecord>();
620
621 /**
622 * List of processes that should gc as soon as things are idle.
623 */
624 final ArrayList<ProcessRecord> mProcessesToGc
625 = new ArrayList<ProcessRecord>();
626
627 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800628 * This is the process holding what we currently consider to be
629 * the "home" activity.
630 */
631 private ProcessRecord mHomeProcess;
632
633 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 * List of running activities, sorted by recent usage.
635 * The first entry in the list is the least recently used.
636 * It contains HistoryRecord objects.
637 */
638 private final ArrayList mLRUActivities = new ArrayList();
639
640 /**
641 * Set of PendingResultRecord objects that are currently active.
642 */
643 final HashSet mPendingResultRecords = new HashSet();
644
645 /**
646 * Set of IntentSenderRecord objects that are currently active.
647 */
648 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
649 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
650
651 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700652 * Fingerprints (String.hashCode()) of stack traces that we've
653 * already logged DropBox entries for. Guarded by itself. If
654 * something (rogue user app) forces this over
655 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
656 */
657 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
658 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
659
660 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661 * Intent broadcast that we have tried to start, but are
662 * waiting for its application's process to be created. We only
663 * need one (instead of a list) because we always process broadcasts
664 * one at a time, so no others can be started while waiting for this
665 * one.
666 */
667 BroadcastRecord mPendingBroadcast = null;
668
669 /**
670 * Keeps track of all IIntentReceivers that have been registered for
671 * broadcasts. Hash keys are the receiver IBinder, hash value is
672 * a ReceiverList.
673 */
674 final HashMap mRegisteredReceivers = new HashMap();
675
676 /**
677 * Resolver for broadcast intents to registered receivers.
678 * Holds BroadcastFilter (subclass of IntentFilter).
679 */
680 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
681 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
682 @Override
683 protected boolean allowFilterResult(
684 BroadcastFilter filter, List<BroadcastFilter> dest) {
685 IBinder target = filter.receiverList.receiver.asBinder();
686 for (int i=dest.size()-1; i>=0; i--) {
687 if (dest.get(i).receiverList.receiver.asBinder() == target) {
688 return false;
689 }
690 }
691 return true;
692 }
693 };
694
695 /**
696 * State of all active sticky broadcasts. Keys are the action of the
697 * sticky Intent, values are an ArrayList of all broadcasted intents with
698 * that action (which should usually be one).
699 */
700 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
701 new HashMap<String, ArrayList<Intent>>();
702
703 /**
704 * All currently running services.
705 */
706 final HashMap<ComponentName, ServiceRecord> mServices =
707 new HashMap<ComponentName, ServiceRecord>();
708
709 /**
710 * All currently running services indexed by the Intent used to start them.
711 */
712 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
713 new HashMap<Intent.FilterComparison, ServiceRecord>();
714
715 /**
716 * All currently bound service connections. Keys are the IBinder of
717 * the client's IServiceConnection.
718 */
719 final HashMap<IBinder, ConnectionRecord> mServiceConnections
720 = new HashMap<IBinder, ConnectionRecord>();
721
722 /**
723 * List of services that we have been asked to start,
724 * but haven't yet been able to. It is used to hold start requests
725 * while waiting for their corresponding application thread to get
726 * going.
727 */
728 final ArrayList<ServiceRecord> mPendingServices
729 = new ArrayList<ServiceRecord>();
730
731 /**
732 * List of services that are scheduled to restart following a crash.
733 */
734 final ArrayList<ServiceRecord> mRestartingServices
735 = new ArrayList<ServiceRecord>();
736
737 /**
738 * List of services that are in the process of being stopped.
739 */
740 final ArrayList<ServiceRecord> mStoppingServices
741 = new ArrayList<ServiceRecord>();
742
743 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700744 * Backup/restore process management
745 */
746 String mBackupAppName = null;
747 BackupRecord mBackupTarget = null;
748
749 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 * List of PendingThumbnailsRecord objects of clients who are still
751 * waiting to receive all of the thumbnails for a task.
752 */
753 final ArrayList mPendingThumbnails = new ArrayList();
754
755 /**
756 * List of HistoryRecord objects that have been finished and must
757 * still report back to a pending thumbnail receiver.
758 */
759 final ArrayList mCancelledThumbnails = new ArrayList();
760
761 /**
762 * All of the currently running global content providers. Keys are a
763 * string containing the provider name and values are a
764 * ContentProviderRecord object containing the data about it. Note
765 * that a single provider may be published under multiple names, so
766 * there may be multiple entries here for a single one in mProvidersByClass.
767 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700768 final HashMap<String, ContentProviderRecord> mProvidersByName
769 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770
771 /**
772 * All of the currently running global content providers. Keys are a
773 * string containing the provider's implementation class and values are a
774 * ContentProviderRecord object containing the data about it.
775 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700776 final HashMap<String, ContentProviderRecord> mProvidersByClass
777 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778
779 /**
780 * List of content providers who have clients waiting for them. The
781 * application is currently being launched and the provider will be
782 * removed from this list once it is published.
783 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700784 final ArrayList<ContentProviderRecord> mLaunchingProviders
785 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786
787 /**
788 * Global set of specific Uri permissions that have been granted.
789 */
790 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
791 = new SparseArray<HashMap<Uri, UriPermission>>();
792
793 /**
794 * Thread-local storage used to carry caller permissions over through
795 * indirect content-provider access.
796 * @see #ActivityManagerService.openContentUri()
797 */
798 private class Identity {
799 public int pid;
800 public int uid;
801
802 Identity(int _pid, int _uid) {
803 pid = _pid;
804 uid = _uid;
805 }
806 }
807 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
808
809 /**
810 * All information we have collected about the runtime performance of
811 * any user id that can impact battery performance.
812 */
813 final BatteryStatsService mBatteryStatsService;
814
815 /**
816 * information about component usage
817 */
818 final UsageStatsService mUsageStatsService;
819
820 /**
821 * Current configuration information. HistoryRecord objects are given
822 * a reference to this object to indicate which configuration they are
823 * currently running in, so this object must be kept immutable.
824 */
825 Configuration mConfiguration = new Configuration();
826
827 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800828 * Current sequencing integer of the configuration, for skipping old
829 * configurations.
830 */
831 int mConfigurationSeq = 0;
832
833 /**
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700834 * Set when we know we are going to be calling updateConfiguration()
835 * soon, so want to skip intermediate config checks.
836 */
837 boolean mConfigWillChange;
838
839 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700840 * Hardware-reported OpenGLES version.
841 */
842 final int GL_ES_VERSION;
843
844 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 * List of initialization arguments to pass to all processes when binding applications to them.
846 * For example, references to the commonly used services.
847 */
848 HashMap<String, IBinder> mAppBindArgs;
849
850 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700851 * Temporary to avoid allocations. Protected by main lock.
852 */
853 final StringBuilder mStringBuilder = new StringBuilder(256);
854
855 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 * Used to control how we initialize the service.
857 */
858 boolean mStartRunning = false;
859 ComponentName mTopComponent;
860 String mTopAction;
861 String mTopData;
862 boolean mSystemReady = false;
863 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700864 boolean mWaitingUpdate = false;
865 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866
867 Context mContext;
868
869 int mFactoryTest;
870
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700871 boolean mCheckedForSetup;
872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700874 * The time at which we will allow normal application switches again,
875 * after a call to {@link #stopAppSwitches()}.
876 */
877 long mAppSwitchesAllowedTime;
878
879 /**
880 * This is set to true after the first switch after mAppSwitchesAllowedTime
881 * is set; any switches after that will clear the time.
882 */
883 boolean mDidAppSwitch;
884
885 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 * Set while we are wanting to sleep, to prevent any
887 * activities from being started/resumed.
888 */
889 boolean mSleeping = false;
890
891 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700892 * Set if we are shutting down the system, similar to sleeping.
893 */
894 boolean mShuttingDown = false;
895
896 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 * Set when the system is going to sleep, until we have
898 * successfully paused the current activity and released our wake lock.
899 * At that point the system is allowed to actually sleep.
900 */
901 PowerManager.WakeLock mGoingToSleep;
902
903 /**
904 * We don't want to allow the device to go to sleep while in the process
905 * of launching an activity. This is primarily to allow alarm intent
906 * receivers to launch an activity and get that to run before the device
907 * goes back to sleep.
908 */
909 PowerManager.WakeLock mLaunchingActivity;
910
911 /**
912 * Task identifier that activities are currently being started
913 * in. Incremented each time a new task is created.
914 * todo: Replace this with a TokenSpace class that generates non-repeating
915 * integers that won't wrap.
916 */
917 int mCurTask = 1;
918
919 /**
920 * Current sequence id for oom_adj computation traversal.
921 */
922 int mAdjSeq = 0;
923
924 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700925 * Current sequence id for process LRU updating.
926 */
927 int mLruSeq = 0;
928
929 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
931 * is set, indicating the user wants processes started in such a way
932 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
933 * running in each process (thus no pre-initialized process, etc).
934 */
935 boolean mSimpleProcessManagement = false;
936
937 /**
938 * System monitoring: number of processes that died since the last
939 * N procs were started.
940 */
941 int[] mProcDeaths = new int[20];
942
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700943 /**
944 * This is set if we had to do a delayed dexopt of an app before launching
945 * it, to increasing the ANR timeouts in that case.
946 */
947 boolean mDidDexOpt;
948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 String mDebugApp = null;
950 boolean mWaitForDebugger = false;
951 boolean mDebugTransient = false;
952 String mOrigDebugApp = null;
953 boolean mOrigWaitForDebugger = false;
954 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700955 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700957 final RemoteCallbackList<IActivityWatcher> mWatchers
958 = new RemoteCallbackList<IActivityWatcher>();
959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 /**
961 * Callback of last caller to {@link #requestPss}.
962 */
963 Runnable mRequestPssCallback;
964
965 /**
966 * Remaining processes for which we are waiting results from the last
967 * call to {@link #requestPss}.
968 */
969 final ArrayList<ProcessRecord> mRequestPssList
970 = new ArrayList<ProcessRecord>();
971
972 /**
973 * Runtime statistics collection thread. This object's lock is used to
974 * protect all related state.
975 */
976 final Thread mProcessStatsThread;
977
978 /**
979 * Used to collect process stats when showing not responding dialog.
980 * Protected by mProcessStatsThread.
981 */
982 final ProcessStats mProcessStats = new ProcessStats(
983 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700984 final AtomicLong mLastCpuTime = new AtomicLong(0);
985 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 long mLastWriteTime = 0;
988
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700989 long mInitialStartTime = 0;
990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 /**
992 * Set to true after the system has finished booting.
993 */
994 boolean mBooted = false;
995
996 int mProcessLimit = 0;
997
998 WindowManagerService mWindowManager;
999
1000 static ActivityManagerService mSelf;
1001 static ActivityThread mSystemThread;
1002
1003 private final class AppDeathRecipient implements IBinder.DeathRecipient {
1004 final ProcessRecord mApp;
1005 final int mPid;
1006 final IApplicationThread mAppThread;
1007
1008 AppDeathRecipient(ProcessRecord app, int pid,
1009 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001010 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 TAG, "New death recipient " + this
1012 + " for thread " + thread.asBinder());
1013 mApp = app;
1014 mPid = pid;
1015 mAppThread = thread;
1016 }
1017
1018 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001019 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 TAG, "Death received in " + this
1021 + " for thread " + mAppThread.asBinder());
1022 removeRequestedPss(mApp);
1023 synchronized(ActivityManagerService.this) {
1024 appDiedLocked(mApp, mPid, mAppThread);
1025 }
1026 }
1027 }
1028
1029 static final int SHOW_ERROR_MSG = 1;
1030 static final int SHOW_NOT_RESPONDING_MSG = 2;
1031 static final int SHOW_FACTORY_ERROR_MSG = 3;
1032 static final int UPDATE_CONFIGURATION_MSG = 4;
1033 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
1034 static final int WAIT_FOR_DEBUGGER_MSG = 6;
1035 static final int BROADCAST_INTENT_MSG = 7;
1036 static final int BROADCAST_TIMEOUT_MSG = 8;
1037 static final int PAUSE_TIMEOUT_MSG = 9;
1038 static final int IDLE_TIMEOUT_MSG = 10;
1039 static final int IDLE_NOW_MSG = 11;
1040 static final int SERVICE_TIMEOUT_MSG = 12;
1041 static final int UPDATE_TIME_ZONE = 13;
1042 static final int SHOW_UID_ERROR_MSG = 14;
1043 static final int IM_FEELING_LUCKY_MSG = 15;
1044 static final int LAUNCH_TIMEOUT_MSG = 16;
1045 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046 static final int RESUME_TOP_ACTIVITY_MSG = 19;
1047 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001048 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001049 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001050 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001051 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
1052 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001053 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054
1055 AlertDialog mUidAlert;
1056
1057 final Handler mHandler = new Handler() {
1058 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001059 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 //}
1061
1062 public void handleMessage(Message msg) {
1063 switch (msg.what) {
1064 case SHOW_ERROR_MSG: {
1065 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 synchronized (ActivityManagerService.this) {
1067 ProcessRecord proc = (ProcessRecord)data.get("app");
1068 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001069 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070 return;
1071 }
1072 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001073 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001074 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 d.show();
1076 proc.crashDialog = d;
1077 } else {
1078 // The device is asleep, so just pretend that the user
1079 // saw a crash dialog and hit "force quit".
1080 res.set(0);
1081 }
1082 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001083
1084 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085 } break;
1086 case SHOW_NOT_RESPONDING_MSG: {
1087 synchronized (ActivityManagerService.this) {
1088 HashMap data = (HashMap) msg.obj;
1089 ProcessRecord proc = (ProcessRecord)data.get("app");
1090 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001091 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 return;
1093 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001094
1095 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1096 null, null, 0, null, null, null,
1097 false, false, MY_PID, Process.SYSTEM_UID);
1098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001100 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 d.show();
1102 proc.anrDialog = d;
1103 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001104
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001105 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001107 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1108 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1109 synchronized (ActivityManagerService.this) {
1110 ProcessRecord proc = (ProcessRecord) data.get("app");
1111 if (proc == null) {
1112 Slog.e(TAG, "App not found when showing strict mode dialog.");
1113 break;
1114 }
1115 if (proc.crashDialog != null) {
1116 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1117 return;
1118 }
1119 AppErrorResult res = (AppErrorResult) data.get("result");
1120 if (!mSleeping && !mShuttingDown) {
1121 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1122 d.show();
1123 proc.crashDialog = d;
1124 } else {
1125 // The device is asleep, so just pretend that the user
1126 // saw a crash dialog and hit "force quit".
1127 res.set(0);
1128 }
1129 }
1130 ensureBootCompleted();
1131 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 case SHOW_FACTORY_ERROR_MSG: {
1133 Dialog d = new FactoryErrorDialog(
1134 mContext, msg.getData().getCharSequence("msg"));
1135 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001136 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 } break;
1138 case UPDATE_CONFIGURATION_MSG: {
1139 final ContentResolver resolver = mContext.getContentResolver();
1140 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1141 } break;
1142 case GC_BACKGROUND_PROCESSES_MSG: {
1143 synchronized (ActivityManagerService.this) {
1144 performAppGcsIfAppropriateLocked();
1145 }
1146 } break;
1147 case WAIT_FOR_DEBUGGER_MSG: {
1148 synchronized (ActivityManagerService.this) {
1149 ProcessRecord app = (ProcessRecord)msg.obj;
1150 if (msg.arg1 != 0) {
1151 if (!app.waitedForDebugger) {
1152 Dialog d = new AppWaitingForDebuggerDialog(
1153 ActivityManagerService.this,
1154 mContext, app);
1155 app.waitDialog = d;
1156 app.waitedForDebugger = true;
1157 d.show();
1158 }
1159 } else {
1160 if (app.waitDialog != null) {
1161 app.waitDialog.dismiss();
1162 app.waitDialog = null;
1163 }
1164 }
1165 }
1166 } break;
1167 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001168 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 TAG, "Received BROADCAST_INTENT_MSG");
1170 processNextBroadcast(true);
1171 } break;
1172 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001173 if (mDidDexOpt) {
1174 mDidDexOpt = false;
1175 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1176 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1177 return;
1178 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001179 // Only process broadcast timeouts if the system is ready. That way
1180 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1181 // to do heavy lifting for system up
1182 if (mSystemReady) {
1183 broadcastTimeout();
1184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 } break;
1186 case PAUSE_TIMEOUT_MSG: {
1187 IBinder token = (IBinder)msg.obj;
1188 // We don't at this point know if the activity is fullscreen,
1189 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001190 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 activityPaused(token, null, true);
1192 } break;
1193 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001194 if (mDidDexOpt) {
1195 mDidDexOpt = false;
1196 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1197 nmsg.obj = msg.obj;
1198 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1199 return;
1200 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 // We don't at this point know if the activity is fullscreen,
1202 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001203 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001204 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001205 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 } break;
1207 case DESTROY_TIMEOUT_MSG: {
1208 IBinder token = (IBinder)msg.obj;
1209 // We don't at this point know if the activity is fullscreen,
1210 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001211 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 activityDestroyed(token);
1213 } break;
1214 case IDLE_NOW_MSG: {
1215 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001216 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 } break;
1218 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001219 if (mDidDexOpt) {
1220 mDidDexOpt = false;
1221 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1222 nmsg.obj = msg.obj;
1223 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1224 return;
1225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 serviceTimeout((ProcessRecord)msg.obj);
1227 } break;
1228 case UPDATE_TIME_ZONE: {
1229 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001230 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1231 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232 if (r.thread != null) {
1233 try {
1234 r.thread.updateTimeZone();
1235 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001236 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 }
1238 }
1239 }
1240 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001241 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242 case SHOW_UID_ERROR_MSG: {
1243 // XXX This is a temporary dialog, no need to localize.
1244 AlertDialog d = new BaseErrorDialog(mContext);
1245 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1246 d.setCancelable(false);
1247 d.setTitle("System UIDs Inconsistent");
1248 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1249 d.setButton("I'm Feeling Lucky",
1250 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1251 mUidAlert = d;
1252 d.show();
1253 } break;
1254 case IM_FEELING_LUCKY_MSG: {
1255 if (mUidAlert != null) {
1256 mUidAlert.dismiss();
1257 mUidAlert = null;
1258 }
1259 } break;
1260 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001261 if (mDidDexOpt) {
1262 mDidDexOpt = false;
1263 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1264 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1265 return;
1266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 synchronized (ActivityManagerService.this) {
1268 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001269 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 mLaunchingActivity.release();
1271 }
1272 }
1273 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001274 case RESUME_TOP_ACTIVITY_MSG: {
1275 synchronized (ActivityManagerService.this) {
1276 resumeTopActivityLocked(null);
1277 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001278 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001280 if (mDidDexOpt) {
1281 mDidDexOpt = false;
1282 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1283 nmsg.obj = msg.obj;
1284 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1285 return;
1286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 ProcessRecord app = (ProcessRecord)msg.obj;
1288 synchronized (ActivityManagerService.this) {
1289 processStartTimedOutLocked(app);
1290 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001291 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001292 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1293 synchronized (ActivityManagerService.this) {
1294 doPendingActivityLaunchesLocked(true);
1295 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001296 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001297 case KILL_APPLICATION_MSG: {
1298 synchronized (ActivityManagerService.this) {
1299 int uid = msg.arg1;
1300 boolean restart = (msg.arg2 == 1);
1301 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001302 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001303 }
1304 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001305 case FINALIZE_PENDING_INTENT_MSG: {
1306 ((PendingIntentRecord)msg.obj).completeFinalize();
1307 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001308 case POST_HEAVY_NOTIFICATION_MSG: {
1309 INotificationManager inm = NotificationManager.getService();
1310 if (inm == null) {
1311 return;
1312 }
1313
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001314 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001315 ProcessRecord process = root.app;
1316 if (process == null) {
1317 return;
1318 }
1319
1320 try {
1321 Context context = mContext.createPackageContext(process.info.packageName, 0);
1322 String text = mContext.getString(R.string.heavy_weight_notification,
1323 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1324 Notification notification = new Notification();
1325 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1326 notification.when = 0;
1327 notification.flags = Notification.FLAG_ONGOING_EVENT;
1328 notification.tickerText = text;
1329 notification.defaults = 0; // please be quiet
1330 notification.sound = null;
1331 notification.vibrate = null;
1332 notification.setLatestEventInfo(context, text,
1333 mContext.getText(R.string.heavy_weight_notification_detail),
1334 PendingIntent.getActivity(mContext, 0, root.intent,
1335 PendingIntent.FLAG_CANCEL_CURRENT));
1336
1337 try {
1338 int[] outId = new int[1];
1339 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1340 notification, outId);
1341 } catch (RuntimeException e) {
1342 Slog.w(ActivityManagerService.TAG,
1343 "Error showing notification for heavy-weight app", e);
1344 } catch (RemoteException e) {
1345 }
1346 } catch (NameNotFoundException e) {
1347 Log.w(TAG, "Unable to create context for heavy notification", e);
1348 }
1349 } break;
1350 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1351 INotificationManager inm = NotificationManager.getService();
1352 if (inm == null) {
1353 return;
1354 }
1355 try {
1356 inm.cancelNotification("android",
1357 R.string.heavy_weight_notification);
1358 } catch (RuntimeException e) {
1359 Slog.w(ActivityManagerService.TAG,
1360 "Error canceling notification for service", e);
1361 } catch (RemoteException e) {
1362 }
1363 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 }
1365 }
1366 };
1367
1368 public static void setSystemProcess() {
1369 try {
1370 ActivityManagerService m = mSelf;
1371
1372 ServiceManager.addService("activity", m);
1373 ServiceManager.addService("meminfo", new MemBinder(m));
1374 if (MONITOR_CPU_USAGE) {
1375 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 ServiceManager.addService("permission", new PermissionController(m));
1378
1379 ApplicationInfo info =
1380 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001381 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001382 mSystemThread.installSystemApplicationInfo(info);
1383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 synchronized (mSelf) {
1385 ProcessRecord app = mSelf.newProcessRecordLocked(
1386 mSystemThread.getApplicationThread(), info,
1387 info.processName);
1388 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001389 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 app.maxAdj = SYSTEM_ADJ;
1391 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1392 synchronized (mSelf.mPidsSelfLocked) {
1393 mSelf.mPidsSelfLocked.put(app.pid, app);
1394 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001395 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 }
1397 } catch (PackageManager.NameNotFoundException e) {
1398 throw new RuntimeException(
1399 "Unable to find android system package", e);
1400 }
1401 }
1402
1403 public void setWindowManager(WindowManagerService wm) {
1404 mWindowManager = wm;
1405 }
1406
1407 public static final Context main(int factoryTest) {
1408 AThread thr = new AThread();
1409 thr.start();
1410
1411 synchronized (thr) {
1412 while (thr.mService == null) {
1413 try {
1414 thr.wait();
1415 } catch (InterruptedException e) {
1416 }
1417 }
1418 }
1419
1420 ActivityManagerService m = thr.mService;
1421 mSelf = m;
1422 ActivityThread at = ActivityThread.systemMain();
1423 mSystemThread = at;
1424 Context context = at.getSystemContext();
1425 m.mContext = context;
1426 m.mFactoryTest = factoryTest;
1427 PowerManager pm =
1428 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1429 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1430 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1431 m.mLaunchingActivity.setReferenceCounted(false);
1432
1433 m.mBatteryStatsService.publish(context);
1434 m.mUsageStatsService.publish(context);
1435
1436 synchronized (thr) {
1437 thr.mReady = true;
1438 thr.notifyAll();
1439 }
1440
1441 m.startRunning(null, null, null, null);
1442
1443 return context;
1444 }
1445
1446 public static ActivityManagerService self() {
1447 return mSelf;
1448 }
1449
1450 static class AThread extends Thread {
1451 ActivityManagerService mService;
1452 boolean mReady = false;
1453
1454 public AThread() {
1455 super("ActivityManager");
1456 }
1457
1458 public void run() {
1459 Looper.prepare();
1460
1461 android.os.Process.setThreadPriority(
1462 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1463
1464 ActivityManagerService m = new ActivityManagerService();
1465
1466 synchronized (this) {
1467 mService = m;
1468 notifyAll();
1469 }
1470
1471 synchronized (this) {
1472 while (!mReady) {
1473 try {
1474 wait();
1475 } catch (InterruptedException e) {
1476 }
1477 }
1478 }
1479
1480 Looper.loop();
1481 }
1482 }
1483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 static class MemBinder extends Binder {
1485 ActivityManagerService mActivityManagerService;
1486 MemBinder(ActivityManagerService activityManagerService) {
1487 mActivityManagerService = activityManagerService;
1488 }
1489
1490 @Override
1491 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1492 ActivityManagerService service = mActivityManagerService;
1493 ArrayList<ProcessRecord> procs;
1494 synchronized (mActivityManagerService) {
1495 if (args != null && args.length > 0
1496 && args[0].charAt(0) != '-') {
1497 procs = new ArrayList<ProcessRecord>();
1498 int pid = -1;
1499 try {
1500 pid = Integer.parseInt(args[0]);
1501 } catch (NumberFormatException e) {
1502
1503 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001504 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1505 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 if (proc.pid == pid) {
1507 procs.add(proc);
1508 } else if (proc.processName.equals(args[0])) {
1509 procs.add(proc);
1510 }
1511 }
1512 if (procs.size() <= 0) {
1513 pw.println("No process found for: " + args[0]);
1514 return;
1515 }
1516 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001517 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 }
1519 }
1520 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1521 }
1522 }
1523
1524 static class CpuBinder extends Binder {
1525 ActivityManagerService mActivityManagerService;
1526 CpuBinder(ActivityManagerService activityManagerService) {
1527 mActivityManagerService = activityManagerService;
1528 }
1529
1530 @Override
1531 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1532 synchronized (mActivityManagerService.mProcessStatsThread) {
1533 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1534 }
1535 }
1536 }
1537
1538 private ActivityManagerService() {
1539 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1540 if (v != null && Integer.getInteger(v) != 0) {
1541 mSimpleProcessManagement = true;
1542 }
1543 v = System.getenv("ANDROID_DEBUG_APP");
1544 if (v != null) {
1545 mSimpleProcessManagement = true;
1546 }
1547
Joe Onorato8a9b2202010-02-26 18:56:32 -08001548 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 File dataDir = Environment.getDataDirectory();
1551 File systemDir = new File(dataDir, "system");
1552 systemDir.mkdirs();
1553 mBatteryStatsService = new BatteryStatsService(new File(
1554 systemDir, "batterystats.bin").toString());
1555 mBatteryStatsService.getActiveStatistics().readLocked();
1556 mBatteryStatsService.getActiveStatistics().writeLocked();
1557
1558 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001559 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560
Jack Palevichb90d28c2009-07-22 15:35:24 -07001561 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1562 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1563
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001564 mConfiguration.setToDefaults();
1565 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 mProcessStats.init();
1567
1568 // Add ourself to the Watchdog monitors.
1569 Watchdog.getInstance().addMonitor(this);
1570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 mProcessStatsThread = new Thread("ProcessStats") {
1572 public void run() {
1573 while (true) {
1574 try {
1575 try {
1576 synchronized(this) {
1577 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001578 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001580 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 // + ", write delay=" + nextWriteDelay);
1582 if (nextWriteDelay < nextCpuDelay) {
1583 nextCpuDelay = nextWriteDelay;
1584 }
1585 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001586 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 this.wait(nextCpuDelay);
1588 }
1589 }
1590 } catch (InterruptedException e) {
1591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 updateCpuStatsNow();
1593 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001594 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 }
1596 }
1597 }
1598 };
1599 mProcessStatsThread.start();
1600 }
1601
1602 @Override
1603 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1604 throws RemoteException {
1605 try {
1606 return super.onTransact(code, data, reply, flags);
1607 } catch (RuntimeException e) {
1608 // The activity manager only throws security exceptions, so let's
1609 // log all others.
1610 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001611 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 }
1613 throw e;
1614 }
1615 }
1616
1617 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001618 final long now = SystemClock.uptimeMillis();
1619 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1620 return;
1621 }
1622 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1623 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 mProcessStatsThread.notify();
1625 }
1626 }
1627 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 void updateCpuStatsNow() {
1630 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001631 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 final long now = SystemClock.uptimeMillis();
1633 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001636 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1637 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 haveNewCpuStats = true;
1639 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001640 //Slog.i(TAG, mProcessStats.printCurrentState());
1641 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 // + mProcessStats.getTotalCpuPercent() + "%");
1643
Joe Onorato8a9b2202010-02-26 18:56:32 -08001644 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 if ("true".equals(SystemProperties.get("events.cpu"))) {
1646 int user = mProcessStats.getLastUserTime();
1647 int system = mProcessStats.getLastSystemTime();
1648 int iowait = mProcessStats.getLastIoWaitTime();
1649 int irq = mProcessStats.getLastIrqTime();
1650 int softIrq = mProcessStats.getLastSoftIrqTime();
1651 int idle = mProcessStats.getLastIdleTime();
1652
1653 int total = user + system + iowait + irq + softIrq + idle;
1654 if (total == 0) total = 1;
1655
Doug Zongker2bec3d42009-12-04 12:52:44 -08001656 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 ((user+system+iowait+irq+softIrq) * 100) / total,
1658 (user * 100) / total,
1659 (system * 100) / total,
1660 (iowait * 100) / total,
1661 (irq * 100) / total,
1662 (softIrq * 100) / total);
1663 }
1664 }
1665
Amith Yamasanie43530a2009-08-21 13:11:37 -07001666 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001667 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001668 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669 synchronized(mPidsSelfLocked) {
1670 if (haveNewCpuStats) {
1671 if (mBatteryStatsService.isOnBattery()) {
1672 final int N = mProcessStats.countWorkingStats();
1673 for (int i=0; i<N; i++) {
1674 ProcessStats.Stats st
1675 = mProcessStats.getWorkingStats(i);
1676 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1677 if (pr != null) {
1678 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1679 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001680 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001681 } else {
1682 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001683 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001684 if (ps != null) {
1685 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001686 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 }
1689 }
1690 }
1691 }
1692 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1695 mLastWriteTime = now;
1696 mBatteryStatsService.getActiveStatistics().writeLocked();
1697 }
1698 }
1699 }
1700 }
1701
1702 /**
1703 * Initialize the application bind args. These are passed to each
1704 * process when the bindApplication() IPC is sent to the process. They're
1705 * lazily setup to make sure the services are running when they're asked for.
1706 */
1707 private HashMap<String, IBinder> getCommonServicesLocked() {
1708 if (mAppBindArgs == null) {
1709 mAppBindArgs = new HashMap<String, IBinder>();
1710
1711 // Setup the application init args
1712 mAppBindArgs.put("package", ServiceManager.getService("package"));
1713 mAppBindArgs.put("window", ServiceManager.getService("window"));
1714 mAppBindArgs.put(Context.ALARM_SERVICE,
1715 ServiceManager.getService(Context.ALARM_SERVICE));
1716 }
1717 return mAppBindArgs;
1718 }
1719
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001720 private final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 if (mFocusedActivity != r) {
1722 mFocusedActivity = r;
1723 mWindowManager.setFocusedApp(r, true);
1724 }
1725 }
1726
Dianne Hackborn906497c2010-05-10 15:57:38 -07001727 private final void updateLruProcessInternalLocked(ProcessRecord app,
1728 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001730 int lrui = mLruProcesses.indexOf(app);
1731 if (lrui >= 0) mLruProcesses.remove(lrui);
1732
1733 int i = mLruProcesses.size()-1;
1734 int skipTop = 0;
1735
Dianne Hackborn906497c2010-05-10 15:57:38 -07001736 app.lruSeq = mLruSeq;
1737
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001738 // compute the new weight for this process.
1739 if (updateActivityTime) {
1740 app.lastActivityTime = SystemClock.uptimeMillis();
1741 }
1742 if (app.activities.size() > 0) {
1743 // If this process has activities, we more strongly want to keep
1744 // it around.
1745 app.lruWeight = app.lastActivityTime;
1746 } else if (app.pubProviders.size() > 0) {
1747 // If this process contains content providers, we want to keep
1748 // it a little more strongly.
1749 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1750 // Also don't let it kick out the first few "real" hidden processes.
1751 skipTop = MIN_HIDDEN_APPS;
1752 } else {
1753 // If this process doesn't have activities, we less strongly
1754 // want to keep it around, and generally want to avoid getting
1755 // in front of any very recently used activities.
1756 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1757 // Also don't let it kick out the first few "real" hidden processes.
1758 skipTop = MIN_HIDDEN_APPS;
1759 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001760
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001761 while (i >= 0) {
1762 ProcessRecord p = mLruProcesses.get(i);
1763 // If this app shouldn't be in front of the first N background
1764 // apps, then skip over that many that are currently hidden.
1765 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1766 skipTop--;
1767 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001768 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001769 mLruProcesses.add(i+1, app);
1770 break;
1771 }
1772 i--;
1773 }
1774 if (i < 0) {
1775 mLruProcesses.add(0, app);
1776 }
1777
Dianne Hackborn906497c2010-05-10 15:57:38 -07001778 // If the app is currently using a content provider or service,
1779 // bump those processes as well.
1780 if (app.connections.size() > 0) {
1781 for (ConnectionRecord cr : app.connections) {
1782 if (cr.binding != null && cr.binding.service != null
1783 && cr.binding.service.app != null
1784 && cr.binding.service.app.lruSeq != mLruSeq) {
1785 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1786 updateActivityTime, i+1);
1787 }
1788 }
1789 }
1790 if (app.conProviders.size() > 0) {
1791 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1792 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1793 updateLruProcessInternalLocked(cpr.app, oomAdj,
1794 updateActivityTime, i+1);
1795 }
1796 }
1797 }
1798
Joe Onorato8a9b2202010-02-26 18:56:32 -08001799 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 if (oomAdj) {
1801 updateOomAdjLocked();
1802 }
1803 }
1804
Dianne Hackborn906497c2010-05-10 15:57:38 -07001805 private final void updateLruProcessLocked(ProcessRecord app,
1806 boolean oomAdj, boolean updateActivityTime) {
1807 mLruSeq++;
1808 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1809 }
1810
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001811 private final boolean updateLRUListLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 final boolean hadit = mLRUActivities.remove(r);
1813 mLRUActivities.add(r);
1814 return hadit;
1815 }
1816
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001817 private final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 int i = mHistory.size()-1;
1819 while (i >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001820 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001821 if (!r.finishing && r != notTop) {
1822 return r;
1823 }
1824 i--;
1825 }
1826 return null;
1827 }
1828
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001829 private final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001830 int i = mHistory.size()-1;
1831 while (i >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001832 ActivityRecord r = (ActivityRecord)mHistory.get(i);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001833 if (!r.finishing && !r.delayedResume && r != notTop) {
1834 return r;
1835 }
1836 i--;
1837 }
1838 return null;
1839 }
1840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 /**
1842 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001843 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 *
1845 * @param token If non-null, any history records matching this token will be skipped.
1846 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1847 *
1848 * @return Returns the HistoryRecord of the next activity on the stack.
1849 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001850 private final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 int i = mHistory.size()-1;
1852 while (i >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001853 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 // Note: the taskId check depends on real taskId fields being non-zero
1855 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1856 return r;
1857 }
1858 i--;
1859 }
1860 return null;
1861 }
1862
1863 private final ProcessRecord getProcessRecordLocked(
1864 String processName, int uid) {
1865 if (uid == Process.SYSTEM_UID) {
1866 // The system gets to run in any process. If there are multiple
1867 // processes with the same uid, just pick the first (this
1868 // should never happen).
1869 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1870 processName);
1871 return procs != null ? procs.valueAt(0) : null;
1872 }
1873 ProcessRecord proc = mProcessNames.get(processName, uid);
1874 return proc;
1875 }
1876
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001877 private void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001878 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001879 try {
1880 if (pm.performDexOpt(packageName)) {
1881 mDidDexOpt = true;
1882 }
1883 } catch (RemoteException e) {
1884 }
1885 }
1886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 private boolean isNextTransitionForward() {
1888 int transit = mWindowManager.getPendingAppTransition();
1889 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1890 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1891 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1892 }
1893
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001894 private final boolean realStartActivityLocked(ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 ProcessRecord app, boolean andResume, boolean checkConfig)
1896 throws RemoteException {
1897
1898 r.startFreezingScreenLocked(app, 0);
1899 mWindowManager.setAppVisibility(r, true);
1900
1901 // Have the window manager re-evaluate the orientation of
1902 // the screen based on the new activity order. Note that
1903 // as a result of this, it can call back into the activity
1904 // manager with a new orientation. We don't care about that,
1905 // because the activity is not currently running so we are
1906 // just restarting it anyway.
1907 if (checkConfig) {
1908 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001909 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 r.mayFreezeScreenLocked(app) ? r : null);
1911 updateConfigurationLocked(config, r);
1912 }
1913
1914 r.app = app;
1915
Joe Onorato8a9b2202010-02-26 18:56:32 -08001916 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917
1918 int idx = app.activities.indexOf(r);
1919 if (idx < 0) {
1920 app.activities.add(r);
1921 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001922 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001923
1924 try {
1925 if (app.thread == null) {
1926 throw new RemoteException();
1927 }
1928 List<ResultInfo> results = null;
1929 List<Intent> newIntents = null;
1930 if (andResume) {
1931 results = r.results;
1932 newIntents = r.newIntents;
1933 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001934 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 + " icicle=" + r.icicle
1936 + " with results=" + results + " newIntents=" + newIntents
1937 + " andResume=" + andResume);
1938 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001939 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001940 System.identityHashCode(r),
1941 r.task.taskId, r.shortComponentName);
1942 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001943 if (r.isHomeActivity) {
1944 mHomeProcess = app;
1945 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001946 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001947 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001948 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949 r.info, r.icicle, results, newIntents, !andResume,
1950 isNextTransitionForward());
Dianne Hackborn860755f2010-06-03 18:47:52 -07001951
1952 if ((app.info.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
1953 // This may be a heavy-weight process! Note that the package
1954 // manager will ensure that only activity can run in the main
1955 // process of the .apk, which is the only thing that will be
1956 // considered heavy-weight.
1957 if (app.processName.equals(app.info.packageName)) {
1958 if (mHeavyWeightProcess != null && mHeavyWeightProcess != app) {
1959 Log.w(TAG, "Starting new heavy weight process " + app
1960 + " when already running " + mHeavyWeightProcess);
1961 }
1962 mHeavyWeightProcess = app;
1963 Message msg = mHandler.obtainMessage(POST_HEAVY_NOTIFICATION_MSG);
1964 msg.obj = r;
1965 mHandler.sendMessage(msg);
1966 }
1967 }
1968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001969 } catch (RemoteException e) {
1970 if (r.launchFailed) {
1971 // This is the second time we failed -- finish activity
1972 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001973 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001974 + r.intent.getComponent().flattenToShortString()
1975 + ", giving up", e);
1976 appDiedLocked(app, app.pid, app.thread);
1977 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1978 "2nd-crash");
1979 return false;
1980 }
1981
1982 // This is the first time we failed -- restart process and
1983 // retry.
1984 app.activities.remove(r);
1985 throw e;
1986 }
1987
1988 r.launchFailed = false;
1989 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001990 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001991 + " being launched, but already in LRU list");
1992 }
1993
1994 if (andResume) {
1995 // As part of the process of launching, ActivityThread also performs
1996 // a resume.
1997 r.state = ActivityState.RESUMED;
1998 r.icicle = null;
1999 r.haveState = false;
2000 r.stopped = false;
2001 mResumedActivity = r;
2002 r.task.touchActiveTime();
2003 completeResumeLocked(r);
2004 pauseIfSleepingLocked();
2005 } else {
2006 // This activity is not starting in the resumed state... which
2007 // should look like we asked it to pause+stop (but remain visible),
2008 // and it has done so and reported back the current icicle and
2009 // other state.
2010 r.state = ActivityState.STOPPED;
2011 r.stopped = true;
2012 }
2013
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002014 // Launch the new version setup screen if needed. We do this -after-
2015 // launching the initial activity (that is, home), so that it can have
2016 // a chance to initialize itself while in the background, making the
2017 // switch back to it faster and look better.
2018 startSetupActivityLocked();
2019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 return true;
2021 }
2022
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002023 private final void startSpecificActivityLocked(ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002024 boolean andResume, boolean checkConfig) {
2025 // Is this activity's application already running?
2026 ProcessRecord app = getProcessRecordLocked(r.processName,
2027 r.info.applicationInfo.uid);
2028
2029 if (r.startTime == 0) {
2030 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002031 if (mInitialStartTime == 0) {
2032 mInitialStartTime = r.startTime;
2033 }
2034 } else if (mInitialStartTime == 0) {
2035 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002036 }
2037
2038 if (app != null && app.thread != null) {
2039 try {
2040 realStartActivityLocked(r, app, andResume, checkConfig);
2041 return;
2042 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002043 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002044 + r.intent.getComponent().flattenToShortString(), e);
2045 }
2046
2047 // If a dead object exception was thrown -- fall through to
2048 // restart the application.
2049 }
2050
2051 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002052 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 }
2054
2055 private final ProcessRecord startProcessLocked(String processName,
2056 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002057 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002058 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
2059 // We don't have to do anything more if:
2060 // (1) There is an existing application record; and
2061 // (2) The caller doesn't think it is dead, OR there is no thread
2062 // object attached to it so we know it couldn't have crashed; and
2063 // (3) There is a pid assigned to it, so it is either starting or
2064 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002065 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 + " app=" + app + " knownToBeDead=" + knownToBeDead
2067 + " thread=" + (app != null ? app.thread : null)
2068 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01002069 if (app != null && app.pid > 0) {
2070 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002071 // We already have the app running, or are waiting for it to
2072 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01002073 return app;
2074 } else {
2075 // An application record is attached to a previous process,
2076 // clean it up now.
2077 handleAppDiedLocked(app, true);
2078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002079 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 String hostingNameStr = hostingName != null
2082 ? hostingName.flattenToShortString() : null;
2083
2084 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
2085 // If we are in the background, then check to see if this process
2086 // is bad. If so, we will just silently fail.
2087 if (mBadProcesses.get(info.processName, info.uid) != null) {
2088 return null;
2089 }
2090 } else {
2091 // When the user is explicitly starting a process, then clear its
2092 // crash count so that we won't make it bad until they see at
2093 // least one crash dialog again, and make the process good again
2094 // if it had been bad.
2095 mProcessCrashTimes.remove(info.processName, info.uid);
2096 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002097 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002098 info.processName);
2099 mBadProcesses.remove(info.processName, info.uid);
2100 if (app != null) {
2101 app.bad = false;
2102 }
2103 }
2104 }
2105
2106 if (app == null) {
2107 app = newProcessRecordLocked(null, info, processName);
2108 mProcessNames.put(processName, info.uid, app);
2109 } else {
2110 // If this is a new package in the process, add the package to the list
2111 app.addPackage(info.packageName);
2112 }
2113
2114 // If the system is not ready yet, then hold off on starting this
2115 // process until it is.
2116 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002117 && !isAllowedWhileBooting(info)
2118 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002119 if (!mProcessesOnHold.contains(app)) {
2120 mProcessesOnHold.add(app);
2121 }
2122 return app;
2123 }
2124
2125 startProcessLocked(app, hostingType, hostingNameStr);
2126 return (app.pid != 0) ? app : null;
2127 }
2128
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002129 boolean isAllowedWhileBooting(ApplicationInfo ai) {
2130 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
2131 }
2132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 private final void startProcessLocked(ProcessRecord app,
2134 String hostingType, String hostingNameStr) {
2135 if (app.pid > 0 && app.pid != MY_PID) {
2136 synchronized (mPidsSelfLocked) {
2137 mPidsSelfLocked.remove(app.pid);
2138 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
2139 }
2140 app.pid = 0;
2141 }
2142
2143 mProcessesOnHold.remove(app);
2144
2145 updateCpuStats();
2146
2147 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
2148 mProcDeaths[0] = 0;
2149
2150 try {
2151 int uid = app.info.uid;
2152 int[] gids = null;
2153 try {
2154 gids = mContext.getPackageManager().getPackageGids(
2155 app.info.packageName);
2156 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002157 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158 }
2159 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
2160 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2161 && mTopComponent != null
2162 && app.processName.equals(mTopComponent.getPackageName())) {
2163 uid = 0;
2164 }
2165 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
2166 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
2167 uid = 0;
2168 }
2169 }
2170 int debugFlags = 0;
2171 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
2172 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
2173 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08002174 // Run the app in safe mode if its manifest requests so or the
2175 // system is booted in safe mode.
2176 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
2177 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08002178 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
2179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
2181 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
2182 }
2183 if ("1".equals(SystemProperties.get("debug.assert"))) {
2184 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2185 }
2186 int pid = Process.start("android.app.ActivityThread",
2187 mSimpleProcessManagement ? app.processName : null, uid, uid,
2188 gids, debugFlags, null);
2189 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2190 synchronized (bs) {
2191 if (bs.isOnBattery()) {
2192 app.batteryStats.incStartsLocked();
2193 }
2194 }
2195
Doug Zongker2bec3d42009-12-04 12:52:44 -08002196 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002197 app.processName, hostingType,
2198 hostingNameStr != null ? hostingNameStr : "");
2199
2200 if (app.persistent) {
2201 Watchdog.getInstance().processStarted(app, app.processName, pid);
2202 }
2203
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002204 StringBuilder buf = mStringBuilder;
2205 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 buf.append("Start proc ");
2207 buf.append(app.processName);
2208 buf.append(" for ");
2209 buf.append(hostingType);
2210 if (hostingNameStr != null) {
2211 buf.append(" ");
2212 buf.append(hostingNameStr);
2213 }
2214 buf.append(": pid=");
2215 buf.append(pid);
2216 buf.append(" uid=");
2217 buf.append(uid);
2218 buf.append(" gids={");
2219 if (gids != null) {
2220 for (int gi=0; gi<gids.length; gi++) {
2221 if (gi != 0) buf.append(", ");
2222 buf.append(gids[gi]);
2223
2224 }
2225 }
2226 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002227 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002228 if (pid == 0 || pid == MY_PID) {
2229 // Processes are being emulated with threads.
2230 app.pid = MY_PID;
2231 app.removed = false;
2232 mStartingProcesses.add(app);
2233 } else if (pid > 0) {
2234 app.pid = pid;
2235 app.removed = false;
2236 synchronized (mPidsSelfLocked) {
2237 this.mPidsSelfLocked.put(pid, app);
2238 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2239 msg.obj = app;
2240 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2241 }
2242 } else {
2243 app.pid = 0;
2244 RuntimeException e = new RuntimeException(
2245 "Failure starting process " + app.processName
2246 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002247 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002248 }
2249 } catch (RuntimeException e) {
2250 // XXX do better error recovery.
2251 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002252 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 }
2254 }
2255
2256 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2257 if (mPausingActivity != null) {
2258 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002259 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002260 + mPausingActivity, e);
2261 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002262 ActivityRecord prev = mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263 if (prev == null) {
2264 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002265 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 resumeTopActivityLocked(null);
2267 return;
2268 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002269 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270 mResumedActivity = null;
2271 mPausingActivity = prev;
2272 mLastPausedActivity = prev;
2273 prev.state = ActivityState.PAUSING;
2274 prev.task.touchActiveTime();
2275
2276 updateCpuStats();
2277
2278 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002279 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002281 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 System.identityHashCode(prev),
2283 prev.shortComponentName);
2284 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2285 prev.configChangeFlags);
2286 updateUsageStats(prev, false);
2287 } catch (Exception e) {
2288 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002289 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290 mPausingActivity = null;
2291 mLastPausedActivity = null;
2292 }
2293 } else {
2294 mPausingActivity = null;
2295 mLastPausedActivity = null;
2296 }
2297
2298 // If we are not going to sleep, we want to ensure the device is
2299 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002300 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002301 mLaunchingActivity.acquire();
2302 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2303 // To be safe, don't allow the wake lock to be held for too long.
2304 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2305 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2306 }
2307 }
2308
2309
2310 if (mPausingActivity != null) {
2311 // Have the window manager pause its key dispatching until the new
2312 // activity has started. If we're pausing the activity just because
2313 // the screen is being turned off and the UI is sleeping, don't interrupt
2314 // key dispatch; the same activity will pick it up again on wakeup.
2315 if (!uiSleeping) {
2316 prev.pauseKeyDispatchingLocked();
2317 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002318 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002319 }
2320
2321 // Schedule a pause timeout in case the app doesn't respond.
2322 // We don't give it much time because this directly impacts the
2323 // responsiveness seen by the user.
2324 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2325 msg.obj = prev;
2326 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002327 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 } else {
2329 // This activity failed to schedule the
2330 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002331 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 resumeTopActivityLocked(null);
2333 }
2334 }
2335
2336 private final void completePauseLocked() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002337 ActivityRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002338 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002339
2340 if (prev != null) {
2341 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002342 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002343 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2344 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002345 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002346 if (prev.waitingVisible) {
2347 prev.waitingVisible = false;
2348 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002349 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350 TAG, "Complete pause, no longer waiting: " + prev);
2351 }
2352 if (prev.configDestroy) {
2353 // The previous is being paused because the configuration
2354 // is changing, which means it is actually stopping...
2355 // To juggle the fact that we are also starting a new
2356 // instance right now, we need to first completely stop
2357 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002358 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002359 destroyActivityLocked(prev, true);
2360 } else {
2361 mStoppingActivities.add(prev);
2362 if (mStoppingActivities.size() > 3) {
2363 // If we already have a few activities waiting to stop,
2364 // then give up on things going idle and start clearing
2365 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002366 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 Message msg = Message.obtain();
2368 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2369 mHandler.sendMessage(msg);
2370 }
2371 }
2372 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002373 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 prev = null;
2375 }
2376 mPausingActivity = null;
2377 }
2378
Dianne Hackborn55280a92009-05-07 15:53:46 -07002379 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 resumeTopActivityLocked(prev);
2381 } else {
2382 if (mGoingToSleep.isHeld()) {
2383 mGoingToSleep.release();
2384 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002385 if (mShuttingDown) {
2386 notifyAll();
2387 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002388 }
2389
2390 if (prev != null) {
2391 prev.resumeKeyDispatchingLocked();
2392 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002393
2394 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2395 long diff = 0;
2396 synchronized (mProcessStatsThread) {
2397 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2398 }
2399 if (diff > 0) {
2400 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2401 synchronized (bsi) {
2402 BatteryStatsImpl.Uid.Proc ps =
2403 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2404 prev.info.packageName);
2405 if (ps != null) {
2406 ps.addForegroundTimeLocked(diff);
2407 }
2408 }
2409 }
2410 }
2411 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 }
2413
2414 /**
2415 * Once we know that we have asked an application to put an activity in
2416 * the resumed state (either by launching it or explicitly telling it),
2417 * this function updates the rest of our state to match that fact.
2418 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002419 private final void completeResumeLocked(ActivityRecord next) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002420 next.idle = false;
2421 next.results = null;
2422 next.newIntents = null;
2423
2424 // schedule an idle timeout in case the app doesn't do it for us.
2425 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2426 msg.obj = next;
2427 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2428
2429 if (false) {
2430 // The activity was never told to pause, so just keep
2431 // things going as-is. To maintain our own state,
2432 // we need to emulate it coming back and saying it is
2433 // idle.
2434 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2435 msg.obj = next;
2436 mHandler.sendMessage(msg);
2437 }
2438
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002439 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002441 next.thumbnail = null;
2442 setFocusedActivityLocked(next);
2443 next.resumeKeyDispatchingLocked();
2444 ensureActivitiesVisibleLocked(null, 0);
2445 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002446 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002447
2448 // Mark the point when the activity is resuming
2449 // TODO: To be more accurate, the mark should be before the onCreate,
2450 // not after the onResume. But for subsequent starts, onResume is fine.
2451 if (next.app != null) {
2452 synchronized (mProcessStatsThread) {
2453 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2454 }
2455 } else {
2456 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458 }
2459
2460 /**
2461 * Make sure that all activities that need to be visible (that is, they
2462 * currently can be seen by the user) actually are.
2463 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002464 private final void ensureActivitiesVisibleLocked(ActivityRecord top,
2465 ActivityRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002466 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 TAG, "ensureActivitiesVisible behind " + top
2468 + " configChanges=0x" + Integer.toHexString(configChanges));
2469
2470 // If the top activity is not fullscreen, then we need to
2471 // make sure any activities under it are now visible.
2472 final int count = mHistory.size();
2473 int i = count-1;
2474 while (mHistory.get(i) != top) {
2475 i--;
2476 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002477 ActivityRecord r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002478 boolean behindFullscreen = false;
2479 for (; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002480 r = (ActivityRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002481 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 TAG, "Make visible? " + r + " finishing=" + r.finishing
2483 + " state=" + r.state);
2484 if (r.finishing) {
2485 continue;
2486 }
2487
2488 final boolean doThisProcess = onlyThisProcess == null
2489 || onlyThisProcess.equals(r.processName);
2490
2491 // First: if this is not the current activity being started, make
2492 // sure it matches the current configuration.
2493 if (r != starting && doThisProcess) {
2494 ensureActivityConfigurationLocked(r, 0);
2495 }
2496
2497 if (r.app == null || r.app.thread == null) {
2498 if (onlyThisProcess == null
2499 || onlyThisProcess.equals(r.processName)) {
2500 // This activity needs to be visible, but isn't even
2501 // running... get it started, but don't resume it
2502 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002503 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002504 TAG, "Start and freeze screen for " + r);
2505 if (r != starting) {
2506 r.startFreezingScreenLocked(r.app, configChanges);
2507 }
2508 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002509 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 TAG, "Starting and making visible: " + r);
2511 mWindowManager.setAppVisibility(r, true);
2512 }
2513 if (r != starting) {
2514 startSpecificActivityLocked(r, false, false);
2515 }
2516 }
2517
2518 } else if (r.visible) {
2519 // If this activity is already visible, then there is nothing
2520 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002521 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002522 TAG, "Skipping: already visible at " + r);
2523 r.stopFreezingScreenLocked(false);
2524
2525 } else if (onlyThisProcess == null) {
2526 // This activity is not currently visible, but is running.
2527 // Tell it to become visible.
2528 r.visible = true;
2529 if (r.state != ActivityState.RESUMED && r != starting) {
2530 // If this activity is paused, tell it
2531 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002532 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 TAG, "Making visible and scheduling visibility: " + r);
2534 try {
2535 mWindowManager.setAppVisibility(r, true);
2536 r.app.thread.scheduleWindowVisibility(r, true);
2537 r.stopFreezingScreenLocked(false);
2538 } catch (Exception e) {
2539 // Just skip on any failure; we'll make it
2540 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002541 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 + r.intent.getComponent(), e);
2543 }
2544 }
2545 }
2546
2547 // Aggregate current change flags.
2548 configChanges |= r.configChangeFlags;
2549
2550 if (r.fullscreen) {
2551 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002552 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 TAG, "Stopping: fullscreen at " + r);
2554 behindFullscreen = true;
2555 i--;
2556 break;
2557 }
2558 }
2559
2560 // Now for any activities that aren't visible to the user, make
2561 // sure they no longer are keeping the screen frozen.
2562 while (i >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002563 r = (ActivityRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002564 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002565 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2566 + " state=" + r.state
2567 + " behindFullscreen=" + behindFullscreen);
2568 if (!r.finishing) {
2569 if (behindFullscreen) {
2570 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002571 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002572 TAG, "Making invisible: " + r);
2573 r.visible = false;
2574 try {
2575 mWindowManager.setAppVisibility(r, false);
2576 if ((r.state == ActivityState.STOPPING
2577 || r.state == ActivityState.STOPPED)
2578 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002579 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 TAG, "Scheduling invisibility: " + r);
2581 r.app.thread.scheduleWindowVisibility(r, false);
2582 }
2583 } catch (Exception e) {
2584 // Just skip on any failure; we'll make it
2585 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002586 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 + r.intent.getComponent(), e);
2588 }
2589 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002590 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 TAG, "Already invisible: " + r);
2592 }
2593 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002594 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 TAG, "Now behindFullscreen: " + r);
2596 behindFullscreen = true;
2597 }
2598 }
2599 i--;
2600 }
2601 }
2602
2603 /**
2604 * Version of ensureActivitiesVisible that can easily be called anywhere.
2605 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002606 private final void ensureActivitiesVisibleLocked(ActivityRecord starting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 int configChanges) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002608 ActivityRecord r = topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609 if (r != null) {
2610 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2611 }
2612 }
2613
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002614 private void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 if (resumed) {
2616 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2617 } else {
2618 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2619 }
2620 }
2621
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002622 private boolean startHomeActivityLocked() {
2623 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2624 && mTopAction == null) {
2625 // We are running in factory test mode, but unable to find
2626 // the factory test app, so just sit around displaying the
2627 // error message and don't try to start anything.
2628 return false;
2629 }
2630 Intent intent = new Intent(
2631 mTopAction,
2632 mTopData != null ? Uri.parse(mTopData) : null);
2633 intent.setComponent(mTopComponent);
2634 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2635 intent.addCategory(Intent.CATEGORY_HOME);
2636 }
2637 ActivityInfo aInfo =
2638 intent.resolveActivityInfo(mContext.getPackageManager(),
2639 STOCK_PM_FLAGS);
2640 if (aInfo != null) {
2641 intent.setComponent(new ComponentName(
2642 aInfo.applicationInfo.packageName, aInfo.name));
2643 // Don't do this if the home app is currently being
2644 // instrumented.
2645 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2646 aInfo.applicationInfo.uid);
2647 if (app == null || app.instrumentationClass == null) {
2648 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2649 startActivityLocked(null, intent, null, null, 0, aInfo,
2650 null, null, 0, 0, 0, false, false);
2651 }
2652 }
2653
2654
2655 return true;
2656 }
2657
2658 /**
2659 * Starts the "new version setup screen" if appropriate.
2660 */
2661 private void startSetupActivityLocked() {
2662 // Only do this once per boot.
2663 if (mCheckedForSetup) {
2664 return;
2665 }
2666
2667 // We will show this screen if the current one is a different
2668 // version than the last one shown, and we are not running in
2669 // low-level factory test mode.
2670 final ContentResolver resolver = mContext.getContentResolver();
2671 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2672 Settings.Secure.getInt(resolver,
2673 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2674 mCheckedForSetup = true;
2675
2676 // See if we should be showing the platform update setup UI.
2677 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2678 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2679 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2680
2681 // We don't allow third party apps to replace this.
2682 ResolveInfo ri = null;
2683 for (int i=0; ris != null && i<ris.size(); i++) {
2684 if ((ris.get(i).activityInfo.applicationInfo.flags
2685 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2686 ri = ris.get(i);
2687 break;
2688 }
2689 }
2690
2691 if (ri != null) {
2692 String vers = ri.activityInfo.metaData != null
2693 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2694 : null;
2695 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2696 vers = ri.activityInfo.applicationInfo.metaData.getString(
2697 Intent.METADATA_SETUP_VERSION);
2698 }
2699 String lastVers = Settings.Secure.getString(
2700 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2701 if (vers != null && !vers.equals(lastVers)) {
2702 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2703 intent.setComponent(new ComponentName(
2704 ri.activityInfo.packageName, ri.activityInfo.name));
2705 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2706 null, null, 0, 0, 0, false, false);
2707 }
2708 }
2709 }
2710 }
2711
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002712 private void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002713 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002714
2715 final int identHash = System.identityHashCode(r);
2716 updateUsageStats(r, true);
2717
2718 int i = mWatchers.beginBroadcast();
2719 while (i > 0) {
2720 i--;
2721 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2722 if (w != null) {
2723 try {
2724 w.activityResuming(identHash);
2725 } catch (RemoteException e) {
2726 }
2727 }
2728 }
2729 mWatchers.finishBroadcast();
2730 }
2731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 /**
2733 * Ensure that the top activity in the stack is resumed.
2734 *
2735 * @param prev The previously resumed activity, for when in the process
2736 * of pausing; can be null to call from elsewhere.
2737 *
2738 * @return Returns true if something is being resumed, or false if
2739 * nothing happened.
2740 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002741 private final boolean resumeTopActivityLocked(ActivityRecord prev) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 // Find the first activity that is not finishing.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002743 ActivityRecord next = topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744
2745 // Remember how we'll process this pause/resume situation, and ensure
2746 // that the state is reset however we wind up proceeding.
2747 final boolean userLeaving = mUserLeaving;
2748 mUserLeaving = false;
2749
2750 if (next == null) {
2751 // There are no more activities! Let's just start up the
2752 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002753 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002754 }
2755
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002756 next.delayedResume = false;
2757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002758 // If the top activity is the resumed one, nothing to do.
2759 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2760 // Make sure we have executed any pending transitions, since there
2761 // should be nothing left to do at this point.
2762 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002763 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002764 return false;
2765 }
2766
2767 // If we are sleeping, and there is no resumed activity, and the top
2768 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002769 if ((mSleeping || mShuttingDown)
2770 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002771 // Make sure we have executed any pending transitions, since there
2772 // should be nothing left to do at this point.
2773 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002774 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002775 return false;
2776 }
2777
2778 // The activity may be waiting for stop, but that is no longer
2779 // appropriate for it.
2780 mStoppingActivities.remove(next);
2781 mWaitingVisibleActivities.remove(next);
2782
Joe Onorato8a9b2202010-02-26 18:56:32 -08002783 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002784
2785 // If we are currently pausing an activity, then don't do anything
2786 // until that is done.
2787 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002788 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002789 return false;
2790 }
2791
2792 // We need to start pausing the current activity so the top one
2793 // can be resumed...
2794 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002795 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002796 startPausingLocked(userLeaving, false);
2797 return true;
2798 }
2799
2800 if (prev != null && prev != next) {
2801 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2802 prev.waitingVisible = true;
2803 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002804 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002805 TAG, "Resuming top, waiting visible to hide: " + prev);
2806 } else {
2807 // The next activity is already visible, so hide the previous
2808 // activity's windows right now so we can show the new one ASAP.
2809 // We only do this if the previous is finishing, which should mean
2810 // it is on top of the one being resumed so hiding it quickly
2811 // is good. Otherwise, we want to do the normal route of allowing
2812 // the resumed activity to be shown so we can decide if the
2813 // previous should actually be hidden depending on whether the
2814 // new one is found to be full-screen or not.
2815 if (prev.finishing) {
2816 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002817 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002818 + prev + ", waitingVisible="
2819 + (prev != null ? prev.waitingVisible : null)
2820 + ", nowVisible=" + next.nowVisible);
2821 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002822 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002823 + prev + ", waitingVisible="
2824 + (prev != null ? prev.waitingVisible : null)
2825 + ", nowVisible=" + next.nowVisible);
2826 }
2827 }
2828 }
2829
2830 // We are starting up the next activity, so tell the window manager
2831 // that the previous one will be hidden soon. This way it can know
2832 // to ignore it when computing the desired screen orientation.
2833 if (prev != null) {
2834 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002835 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002836 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002837 if (mNoAnimActivities.contains(prev)) {
2838 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2839 } else {
2840 mWindowManager.prepareAppTransition(prev.task == next.task
2841 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2842 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2843 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002844 mWindowManager.setAppWillBeHidden(prev);
2845 mWindowManager.setAppVisibility(prev, false);
2846 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002847 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002849 if (mNoAnimActivities.contains(next)) {
2850 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2851 } else {
2852 mWindowManager.prepareAppTransition(prev.task == next.task
2853 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2854 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 }
2857 if (false) {
2858 mWindowManager.setAppWillBeHidden(prev);
2859 mWindowManager.setAppVisibility(prev, false);
2860 }
2861 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002862 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002864 if (mNoAnimActivities.contains(next)) {
2865 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2866 } else {
2867 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 }
2870
2871 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002872 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002873
2874 // This activity is now becoming visible.
2875 mWindowManager.setAppVisibility(next, true);
2876
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002877 ActivityRecord lastResumedActivity = mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002878 ActivityState lastState = next.state;
2879
2880 updateCpuStats();
2881
2882 next.state = ActivityState.RESUMED;
2883 mResumedActivity = next;
2884 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002885 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 updateLRUListLocked(next);
2887
2888 // Have the window manager re-evaluate the orientation of
2889 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002890 boolean updated;
2891 synchronized (this) {
2892 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2893 mConfiguration,
2894 next.mayFreezeScreenLocked(next.app) ? next : null);
2895 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002896 next.frozenBeforeDestroy = true;
2897 }
2898 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002900 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002901 // The configuration update wasn't able to keep the existing
2902 // instance of the activity, and instead started a new one.
2903 // We should be all done, but let's just make sure our activity
2904 // is still at the top and schedule another run if something
2905 // weird happened.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002906 ActivityRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002907 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 "Activity config changed during resume: " + next
2909 + ", new next: " + nextNext);
2910 if (nextNext != next) {
2911 // Do over!
2912 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2913 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002914 setFocusedActivityLocked(next);
2915 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002916 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002917 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002918 return true;
2919 }
2920
2921 try {
2922 // Deliver all pending results.
2923 ArrayList a = next.results;
2924 if (a != null) {
2925 final int N = a.size();
2926 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002927 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 TAG, "Delivering results to " + next
2929 + ": " + a);
2930 next.app.thread.scheduleSendResult(next, a);
2931 }
2932 }
2933
2934 if (next.newIntents != null) {
2935 next.app.thread.scheduleNewIntent(next.newIntents, next);
2936 }
2937
Doug Zongker2bec3d42009-12-04 12:52:44 -08002938 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 System.identityHashCode(next),
2940 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941
2942 next.app.thread.scheduleResumeActivity(next,
2943 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 pauseIfSleepingLocked();
2946
2947 } catch (Exception e) {
2948 // Whoops, need to restart this activity!
2949 next.state = lastState;
2950 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002951 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002952 if (!next.hasBeenLaunched) {
2953 next.hasBeenLaunched = true;
2954 } else {
2955 if (SHOW_APP_STARTING_ICON) {
2956 mWindowManager.setAppStartingWindow(
2957 next, next.packageName, next.theme,
2958 next.nonLocalizedLabel,
2959 next.labelRes, next.icon, null, true);
2960 }
2961 }
2962 startSpecificActivityLocked(next, true, false);
2963 return true;
2964 }
2965
2966 // From this point on, if something goes wrong there is no way
2967 // to recover the activity.
2968 try {
2969 next.visible = true;
2970 completeResumeLocked(next);
2971 } catch (Exception e) {
2972 // If any exception gets thrown, toss away this
2973 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002974 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2976 "resume-exception");
2977 return true;
2978 }
2979
2980 // Didn't need to use the icicle, and it is now out of date.
2981 next.icicle = null;
2982 next.haveState = false;
2983 next.stopped = false;
2984
2985 } else {
2986 // Whoops, need to restart this activity!
2987 if (!next.hasBeenLaunched) {
2988 next.hasBeenLaunched = true;
2989 } else {
2990 if (SHOW_APP_STARTING_ICON) {
2991 mWindowManager.setAppStartingWindow(
2992 next, next.packageName, next.theme,
2993 next.nonLocalizedLabel,
2994 next.labelRes, next.icon, null, true);
2995 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002996 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 }
2998 startSpecificActivityLocked(next, true, true);
2999 }
3000
3001 return true;
3002 }
3003
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003004 private final void startActivityLocked(ActivityRecord r, boolean newTask,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003005 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003006 final int NH = mHistory.size();
3007
3008 int addPos = -1;
3009
3010 if (!newTask) {
3011 // If starting in an existing task, find where that is...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003012 ActivityRecord next = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003013 boolean startIt = true;
3014 for (int i = NH-1; i >= 0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003015 ActivityRecord p = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003016 if (p.finishing) {
3017 continue;
3018 }
3019 if (p.task == r.task) {
3020 // Here it is! Now, if this is not yet visible to the
3021 // user, then just add it without starting; it will
3022 // get started when the user navigates back to it.
3023 addPos = i+1;
3024 if (!startIt) {
3025 mHistory.add(addPos, r);
3026 r.inHistory = true;
3027 r.task.numActivities++;
3028 mWindowManager.addAppToken(addPos, r, r.task.taskId,
3029 r.info.screenOrientation, r.fullscreen);
3030 if (VALIDATE_TOKENS) {
3031 mWindowManager.validateAppTokens(mHistory);
3032 }
3033 return;
3034 }
3035 break;
3036 }
3037 if (p.fullscreen) {
3038 startIt = false;
3039 }
3040 next = p;
3041 }
3042 }
3043
3044 // Place a new activity at top of stack, so it is next to interact
3045 // with the user.
3046 if (addPos < 0) {
3047 addPos = mHistory.size();
3048 }
3049
3050 // If we are not placing the new activity frontmost, we do not want
3051 // to deliver the onUserLeaving callback to the actual frontmost
3052 // activity
3053 if (addPos < NH) {
3054 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003055 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003056 }
3057
3058 // Slot the activity into the history stack and proceed
3059 mHistory.add(addPos, r);
3060 r.inHistory = true;
3061 r.frontOfTask = newTask;
3062 r.task.numActivities++;
3063 if (NH > 0) {
3064 // We want to show the starting preview window if we are
3065 // switching to a new task, or the next activity's process is
3066 // not currently running.
3067 boolean showStartingIcon = newTask;
3068 ProcessRecord proc = r.app;
3069 if (proc == null) {
3070 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
3071 }
3072 if (proc == null || proc.thread == null) {
3073 showStartingIcon = true;
3074 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003075 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003076 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003077 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3078 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
3079 mNoAnimActivities.add(r);
3080 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3081 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
3082 mNoAnimActivities.remove(r);
3083 } else {
3084 mWindowManager.prepareAppTransition(newTask
3085 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
3086 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
3087 mNoAnimActivities.remove(r);
3088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 mWindowManager.addAppToken(
3090 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
3091 boolean doShow = true;
3092 if (newTask) {
3093 // Even though this activity is starting fresh, we still need
3094 // to reset it to make sure we apply affinities to move any
3095 // existing activities from other tasks in to it.
3096 // If the caller has requested that the target task be
3097 // reset, then do so.
3098 if ((r.intent.getFlags()
3099 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3100 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003101 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 }
3103 }
3104 if (SHOW_APP_STARTING_ICON && doShow) {
3105 // Figure out if we are transitioning from another activity that is
3106 // "has the same starting icon" as the next one. This allows the
3107 // window manager to keep the previous window it had previously
3108 // created, if it still had one.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003109 ActivityRecord prev = mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 if (prev != null) {
3111 // We don't want to reuse the previous starting preview if:
3112 // (1) The current activity is in a different task.
3113 if (prev.task != r.task) prev = null;
3114 // (2) The current activity is already displayed.
3115 else if (prev.nowVisible) prev = null;
3116 }
3117 mWindowManager.setAppStartingWindow(
3118 r, r.packageName, r.theme, r.nonLocalizedLabel,
3119 r.labelRes, r.icon, prev, showStartingIcon);
3120 }
3121 } else {
3122 // If this is the first activity, don't do any fancy animations,
3123 // because there is nothing for it to animate on top of.
3124 mWindowManager.addAppToken(addPos, r, r.task.taskId,
3125 r.info.screenOrientation, r.fullscreen);
3126 }
3127 if (VALIDATE_TOKENS) {
3128 mWindowManager.validateAppTokens(mHistory);
3129 }
3130
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003131 if (doResume) {
3132 resumeTopActivityLocked(null);
3133 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003134 }
3135
3136 /**
3137 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003138 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
3139 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140 * an instance of that activity in the stack and, if found, finish all
3141 * activities on top of it and return the instance.
3142 *
3143 * @param newR Description of the new activity being started.
3144 * @return Returns the old activity that should be continue to be used,
3145 * or null if none was found.
3146 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003147 private final ActivityRecord performClearTaskLocked(int taskId,
3148 ActivityRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003149 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003150
3151 // First find the requested task.
3152 while (i > 0) {
3153 i--;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003154 ActivityRecord r = (ActivityRecord)mHistory.get(i);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003155 if (r.task.taskId == taskId) {
3156 i++;
3157 break;
3158 }
3159 }
3160
3161 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 while (i > 0) {
3163 i--;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003164 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 if (r.finishing) {
3166 continue;
3167 }
3168 if (r.task.taskId != taskId) {
3169 return null;
3170 }
3171 if (r.realActivity.equals(newR.realActivity)) {
3172 // Here it is! Now finish everything in front...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003173 ActivityRecord ret = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003174 if (doClear) {
3175 while (i < (mHistory.size()-1)) {
3176 i++;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003177 r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 if (r.finishing) {
3179 continue;
3180 }
3181 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3182 null, "clear")) {
3183 i--;
3184 }
3185 }
3186 }
3187
3188 // Finally, if this is a normal launch mode (that is, not
3189 // expecting onNewIntent()), then we will finish the current
3190 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003191 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
3192 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003193 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003194 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07003196 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003197 null, "clear");
3198 }
3199 return null;
3200 }
3201 }
3202
3203 return ret;
3204 }
3205 }
3206
3207 return null;
3208 }
3209
3210 /**
3211 * Find the activity in the history stack within the given task. Returns
3212 * the index within the history at which it's found, or < 0 if not found.
3213 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003214 private final int findActivityInHistoryLocked(ActivityRecord r, int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003215 int i = mHistory.size();
3216 while (i > 0) {
3217 i--;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003218 ActivityRecord candidate = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003219 if (candidate.task.taskId != task) {
3220 break;
3221 }
3222 if (candidate.realActivity.equals(r.realActivity)) {
3223 return i;
3224 }
3225 }
3226
3227 return -1;
3228 }
3229
3230 /**
3231 * Reorder the history stack so that the activity at the given index is
3232 * brought to the front.
3233 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003234 private final ActivityRecord moveActivityToFrontLocked(int where) {
3235 ActivityRecord newTop = (ActivityRecord)mHistory.remove(where);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003236 int top = mHistory.size();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003237 ActivityRecord oldTop = (ActivityRecord)mHistory.get(top-1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003238 mHistory.add(top, newTop);
3239 oldTop.frontOfTask = false;
3240 newTop.frontOfTask = true;
3241 return newTop;
3242 }
3243
3244 /**
3245 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3246 * method will be called at the proper time.
3247 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003248 private final void deliverNewIntentLocked(ActivityRecord r, Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 boolean sent = false;
3250 if (r.state == ActivityState.RESUMED
3251 && r.app != null && r.app.thread != null) {
3252 try {
3253 ArrayList<Intent> ar = new ArrayList<Intent>();
3254 ar.add(new Intent(intent));
3255 r.app.thread.scheduleNewIntent(ar, r);
3256 sent = true;
3257 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003258 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003259 }
3260 }
3261 if (!sent) {
3262 r.addNewIntentLocked(new Intent(intent));
3263 }
3264 }
3265
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003266 private final void logStartActivity(int tag, ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 TaskRecord task) {
3268 EventLog.writeEvent(tag,
3269 System.identityHashCode(r), task.taskId,
3270 r.shortComponentName, r.intent.getAction(),
3271 r.intent.getType(), r.intent.getDataString(),
3272 r.intent.getFlags());
3273 }
3274
3275 private final int startActivityLocked(IApplicationThread caller,
3276 Intent intent, String resolvedType,
3277 Uri[] grantedUriPermissions,
3278 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3279 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003280 int callingPid, int callingUid, boolean onlyIfNeeded,
3281 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003282 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003283
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003284 ActivityRecord sourceRecord = null;
3285 ActivityRecord resultRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003286 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003287 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003288 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3290 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003291 sourceRecord = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003292 if (requestCode >= 0 && !sourceRecord.finishing) {
3293 resultRecord = sourceRecord;
3294 }
3295 }
3296 }
3297
3298 int launchFlags = intent.getFlags();
3299
3300 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3301 && sourceRecord != null) {
3302 // Transfer the result target from the source activity to the new
3303 // one being started, including any failures.
3304 if (requestCode >= 0) {
3305 return START_FORWARD_AND_REQUEST_CONFLICT;
3306 }
3307 resultRecord = sourceRecord.resultTo;
3308 resultWho = sourceRecord.resultWho;
3309 requestCode = sourceRecord.requestCode;
3310 sourceRecord.resultTo = null;
3311 if (resultRecord != null) {
3312 resultRecord.removeResultsLocked(
3313 sourceRecord, resultWho, requestCode);
3314 }
3315 }
3316
3317 int err = START_SUCCESS;
3318
3319 if (intent.getComponent() == null) {
3320 // We couldn't find a class that can handle the given Intent.
3321 // That's the end of that!
3322 err = START_INTENT_NOT_RESOLVED;
3323 }
3324
3325 if (err == START_SUCCESS && aInfo == null) {
3326 // We couldn't find the specific class specified in the Intent.
3327 // Also the end of the line.
3328 err = START_CLASS_NOT_FOUND;
3329 }
3330
3331 ProcessRecord callerApp = null;
3332 if (err == START_SUCCESS && caller != null) {
3333 callerApp = getRecordForAppLocked(caller);
3334 if (callerApp != null) {
3335 callingPid = callerApp.pid;
3336 callingUid = callerApp.info.uid;
3337 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003338 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 + " (pid=" + callingPid + ") when starting: "
3340 + intent.toString());
3341 err = START_PERMISSION_DENIED;
3342 }
3343 }
3344
3345 if (err != START_SUCCESS) {
3346 if (resultRecord != null) {
3347 sendActivityResultLocked(-1,
3348 resultRecord, resultWho, requestCode,
3349 Activity.RESULT_CANCELED, null);
3350 }
3351 return err;
3352 }
3353
3354 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3355 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3356 if (perm != PackageManager.PERMISSION_GRANTED) {
3357 if (resultRecord != null) {
3358 sendActivityResultLocked(-1,
3359 resultRecord, resultWho, requestCode,
3360 Activity.RESULT_CANCELED, null);
3361 }
3362 String msg = "Permission Denial: starting " + intent.toString()
3363 + " from " + callerApp + " (pid=" + callingPid
3364 + ", uid=" + callingUid + ")"
3365 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003366 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 throw new SecurityException(msg);
3368 }
3369
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003370 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371 boolean abort = false;
3372 try {
3373 // The Intent we give to the watcher has the extra data
3374 // stripped off, since it can contain private information.
3375 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003376 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 aInfo.applicationInfo.packageName);
3378 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003379 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003380 }
3381
3382 if (abort) {
3383 if (resultRecord != null) {
3384 sendActivityResultLocked(-1,
3385 resultRecord, resultWho, requestCode,
3386 Activity.RESULT_CANCELED, null);
3387 }
3388 // We pretend to the caller that it was really started, but
3389 // they will just get a cancel result.
3390 return START_SUCCESS;
3391 }
3392 }
3393
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003394 ActivityRecord r = new ActivityRecord(this, callerApp, callingUid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003396 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003397
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003398 if (mResumedActivity == null
3399 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3400 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3401 PendingActivityLaunch pal = new PendingActivityLaunch();
3402 pal.r = r;
3403 pal.sourceRecord = sourceRecord;
3404 pal.grantedUriPermissions = grantedUriPermissions;
3405 pal.grantedMode = grantedMode;
3406 pal.onlyIfNeeded = onlyIfNeeded;
3407 mPendingActivityLaunches.add(pal);
3408 return START_SWITCHES_CANCELED;
3409 }
3410 }
3411
3412 if (mDidAppSwitch) {
3413 // This is the second allowed switch since we stopped switches,
3414 // so now just generally allow switches. Use case: user presses
3415 // home (switches disabled, switch to home, mDidAppSwitch now true);
3416 // user taps a home icon (coming from home so allowed, we hit here
3417 // and now allow anyone to switch again).
3418 mAppSwitchesAllowedTime = 0;
3419 } else {
3420 mDidAppSwitch = true;
3421 }
3422
3423 doPendingActivityLaunchesLocked(false);
3424
3425 return startActivityUncheckedLocked(r, sourceRecord,
3426 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3427 }
3428
3429 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3430 final int N = mPendingActivityLaunches.size();
3431 if (N <= 0) {
3432 return;
3433 }
3434 for (int i=0; i<N; i++) {
3435 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3436 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3437 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3438 doResume && i == (N-1));
3439 }
3440 mPendingActivityLaunches.clear();
3441 }
3442
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003443 private final int startActivityUncheckedLocked(ActivityRecord r,
3444 ActivityRecord sourceRecord, Uri[] grantedUriPermissions,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003445 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3446 final Intent intent = r.intent;
3447 final int callingUid = r.launchedFromUid;
3448
3449 int launchFlags = intent.getFlags();
3450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451 // We'll invoke onUserLeaving before onPause only if the launching
3452 // activity did not explicitly state that this is an automated launch.
3453 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003454 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 "startActivity() => mUserLeaving=" + mUserLeaving);
3456
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003457 // If the caller has asked not to resume at this point, we make note
3458 // of this in the record so that we can skip it when trying to find
3459 // the top running activity.
3460 if (!doResume) {
3461 r.delayedResume = true;
3462 }
3463
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003464 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003465 != 0 ? r : null;
3466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003467 // If the onlyIfNeeded flag is set, then we can do this if the activity
3468 // being launched is the same as the one making the call... or, as
3469 // a special case, if we do not know the caller then we count the
3470 // current top activity as the caller.
3471 if (onlyIfNeeded) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003472 ActivityRecord checkedCaller = sourceRecord;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003474 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003475 }
3476 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3477 // Caller is not the same as launcher, so always needed.
3478 onlyIfNeeded = false;
3479 }
3480 }
3481
3482 if (grantedUriPermissions != null && callingUid > 0) {
3483 for (int i=0; i<grantedUriPermissions.length; i++) {
3484 grantUriPermissionLocked(callingUid, r.packageName,
3485 grantedUriPermissions[i], grantedMode, r);
3486 }
3487 }
3488
3489 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3490 intent, r);
3491
3492 if (sourceRecord == null) {
3493 // This activity is not being started from another... in this
3494 // case we -always- start a new task.
3495 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003496 Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 + intent);
3498 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3499 }
3500 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3501 // The original activity who is starting us is running as a single
3502 // instance... this new activity it is starting must go on its
3503 // own task.
3504 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3505 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3506 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3507 // The activity being started is a single instance... it always
3508 // gets launched into its own task.
3509 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3510 }
3511
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003512 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 // For whatever reason this activity is being launched into a new
3514 // task... yet the caller has requested a result back. Well, that
3515 // is pretty messed up, so instead immediately send back a cancel
3516 // and let the new task continue launched as normal without a
3517 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003518 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003520 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 Activity.RESULT_CANCELED, null);
3522 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 }
3524
3525 boolean addingToTask = false;
3526 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3527 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3528 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3529 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3530 // If bring to front is requested, and no result is requested, and
3531 // we can find a task that was started with this same
3532 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003533 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003534 // See if there is a task to bring to the front. If this is
3535 // a SINGLE_INSTANCE activity, there can be one and only one
3536 // instance of it in the history, and it is always in its own
3537 // unique task, so we do a special search.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003538 ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 ? findTaskLocked(intent, r.info)
3540 : findActivityLocked(intent, r.info);
3541 if (taskTop != null) {
3542 if (taskTop.task.intent == null) {
3543 // This task was started because of movement of
3544 // the activity based on affinity... now that we
3545 // are actually launching it, we can assign the
3546 // base intent.
3547 taskTop.task.setIntent(intent, r.info);
3548 }
3549 // If the target task is not in the front, then we need
3550 // to bring it to the front... except... well, with
3551 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3552 // to have the same behavior as if a new instance was
3553 // being started, which means not bringing it to the front
3554 // if the caller is not itself in the front.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003555 ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556 if (curTop.task != taskTop.task) {
3557 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3558 boolean callerAtFront = sourceRecord == null
3559 || curTop.task == sourceRecord.task;
3560 if (callerAtFront) {
3561 // We really do want to push this one into the
3562 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003563 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003564 }
3565 }
3566 // If the caller has requested that the target task be
3567 // reset, then do so.
3568 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3569 taskTop = resetTaskIfNeededLocked(taskTop, r);
3570 }
3571 if (onlyIfNeeded) {
3572 // We don't need to start a new activity, and
3573 // the client said not to do anything if that
3574 // is the case, so this is it! And for paranoia, make
3575 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003576 if (doResume) {
3577 resumeTopActivityLocked(null);
3578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003579 return START_RETURN_INTENT_TO_CALLER;
3580 }
3581 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3582 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3583 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3584 // In this situation we want to remove all activities
3585 // from the task up to the one being started. In most
3586 // cases this means we are resetting the task to its
3587 // initial state.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003588 ActivityRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003589 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590 if (top != null) {
3591 if (top.frontOfTask) {
3592 // Activity aliases may mean we use different
3593 // intents for the top activity, so make sure
3594 // the task now has the identity of the new
3595 // intent.
3596 top.task.setIntent(r.intent, r.info);
3597 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003598 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 deliverNewIntentLocked(top, r.intent);
3600 } else {
3601 // A special case: we need to
3602 // start the activity because it is not currently
3603 // running, and the caller has asked to clear the
3604 // current task to have this activity at the top.
3605 addingToTask = true;
3606 // Now pretend like this activity is being started
3607 // by the top of its task, so it is put in the
3608 // right place.
3609 sourceRecord = taskTop;
3610 }
3611 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3612 // In this case the top activity on the task is the
3613 // same as the one being launched, so we take that
3614 // as a request to bring the task to the foreground.
3615 // If the top activity in the task is the root
3616 // activity, deliver this new intent to it if it
3617 // desires.
3618 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3619 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003620 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 if (taskTop.frontOfTask) {
3622 taskTop.task.setIntent(r.intent, r.info);
3623 }
3624 deliverNewIntentLocked(taskTop, r.intent);
3625 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3626 // In this case we are launching the root activity
3627 // of the task, but with a different intent. We
3628 // should start a new instance on top.
3629 addingToTask = true;
3630 sourceRecord = taskTop;
3631 }
3632 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3633 // In this case an activity is being launched in to an
3634 // existing task, without resetting that task. This
3635 // is typically the situation of launching an activity
3636 // from a notification or shortcut. We want to place
3637 // the new activity on top of the current task.
3638 addingToTask = true;
3639 sourceRecord = taskTop;
3640 } else if (!taskTop.task.rootWasReset) {
3641 // In this case we are launching in to an existing task
3642 // that has not yet been started from its front door.
3643 // The current task has been brought to the front.
3644 // Ideally, we'd probably like to place this new task
3645 // at the bottom of its stack, but that's a little hard
3646 // to do with the current organization of the code so
3647 // for now we'll just drop it.
3648 taskTop.task.setIntent(r.intent, r.info);
3649 }
3650 if (!addingToTask) {
3651 // We didn't do anything... but it was needed (a.k.a., client
3652 // don't use that intent!) And for paranoia, make
3653 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003654 if (doResume) {
3655 resumeTopActivityLocked(null);
3656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003657 return START_TASK_TO_FRONT;
3658 }
3659 }
3660 }
3661 }
3662
3663 //String uri = r.intent.toURI();
3664 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003665 //Slog.i(TAG, "Given intent: " + r.intent);
3666 //Slog.i(TAG, "URI is: " + uri);
3667 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668
3669 if (r.packageName != null) {
3670 // If the activity being launched is the same as the one currently
3671 // at the top, then we need to check if it should only be launched
3672 // once.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003673 ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003674 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003675 if (top.realActivity.equals(r.realActivity)) {
3676 if (top.app != null && top.app.thread != null) {
3677 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3678 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3679 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003680 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003681 // For paranoia, make sure we have correctly
3682 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003683 if (doResume) {
3684 resumeTopActivityLocked(null);
3685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003686 if (onlyIfNeeded) {
3687 // We don't need to start a new activity, and
3688 // the client said not to do anything if that
3689 // is the case, so this is it!
3690 return START_RETURN_INTENT_TO_CALLER;
3691 }
3692 deliverNewIntentLocked(top, r.intent);
3693 return START_DELIVERED_TO_TOP;
3694 }
3695 }
3696 }
3697 }
3698
3699 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003700 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003702 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003703 Activity.RESULT_CANCELED, null);
3704 }
3705 return START_CLASS_NOT_FOUND;
3706 }
3707
3708 boolean newTask = false;
3709
3710 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003711 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3713 // todo: should do better management of integers.
3714 mCurTask++;
3715 if (mCurTask <= 0) {
3716 mCurTask = 1;
3717 }
3718 r.task = new TaskRecord(mCurTask, r.info, intent,
3719 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003720 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 + " in new task " + r.task);
3722 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003723 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003724
3725 } else if (sourceRecord != null) {
3726 if (!addingToTask &&
3727 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3728 // In this case, we are adding the activity to an existing
3729 // task, but the caller has asked to clear that task if the
3730 // activity is already running.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003731 ActivityRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003732 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003733 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003734 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003735 deliverNewIntentLocked(top, r.intent);
3736 // For paranoia, make sure we have correctly
3737 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003738 if (doResume) {
3739 resumeTopActivityLocked(null);
3740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 return START_DELIVERED_TO_TOP;
3742 }
3743 } else if (!addingToTask &&
3744 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3745 // In this case, we are launching an activity in our own task
3746 // that may already be running somewhere in the history, and
3747 // we want to shuffle it to the front of the stack if so.
3748 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3749 if (where >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003750 ActivityRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003751 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003753 if (doResume) {
3754 resumeTopActivityLocked(null);
3755 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003756 return START_DELIVERED_TO_TOP;
3757 }
3758 }
3759 // An existing activity is starting this new activity, so we want
3760 // to keep the new one in the same task as the one that is starting
3761 // it.
3762 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003763 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 + " in existing task " + r.task);
3765
3766 } else {
3767 // This not being started from an existing activity, and not part
3768 // of a new task... just put it in the top task, though these days
3769 // this case should never happen.
3770 final int N = mHistory.size();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003771 ActivityRecord prev =
3772 N > 0 ? (ActivityRecord)mHistory.get(N-1) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 r.task = prev != null
3774 ? prev.task
3775 : new TaskRecord(mCurTask, r.info, intent,
3776 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003777 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 + " in new guessed " + r.task);
3779 }
3780 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003781 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003783 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003784 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003785 return START_SUCCESS;
3786 }
3787
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003788 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003789 long thisTime, long totalTime) {
3790 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3791 WaitResult w = mWaitingActivityLaunched.get(i);
3792 w.timeout = timeout;
3793 if (r != null) {
3794 w.who = new ComponentName(r.info.packageName, r.info.name);
3795 }
3796 w.thisTime = thisTime;
3797 w.totalTime = totalTime;
3798 }
3799 notify();
3800 }
3801
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003802 void reportActivityVisibleLocked(ActivityRecord r) {
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003803 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3804 WaitResult w = mWaitingActivityVisible.get(i);
3805 w.timeout = false;
3806 if (r != null) {
3807 w.who = new ComponentName(r.info.packageName, r.info.name);
3808 }
3809 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3810 w.thisTime = w.totalTime;
3811 }
3812 notify();
3813 }
3814
3815 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3817 int grantedMode, IBinder resultTo,
3818 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003819 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 // Refuse possible leaked file descriptors
3821 if (intent != null && intent.hasFileDescriptors()) {
3822 throw new IllegalArgumentException("File descriptors passed in Intent");
3823 }
3824
Dianne Hackborn860755f2010-06-03 18:47:52 -07003825 boolean componentSpecified = intent.getComponent() != null;
The Android Open Source Project4df24232009-03-05 14:34:35 -08003826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 // Don't modify the client's object!
3828 intent = new Intent(intent);
3829
3830 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 ActivityInfo aInfo;
3832 try {
3833 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003834 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 intent, resolvedType,
3836 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003837 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 aInfo = rInfo != null ? rInfo.activityInfo : null;
3839 } catch (RemoteException e) {
3840 aInfo = null;
3841 }
3842
3843 if (aInfo != null) {
3844 // Store the found target back into the intent, because now that
3845 // we have it we never want to do this again. For example, if the
3846 // user navigates back to this point in the history, we should
3847 // always restart the exact same activity.
3848 intent.setComponent(new ComponentName(
3849 aInfo.applicationInfo.packageName, aInfo.name));
3850
3851 // Don't debug things in the system process
3852 if (debug) {
3853 if (!aInfo.processName.equals("system")) {
3854 setDebugApp(aInfo.processName, true, false);
3855 }
3856 }
3857 }
3858
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003859 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003860 int callingPid;
3861 int callingUid;
3862 if (caller == null) {
3863 callingPid = Binder.getCallingPid();
3864 callingUid = Binder.getCallingUid();
3865 } else {
3866 callingPid = callingUid = -1;
3867 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003868
3869 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003870 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3871 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003873 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003874
Dianne Hackborn860755f2010-06-03 18:47:52 -07003875 if (aInfo != null &&
3876 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
3877 // This may be a heavy-weight process! Check to see if we already
3878 // have another, different heavy-weight process running.
3879 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
3880 if (mHeavyWeightProcess != null &&
3881 (mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
3882 !mHeavyWeightProcess.processName.equals(aInfo.processName))) {
3883 int realCallingPid = callingPid;
3884 int realCallingUid = callingUid;
3885 if (caller != null) {
3886 ProcessRecord callerApp = getRecordForAppLocked(caller);
3887 if (callerApp != null) {
3888 realCallingPid = callerApp.pid;
3889 realCallingUid = callerApp.info.uid;
3890 } else {
3891 Slog.w(TAG, "Unable to find app for caller " + caller
3892 + " (pid=" + realCallingPid + ") when starting: "
3893 + intent.toString());
3894 return START_PERMISSION_DENIED;
3895 }
3896 }
3897
3898 IIntentSender target = getIntentSenderLocked(
3899 IActivityManager.INTENT_SENDER_ACTIVITY, "android",
3900 realCallingUid, null, null, 0, intent,
3901 resolvedType, PendingIntent.FLAG_CANCEL_CURRENT
3902 | PendingIntent.FLAG_ONE_SHOT);
3903
3904 Intent newIntent = new Intent();
3905 if (requestCode >= 0) {
3906 // Caller is requesting a result.
3907 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3908 }
3909 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
3910 new IntentSender(target));
3911 if (mHeavyWeightProcess.activities.size() > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003912 ActivityRecord hist = mHeavyWeightProcess.activities.get(0);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003913 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
3914 hist.packageName);
3915 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3916 hist.task.taskId);
3917 }
3918 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3919 aInfo.packageName);
3920 newIntent.setFlags(intent.getFlags());
3921 newIntent.setClassName("android",
3922 HeavyWeightSwitcherActivity.class.getName());
3923 intent = newIntent;
3924 resolvedType = null;
3925 caller = null;
3926 callingUid = Binder.getCallingUid();
3927 callingPid = Binder.getCallingPid();
3928 componentSpecified = true;
3929 try {
3930 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003931 AppGlobals.getPackageManager().resolveIntent(
Dianne Hackborn860755f2010-06-03 18:47:52 -07003932 intent, null,
3933 PackageManager.MATCH_DEFAULT_ONLY
3934 | STOCK_PM_FLAGS);
3935 aInfo = rInfo != null ? rInfo.activityInfo : null;
3936 } catch (RemoteException e) {
3937 aInfo = null;
3938 }
3939 }
3940 }
3941 }
3942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 int res = startActivityLocked(caller, intent, resolvedType,
3944 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003945 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003946 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003947
Dianne Hackborne2522462010-03-29 18:41:30 -07003948 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003949 // If the caller also wants to switch to a new configuration,
3950 // do so now. This allows a clean switch, as we are waiting
3951 // for the current activity to pause (so we will not destroy
3952 // it), and have not yet started the next activity.
3953 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3954 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003955 mConfigWillChange = false;
3956 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3957 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003958 updateConfigurationLocked(config, null);
3959 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003961 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003962
3963 if (outResult != null) {
3964 outResult.result = res;
3965 if (res == IActivityManager.START_SUCCESS) {
3966 mWaitingActivityLaunched.add(outResult);
3967 do {
3968 try {
3969 wait();
3970 } catch (InterruptedException e) {
3971 }
3972 } while (!outResult.timeout && outResult.who == null);
3973 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003974 ActivityRecord r = this.topRunningActivityLocked(null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003975 if (r.nowVisible) {
3976 outResult.timeout = false;
3977 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3978 outResult.totalTime = 0;
3979 outResult.thisTime = 0;
3980 } else {
3981 outResult.thisTime = SystemClock.uptimeMillis();
3982 mWaitingActivityVisible.add(outResult);
3983 do {
3984 try {
3985 wait();
3986 } catch (InterruptedException e) {
3987 }
3988 } while (!outResult.timeout && outResult.who == null);
3989 }
3990 }
3991 }
3992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 return res;
3994 }
3995 }
3996
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003997 public final int startActivity(IApplicationThread caller,
3998 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3999 int grantedMode, IBinder resultTo,
4000 String resultWho, int requestCode, boolean onlyIfNeeded,
4001 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07004002 return startActivityMayWait(caller, intent, resolvedType,
4003 grantedUriPermissions, grantedMode, resultTo, resultWho,
4004 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08004005 }
4006
4007 public final WaitResult startActivityAndWait(IApplicationThread caller,
4008 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
4009 int grantedMode, IBinder resultTo,
4010 String resultWho, int requestCode, boolean onlyIfNeeded,
4011 boolean debug) {
4012 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07004013 startActivityMayWait(caller, intent, resolvedType,
4014 grantedUriPermissions, grantedMode, resultTo, resultWho,
4015 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08004016 return res;
4017 }
4018
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07004019 public final int startActivityWithConfig(IApplicationThread caller,
4020 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
4021 int grantedMode, IBinder resultTo,
4022 String resultWho, int requestCode, boolean onlyIfNeeded,
4023 boolean debug, Configuration config) {
4024 return startActivityMayWait(caller, intent, resolvedType,
4025 grantedUriPermissions, grantedMode, resultTo, resultWho,
4026 requestCode, onlyIfNeeded, debug, null, config);
4027 }
4028
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08004029 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07004030 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07004031 IBinder resultTo, String resultWho, int requestCode,
4032 int flagsMask, int flagsValues) {
4033 // Refuse possible leaked file descriptors
4034 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
4035 throw new IllegalArgumentException("File descriptors passed in Intent");
4036 }
4037
4038 IIntentSender sender = intent.getTarget();
4039 if (!(sender instanceof PendingIntentRecord)) {
4040 throw new IllegalArgumentException("Bad PendingIntent object");
4041 }
4042
4043 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07004044
4045 synchronized (this) {
4046 // If this is coming from the currently resumed activity, it is
4047 // effectively saying that app switches are allowed at this point.
4048 if (mResumedActivity != null
4049 && mResumedActivity.info.applicationInfo.uid ==
4050 Binder.getCallingUid()) {
4051 mAppSwitchesAllowedTime = 0;
4052 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07004053 }
4054
4055 return pir.sendInner(0, fillInIntent, resolvedType,
4056 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
4057 }
4058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004059 public boolean startNextMatchingActivity(IBinder callingActivity,
4060 Intent intent) {
4061 // Refuse possible leaked file descriptors
4062 if (intent != null && intent.hasFileDescriptors() == true) {
4063 throw new IllegalArgumentException("File descriptors passed in Intent");
4064 }
4065
4066 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004067 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004068 if (index < 0) {
4069 return false;
4070 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004071 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004072 if (r.app == null || r.app.thread == null) {
4073 // The caller is not running... d'oh!
4074 return false;
4075 }
4076 intent = new Intent(intent);
4077 // The caller is not allowed to change the data.
4078 intent.setDataAndType(r.intent.getData(), r.intent.getType());
4079 // And we are resetting to find the next component...
4080 intent.setComponent(null);
4081
4082 ActivityInfo aInfo = null;
4083 try {
4084 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004085 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004086 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004087 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088
4089 // Look for the original activity in the list...
4090 final int N = resolves != null ? resolves.size() : 0;
4091 for (int i=0; i<N; i++) {
4092 ResolveInfo rInfo = resolves.get(i);
4093 if (rInfo.activityInfo.packageName.equals(r.packageName)
4094 && rInfo.activityInfo.name.equals(r.info.name)) {
4095 // We found the current one... the next matching is
4096 // after it.
4097 i++;
4098 if (i<N) {
4099 aInfo = resolves.get(i).activityInfo;
4100 }
4101 break;
4102 }
4103 }
4104 } catch (RemoteException e) {
4105 }
4106
4107 if (aInfo == null) {
4108 // Nobody who is next!
4109 return false;
4110 }
4111
4112 intent.setComponent(new ComponentName(
4113 aInfo.applicationInfo.packageName, aInfo.name));
4114 intent.setFlags(intent.getFlags()&~(
4115 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
4116 Intent.FLAG_ACTIVITY_CLEAR_TOP|
4117 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
4118 Intent.FLAG_ACTIVITY_NEW_TASK));
4119
4120 // Okay now we need to start the new activity, replacing the
4121 // currently running activity. This is a little tricky because
4122 // we want to start the new one as if the current one is finished,
4123 // but not finish the current one first so that there is no flicker.
4124 // And thus...
4125 final boolean wasFinishing = r.finishing;
4126 r.finishing = true;
4127
4128 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004129 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 final String resultWho = r.resultWho;
4131 final int requestCode = r.requestCode;
4132 r.resultTo = null;
4133 if (resultTo != null) {
4134 resultTo.removeResultsLocked(r, resultWho, requestCode);
4135 }
4136
4137 final long origId = Binder.clearCallingIdentity();
4138 // XXX we are not dealing with propagating grantedUriPermissions...
4139 // those are not yet exposed to user code, so there is no need.
4140 int res = startActivityLocked(r.app.thread, intent,
4141 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004142 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004143 Binder.restoreCallingIdentity(origId);
4144
4145 r.finishing = wasFinishing;
4146 if (res != START_SUCCESS) {
4147 return false;
4148 }
4149 return true;
4150 }
4151 }
4152
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004153 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004154 Intent intent, String resolvedType, IBinder resultTo,
4155 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004156
4157 // This is so super not safe, that only the system (or okay root)
4158 // can do it.
4159 final int callingUid = Binder.getCallingUid();
4160 if (callingUid != 0 && callingUid != Process.myUid()) {
4161 throw new SecurityException(
4162 "startActivityInPackage only available to the system");
4163 }
4164
The Android Open Source Project4df24232009-03-05 14:34:35 -08004165 final boolean componentSpecified = intent.getComponent() != null;
4166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004167 // Don't modify the client's object!
4168 intent = new Intent(intent);
4169
4170 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171 ActivityInfo aInfo;
4172 try {
4173 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004174 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004175 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004176 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004177 aInfo = rInfo != null ? rInfo.activityInfo : null;
4178 } catch (RemoteException e) {
4179 aInfo = null;
4180 }
4181
4182 if (aInfo != null) {
4183 // Store the found target back into the intent, because now that
4184 // we have it we never want to do this again. For example, if the
4185 // user navigates back to this point in the history, we should
4186 // always restart the exact same activity.
4187 intent.setComponent(new ComponentName(
4188 aInfo.applicationInfo.packageName, aInfo.name));
4189 }
4190
4191 synchronized(this) {
4192 return startActivityLocked(null, intent, resolvedType,
4193 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004194 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004195 }
4196 }
4197
Josh Bartel7f208742010-02-25 11:01:44 -06004198 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004199 // Remove any existing entries that are the same kind of task.
4200 int N = mRecentTasks.size();
4201 for (int i=0; i<N; i++) {
4202 TaskRecord tr = mRecentTasks.get(i);
4203 if ((task.affinity != null && task.affinity.equals(tr.affinity))
4204 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
4205 mRecentTasks.remove(i);
4206 i--;
4207 N--;
4208 if (task.intent == null) {
4209 // If the new recent task we are adding is not fully
4210 // specified, then replace it with the existing recent task.
4211 task = tr;
4212 }
4213 }
4214 }
4215 if (N >= MAX_RECENT_TASKS) {
4216 mRecentTasks.remove(N-1);
4217 }
4218 mRecentTasks.add(0, task);
4219 }
4220
4221 public void setRequestedOrientation(IBinder token,
4222 int requestedOrientation) {
4223 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004224 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 if (index < 0) {
4226 return;
4227 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004228 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004229 final long origId = Binder.clearCallingIdentity();
4230 mWindowManager.setAppOrientation(r, requestedOrientation);
4231 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07004232 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004233 r.mayFreezeScreenLocked(r.app) ? r : null);
4234 if (config != null) {
4235 r.frozenBeforeDestroy = true;
4236 if (!updateConfigurationLocked(config, r)) {
4237 resumeTopActivityLocked(null);
4238 }
4239 }
4240 Binder.restoreCallingIdentity(origId);
4241 }
4242 }
4243
4244 public int getRequestedOrientation(IBinder token) {
4245 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004246 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004247 if (index < 0) {
4248 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
4249 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004250 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004251 return mWindowManager.getAppOrientation(r);
4252 }
4253 }
4254
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004255 private final void stopActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004256 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004257 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4258 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
4259 if (!r.finishing) {
4260 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
4261 "no-history");
4262 }
4263 } else if (r.app != null && r.app.thread != null) {
4264 if (mFocusedActivity == r) {
4265 setFocusedActivityLocked(topRunningActivityLocked(null));
4266 }
4267 r.resumeKeyDispatchingLocked();
4268 try {
4269 r.stopped = false;
4270 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004271 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 TAG, "Stopping visible=" + r.visible + " for " + r);
4273 if (!r.visible) {
4274 mWindowManager.setAppVisibility(r, false);
4275 }
4276 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4277 } catch (Exception e) {
4278 // Maybe just ignore exceptions here... if the process
4279 // has crashed, our death notification will clean things
4280 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004281 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 // Just in case, assume it to be stopped.
4283 r.stopped = true;
4284 r.state = ActivityState.STOPPED;
4285 if (r.configDestroy) {
4286 destroyActivityLocked(r, true);
4287 }
4288 }
4289 }
4290 }
4291
4292 /**
4293 * @return Returns true if the activity is being finished, false if for
4294 * some reason it is being left as-is.
4295 */
4296 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4297 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004298 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004299 TAG, "Finishing activity: token=" + token
4300 + ", result=" + resultCode + ", data=" + resultData);
4301
Dianne Hackborn75b03852009-06-12 15:43:26 -07004302 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004303 if (index < 0) {
4304 return false;
4305 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004306 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307
4308 // Is this the last activity left?
4309 boolean lastActivity = true;
4310 for (int i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004311 ActivityRecord p = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004312 if (!p.finishing && p != r) {
4313 lastActivity = false;
4314 break;
4315 }
4316 }
4317
4318 // If this is the last activity, but it is the home activity, then
4319 // just don't finish it.
4320 if (lastActivity) {
4321 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4322 return false;
4323 }
4324 }
4325
4326 finishActivityLocked(r, index, resultCode, resultData, reason);
4327 return true;
4328 }
4329
4330 /**
4331 * @return Returns true if this activity has been removed from the history
4332 * list, or false if it is still in the list and will be removed later.
4333 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004334 private final boolean finishActivityLocked(ActivityRecord r, int index,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004335 int resultCode, Intent resultData, String reason) {
4336 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004337 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338 return false;
4339 }
4340
4341 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004342 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004343 System.identityHashCode(r),
4344 r.task.taskId, r.shortComponentName, reason);
4345 r.task.numActivities--;
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004346 if (index < (mHistory.size()-1)) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004347 ActivityRecord next = (ActivityRecord)mHistory.get(index+1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 if (next.task == r.task) {
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004349 if (r.frontOfTask) {
4350 // The next activity is now the front of the task.
4351 next.frontOfTask = true;
4352 }
4353 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4354 // If the caller asked that this activity (and all above it)
4355 // be cleared when the task is reset, don't lose that information,
4356 // but propagate it up to the next activity.
4357 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004359 }
4360 }
4361
4362 r.pauseKeyDispatchingLocked();
4363 if (mFocusedActivity == r) {
4364 setFocusedActivityLocked(topRunningActivityLocked(null));
4365 }
4366
4367 // send the result
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004368 ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004370 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004371 + " who=" + r.resultWho + " req=" + r.requestCode
4372 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 if (r.info.applicationInfo.uid > 0) {
4374 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4375 r.packageName, resultData, r);
4376 }
4377 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4378 resultData);
4379 r.resultTo = null;
4380 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004381 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004382
4383 // Make sure this HistoryRecord is not holding on to other resources,
4384 // because clients have remote IPC references to this object so we
4385 // can't assume that will go away and want to avoid circular IPC refs.
4386 r.results = null;
4387 r.pendingResults = null;
4388 r.newIntents = null;
4389 r.icicle = null;
4390
4391 if (mPendingThumbnails.size() > 0) {
4392 // There are clients waiting to receive thumbnails so, in case
4393 // this is an activity that someone is waiting for, add it
4394 // to the pending list so we can correctly update the clients.
4395 mCancelledThumbnails.add(r);
4396 }
4397
4398 if (mResumedActivity == r) {
4399 boolean endTask = index <= 0
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004400 || ((ActivityRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004401 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004402 "Prepare close transition: finishing " + r);
4403 mWindowManager.prepareAppTransition(endTask
4404 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4405 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4406
4407 // Tell window manager to prepare for this one to be removed.
4408 mWindowManager.setAppVisibility(r, false);
4409
4410 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004411 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4412 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 startPausingLocked(false, false);
4414 }
4415
4416 } else if (r.state != ActivityState.PAUSING) {
4417 // If the activity is PAUSING, we will complete the finish once
4418 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004419 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004420 return finishCurrentActivityLocked(r, index,
4421 FINISH_AFTER_PAUSE) == null;
4422 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004423 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 }
4425
4426 return false;
4427 }
4428
4429 private static final int FINISH_IMMEDIATELY = 0;
4430 private static final int FINISH_AFTER_PAUSE = 1;
4431 private static final int FINISH_AFTER_VISIBLE = 2;
4432
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004433 private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004434 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004435 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 if (index < 0) {
4437 return null;
4438 }
4439
4440 return finishCurrentActivityLocked(r, index, mode);
4441 }
4442
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004443 private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 int index, int mode) {
4445 // First things first: if this activity is currently visible,
4446 // and the resumed activity is not yet visible, then hold off on
4447 // finishing until the resumed one becomes visible.
4448 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4449 if (!mStoppingActivities.contains(r)) {
4450 mStoppingActivities.add(r);
4451 if (mStoppingActivities.size() > 3) {
4452 // If we already have a few activities waiting to stop,
4453 // then give up on things going idle and start clearing
4454 // them out.
4455 Message msg = Message.obtain();
4456 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4457 mHandler.sendMessage(msg);
4458 }
4459 }
4460 r.state = ActivityState.STOPPING;
4461 updateOomAdjLocked();
4462 return r;
4463 }
4464
4465 // make sure the record is cleaned out of other places.
4466 mStoppingActivities.remove(r);
4467 mWaitingVisibleActivities.remove(r);
4468 if (mResumedActivity == r) {
4469 mResumedActivity = null;
4470 }
4471 final ActivityState prevState = r.state;
4472 r.state = ActivityState.FINISHING;
4473
4474 if (mode == FINISH_IMMEDIATELY
4475 || prevState == ActivityState.STOPPED
4476 || prevState == ActivityState.INITIALIZING) {
4477 // If this activity is already stopped, we can just finish
4478 // it right now.
4479 return destroyActivityLocked(r, true) ? null : r;
4480 } else {
4481 // Need to go through the full pause cycle to get this
4482 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004483 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 mFinishingActivities.add(r);
4485 resumeTopActivityLocked(null);
4486 }
4487 return r;
4488 }
4489
4490 /**
4491 * This is the internal entry point for handling Activity.finish().
4492 *
4493 * @param token The Binder token referencing the Activity we want to finish.
4494 * @param resultCode Result code, if any, from this Activity.
4495 * @param resultData Result data (Intent), if any, from this Activity.
4496 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004497 * @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 -08004498 */
4499 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4500 // Refuse possible leaked file descriptors
4501 if (resultData != null && resultData.hasFileDescriptors() == true) {
4502 throw new IllegalArgumentException("File descriptors passed in Intent");
4503 }
4504
4505 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004506 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004507 // Find the first activity that is not finishing.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004508 ActivityRecord next = topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004509 if (next != null) {
4510 // ask watcher if this is allowed
4511 boolean resumeOK = true;
4512 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004513 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004514 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004515 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 }
4517
4518 if (!resumeOK) {
4519 return false;
4520 }
4521 }
4522 }
4523 final long origId = Binder.clearCallingIdentity();
4524 boolean res = requestFinishActivityLocked(token, resultCode,
4525 resultData, "app-request");
4526 Binder.restoreCallingIdentity(origId);
4527 return res;
4528 }
4529 }
4530
Dianne Hackborn860755f2010-06-03 18:47:52 -07004531 public final void finishHeavyWeightApp() {
4532 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4533 != PackageManager.PERMISSION_GRANTED) {
4534 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
4535 + Binder.getCallingPid()
4536 + ", uid=" + Binder.getCallingUid()
4537 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4538 Slog.w(TAG, msg);
4539 throw new SecurityException(msg);
4540 }
4541
4542 synchronized(this) {
4543 if (mHeavyWeightProcess == null) {
4544 return;
4545 }
4546
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004547 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07004548 mHeavyWeightProcess.activities);
4549 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004550 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004551 if (!r.finishing) {
4552 int index = indexOfTokenLocked(r);
4553 if (index >= 0) {
4554 finishActivityLocked(r, index, Activity.RESULT_CANCELED,
4555 null, "finish-heavy");
4556 }
4557 }
4558 }
4559
4560 mHeavyWeightProcess = null;
4561 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4562 }
4563 }
4564
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07004565 public void crashApplication(int uid, int initialPid, String packageName,
4566 String message) {
4567 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4568 != PackageManager.PERMISSION_GRANTED) {
4569 String msg = "Permission Denial: crashApplication() from pid="
4570 + Binder.getCallingPid()
4571 + ", uid=" + Binder.getCallingUid()
4572 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4573 Slog.w(TAG, msg);
4574 throw new SecurityException(msg);
4575 }
4576
4577 synchronized(this) {
4578 ProcessRecord proc = null;
4579
4580 // Figure out which process to kill. We don't trust that initialPid
4581 // still has any relation to current pids, so must scan through the
4582 // list.
4583 synchronized (mPidsSelfLocked) {
4584 for (int i=0; i<mPidsSelfLocked.size(); i++) {
4585 ProcessRecord p = mPidsSelfLocked.valueAt(i);
4586 if (p.info.uid != uid) {
4587 continue;
4588 }
4589 if (p.pid == initialPid) {
4590 proc = p;
4591 break;
4592 }
4593 for (String str : p.pkgList) {
4594 if (str.equals(packageName)) {
4595 proc = p;
4596 }
4597 }
4598 }
4599 }
4600
4601 if (proc == null) {
4602 Log.w(TAG, "crashApplication: nothing for uid=" + uid
4603 + " initialPid=" + initialPid
4604 + " packageName=" + packageName);
4605 return;
4606 }
4607
4608 if (proc.thread != null) {
4609 long ident = Binder.clearCallingIdentity();
4610 try {
4611 proc.thread.scheduleCrash(message);
4612 } catch (RemoteException e) {
4613 }
4614 Binder.restoreCallingIdentity(ident);
4615 }
4616 }
4617 }
4618
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004619 void sendActivityResultLocked(int callingUid, ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004620 String resultWho, int requestCode, int resultCode, Intent data) {
4621
4622 if (callingUid > 0) {
4623 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4624 data, r);
4625 }
4626
Joe Onorato8a9b2202010-02-26 18:56:32 -08004627 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004628 + " : who=" + resultWho + " req=" + requestCode
4629 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4631 try {
4632 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4633 list.add(new ResultInfo(resultWho, requestCode,
4634 resultCode, data));
4635 r.app.thread.scheduleSendResult(r, list);
4636 return;
4637 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004638 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004639 }
4640 }
4641
4642 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4643 }
4644
4645 public final void finishSubActivity(IBinder token, String resultWho,
4646 int requestCode) {
4647 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004648 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004649 if (index < 0) {
4650 return;
4651 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004652 ActivityRecord self = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653
4654 final long origId = Binder.clearCallingIdentity();
4655
4656 int i;
4657 for (i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004658 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 if (r.resultTo == self && r.requestCode == requestCode) {
4660 if ((r.resultWho == null && resultWho == null) ||
4661 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4662 finishActivityLocked(r, i,
4663 Activity.RESULT_CANCELED, null, "request-sub");
4664 }
4665 }
4666 }
4667
4668 Binder.restoreCallingIdentity(origId);
4669 }
4670 }
4671
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004672 public boolean willActivityBeVisible(IBinder token) {
4673 synchronized(this) {
4674 int i;
4675 for (i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004676 ActivityRecord r = (ActivityRecord)mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004677 if (r == token) {
4678 return true;
4679 }
4680 if (r.fullscreen && !r.finishing) {
4681 return false;
4682 }
4683 }
4684 return true;
4685 }
4686 }
4687
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004688 public void overridePendingTransition(IBinder token, String packageName,
4689 int enterAnim, int exitAnim) {
4690 synchronized(this) {
4691 int index = indexOfTokenLocked(token);
4692 if (index < 0) {
4693 return;
4694 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004695 ActivityRecord self = (ActivityRecord)mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004696
4697 final long origId = Binder.clearCallingIdentity();
4698
4699 if (self.state == ActivityState.RESUMED
4700 || self.state == ActivityState.PAUSING) {
4701 mWindowManager.overridePendingAppTransition(packageName,
4702 enterAnim, exitAnim);
4703 }
4704
4705 Binder.restoreCallingIdentity(origId);
4706 }
4707 }
4708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004709 /**
4710 * Perform clean-up of service connections in an activity record.
4711 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004712 private final void cleanUpActivityServicesLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004713 // Throw away any services that have been bound by this activity.
4714 if (r.connections != null) {
4715 Iterator<ConnectionRecord> it = r.connections.iterator();
4716 while (it.hasNext()) {
4717 ConnectionRecord c = it.next();
4718 removeConnectionLocked(c, null, r);
4719 }
4720 r.connections = null;
4721 }
4722 }
4723
4724 /**
4725 * Perform the common clean-up of an activity record. This is called both
4726 * as part of destroyActivityLocked() (when destroying the client-side
4727 * representation) and cleaning things up as a result of its hosting
4728 * processing going away, in which case there is no remaining client-side
4729 * state to destroy so only the cleanup here is needed.
4730 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004731 private final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 if (mResumedActivity == r) {
4733 mResumedActivity = null;
4734 }
4735 if (mFocusedActivity == r) {
4736 mFocusedActivity = null;
4737 }
4738
4739 r.configDestroy = false;
4740 r.frozenBeforeDestroy = false;
4741
4742 // Make sure this record is no longer in the pending finishes list.
4743 // This could happen, for example, if we are trimming activities
4744 // down to the max limit while they are still waiting to finish.
4745 mFinishingActivities.remove(r);
4746 mWaitingVisibleActivities.remove(r);
4747
4748 // Remove any pending results.
4749 if (r.finishing && r.pendingResults != null) {
4750 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4751 PendingIntentRecord rec = apr.get();
4752 if (rec != null) {
4753 cancelIntentSenderLocked(rec, false);
4754 }
4755 }
4756 r.pendingResults = null;
4757 }
4758
4759 if (cleanServices) {
4760 cleanUpActivityServicesLocked(r);
4761 }
4762
4763 if (mPendingThumbnails.size() > 0) {
4764 // There are clients waiting to receive thumbnails so, in case
4765 // this is an activity that someone is waiting for, add it
4766 // to the pending list so we can correctly update the clients.
4767 mCancelledThumbnails.add(r);
4768 }
4769
4770 // Get rid of any pending idle timeouts.
4771 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4772 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4773 }
4774
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004775 private final void removeActivityFromHistoryLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004776 if (r.state != ActivityState.DESTROYED) {
4777 mHistory.remove(r);
4778 r.inHistory = false;
4779 r.state = ActivityState.DESTROYED;
4780 mWindowManager.removeAppToken(r);
4781 if (VALIDATE_TOKENS) {
4782 mWindowManager.validateAppTokens(mHistory);
4783 }
4784 cleanUpActivityServicesLocked(r);
4785 removeActivityUriPermissionsLocked(r);
4786 }
4787 }
4788
4789 /**
4790 * Destroy the current CLIENT SIDE instance of an activity. This may be
4791 * called both when actually finishing an activity, or when performing
4792 * a configuration switch where we destroy the current client-side object
4793 * but then create a new client-side object for this same HistoryRecord.
4794 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004795 private final boolean destroyActivityLocked(ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004797 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004798 TAG, "Removing activity: token=" + r
4799 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004800 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004801 System.identityHashCode(r),
4802 r.task.taskId, r.shortComponentName);
4803
4804 boolean removedFromHistory = false;
4805
4806 cleanUpActivityLocked(r, false);
4807
Dianne Hackborn03abb812010-01-04 18:43:19 -08004808 final boolean hadApp = r.app != null;
4809
4810 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004811 if (removeFromApp) {
4812 int idx = r.app.activities.indexOf(r);
4813 if (idx >= 0) {
4814 r.app.activities.remove(idx);
4815 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004816 if (mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4817 mHeavyWeightProcess = null;
4818 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004820 if (r.persistent) {
4821 decPersistentCountLocked(r.app);
4822 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004823 if (r.app.activities.size() == 0) {
4824 // No longer have activities, so update location in
4825 // LRU list.
4826 updateLruProcessLocked(r.app, true, false);
4827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004828 }
4829
4830 boolean skipDestroy = false;
4831
4832 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004833 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004834 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4835 r.configChangeFlags);
4836 } catch (Exception e) {
4837 // We can just ignore exceptions here... if the process
4838 // has crashed, our death notification will clean things
4839 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004840 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 if (r.finishing) {
4842 removeActivityFromHistoryLocked(r);
4843 removedFromHistory = true;
4844 skipDestroy = true;
4845 }
4846 }
4847
4848 r.app = null;
4849 r.nowVisible = false;
4850
4851 if (r.finishing && !skipDestroy) {
4852 r.state = ActivityState.DESTROYING;
4853 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4854 msg.obj = r;
4855 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4856 } else {
4857 r.state = ActivityState.DESTROYED;
4858 }
4859 } else {
4860 // remove this record from the history.
4861 if (r.finishing) {
4862 removeActivityFromHistoryLocked(r);
4863 removedFromHistory = true;
4864 } else {
4865 r.state = ActivityState.DESTROYED;
4866 }
4867 }
4868
4869 r.configChangeFlags = 0;
4870
Dianne Hackborn03abb812010-01-04 18:43:19 -08004871 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004872 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004873 }
4874
4875 return removedFromHistory;
4876 }
4877
Dianne Hackborn03abb812010-01-04 18:43:19 -08004878 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004880 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 TAG, "Removing app " + app + " from list " + list
4882 + " with " + i + " entries");
4883 while (i > 0) {
4884 i--;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004885 ActivityRecord r = (ActivityRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004886 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004887 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4888 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004889 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004890 list.remove(i);
4891 }
4892 }
4893 }
4894
4895 /**
4896 * Main function for removing an existing process from the activity manager
4897 * as a result of that process going away. Clears out all connections
4898 * to the process.
4899 */
4900 private final void handleAppDiedLocked(ProcessRecord app,
4901 boolean restarting) {
4902 cleanUpApplicationRecordLocked(app, restarting, -1);
4903 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004904 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004905 }
4906
4907 // Just in case...
4908 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004909 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004910 mPausingActivity = null;
4911 }
4912 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4913 mLastPausedActivity = null;
4914 }
4915
4916 // Remove this application's activities from active lists.
4917 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4918 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4919 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4920 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4921
4922 boolean atTop = true;
4923 boolean hasVisibleActivities = false;
4924
4925 // Clean out the history list.
4926 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004927 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928 TAG, "Removing app " + app + " from history with " + i + " entries");
4929 while (i > 0) {
4930 i--;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004931 ActivityRecord r = (ActivityRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004932 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4934 if (r.app == app) {
4935 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004936 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 TAG, "Removing this entry! frozen=" + r.haveState
4938 + " finishing=" + r.finishing);
4939 mHistory.remove(i);
4940
4941 r.inHistory = false;
4942 mWindowManager.removeAppToken(r);
4943 if (VALIDATE_TOKENS) {
4944 mWindowManager.validateAppTokens(mHistory);
4945 }
4946 removeActivityUriPermissionsLocked(r);
4947
4948 } else {
4949 // We have the current state for this activity, so
4950 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004951 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 TAG, "Keeping entry, setting app to null");
4953 if (r.visible) {
4954 hasVisibleActivities = true;
4955 }
4956 r.app = null;
4957 r.nowVisible = false;
4958 if (!r.haveState) {
4959 r.icicle = null;
4960 }
4961 }
4962
4963 cleanUpActivityLocked(r, true);
4964 r.state = ActivityState.STOPPED;
4965 }
4966 atTop = false;
4967 }
4968
4969 app.activities.clear();
4970
4971 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004972 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004973 + " running instrumentation " + app.instrumentationClass);
4974 Bundle info = new Bundle();
4975 info.putString("shortMsg", "Process crashed.");
4976 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4977 }
4978
4979 if (!restarting) {
4980 if (!resumeTopActivityLocked(null)) {
4981 // If there was nothing to resume, and we are not already
4982 // restarting this process, but there is a visible activity that
4983 // is hosted by the process... then make sure all visible
4984 // activities are running, taking care of restarting this
4985 // process.
4986 if (hasVisibleActivities) {
4987 ensureActivitiesVisibleLocked(null, 0);
4988 }
4989 }
4990 }
4991 }
4992
4993 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4994 IBinder threadBinder = thread.asBinder();
4995
4996 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004997 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4998 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
5000 return i;
5001 }
5002 }
5003 return -1;
5004 }
5005
5006 private final ProcessRecord getRecordForAppLocked(
5007 IApplicationThread thread) {
5008 if (thread == null) {
5009 return null;
5010 }
5011
5012 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005013 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 }
5015
5016 private final void appDiedLocked(ProcessRecord app, int pid,
5017 IApplicationThread thread) {
5018
5019 mProcDeaths[0]++;
5020
Magnus Edlund7bb25812010-02-24 15:45:06 +01005021 // Clean up already done if the process has been re-started.
5022 if (app.pid == pid && app.thread != null &&
5023 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07005024 if (!app.killedBackground) {
5025 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
5026 + ") has died.");
5027 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08005028 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005029 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 TAG, "Dying app: " + app + ", pid: " + pid
5031 + ", thread: " + thread.asBinder());
5032 boolean doLowMem = app.instrumentationClass == null;
5033 handleAppDiedLocked(app, false);
5034
5035 if (doLowMem) {
5036 // If there are no longer any background processes running,
5037 // and the app that died was not running instrumentation,
5038 // then tell everyone we are now low on memory.
5039 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005040 for (int i=mLruProcesses.size()-1; i>=0; i--) {
5041 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005042 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
5043 haveBg = true;
5044 break;
5045 }
5046 }
5047
5048 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005049 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005050 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005051 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005052 for (int i=mLruProcesses.size()-1; i>=0; i--) {
5053 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07005054 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005055 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
5056 // The low memory report is overriding any current
5057 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005058 // heavy/important/visible/foreground processes first.
5059 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005060 rec.lastRequestedGc = 0;
5061 } else {
5062 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005064 rec.reportLowMemory = true;
5065 rec.lastLowMemory = now;
5066 mProcessesToGc.remove(rec);
5067 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005068 }
5069 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005070 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 }
5072 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01005073 } else if (app.pid != pid) {
5074 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005075 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01005076 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08005077 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005078 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005079 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005080 + thread.asBinder());
5081 }
5082 }
5083
Dan Egnor42471dd2010-01-07 17:25:22 -08005084 /**
5085 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07005086 * @param clearTraces causes the dump file to be erased prior to the new
5087 * traces being written, if true; when false, the new traces will be
5088 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08005089 * @param pids of dalvik VM processes to dump stack traces for
5090 * @return file containing stack traces, or null if no dump file is configured
5091 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07005092 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005093 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
5094 if (tracesPath == null || tracesPath.length() == 0) {
5095 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005096 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005097
5098 File tracesFile = new File(tracesPath);
5099 try {
5100 File tracesDir = tracesFile.getParentFile();
5101 if (!tracesDir.exists()) tracesFile.mkdirs();
5102 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
5103
Christopher Tate6ee412d2010-05-28 12:01:56 -07005104 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08005105 tracesFile.createNewFile();
5106 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
5107 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005108 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005109 return null;
5110 }
5111
5112 // Use a FileObserver to detect when traces finish writing.
5113 // The order of traces is considered important to maintain for legibility.
5114 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
5115 public synchronized void onEvent(int event, String path) { notify(); }
5116 };
5117
5118 try {
5119 observer.startWatching();
5120 int num = pids.size();
5121 for (int i = 0; i < num; i++) {
5122 synchronized (observer) {
5123 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
5124 observer.wait(200); // Wait for write-close, give up after 200msec
5125 }
5126 }
5127 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08005128 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005129 } finally {
5130 observer.stopWatching();
5131 }
5132
5133 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134 }
5135
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005136 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
5137 ActivityRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005138 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005139
5140 synchronized (this) {
5141 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
5142 if (mShuttingDown) {
5143 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
5144 return;
5145 } else if (app.notResponding) {
5146 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
5147 return;
5148 } else if (app.crashing) {
5149 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
5150 return;
5151 }
5152
5153 // In case we come through here for the same app before completing
5154 // this one, mark as anring now so we will bail out.
5155 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08005156
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005157 // Log the ANR to the event log.
5158 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
5159 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08005160
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005161 // Dump thread traces as quickly as we can, starting with "interesting" processes.
5162 pids.add(app.pid);
5163
5164 int parentPid = app.pid;
5165 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
5166 if (parentPid != app.pid) pids.add(parentPid);
5167
5168 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08005169
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005170 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
5171 ProcessRecord r = mLruProcesses.get(i);
5172 if (r != null && r.thread != null) {
5173 int pid = r.pid;
5174 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
5175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005176 }
5177 }
5178
Christopher Tate6ee412d2010-05-28 12:01:56 -07005179 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08005180
5181 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005182 StringBuilder info = mStringBuilder;
5183 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08005184 info.append("ANR in ").append(app.processName);
5185 if (activity != null && activity.shortComponentName != null) {
5186 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07005187 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08005188 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005189 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005190 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005192 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005193 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195
Dan Egnor42471dd2010-01-07 17:25:22 -08005196 String cpuInfo = null;
5197 if (MONITOR_CPU_USAGE) {
5198 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005199 synchronized (mProcessStatsThread) {
5200 cpuInfo = mProcessStats.printCurrentState();
5201 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005202 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203 }
5204
Joe Onorato8a9b2202010-02-26 18:56:32 -08005205 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08005206 if (tracesFile == null) {
5207 // There is no trace file, so dump (only) the alleged culprit's threads to the log
5208 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
5209 }
5210
5211 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
5212
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005213 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005214 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08005215 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
5216 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005217 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005218 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
5219 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 }
5221 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005222 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223 }
5224 }
5225
Dan Egnor42471dd2010-01-07 17:25:22 -08005226 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
5227 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
5228 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005229
5230 synchronized (this) {
5231 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
5232 Process.killProcess(app.pid);
5233 return;
5234 }
5235
5236 // Set the app's notResponding state, and look up the errorReportReceiver
5237 makeAppNotRespondingLocked(app,
5238 activity != null ? activity.shortComponentName : null,
5239 annotation != null ? "ANR " + annotation : "ANR",
5240 info.toString());
5241
5242 // Bring up the infamous App Not Responding dialog
5243 Message msg = Message.obtain();
5244 HashMap map = new HashMap();
5245 msg.what = SHOW_NOT_RESPONDING_MSG;
5246 msg.obj = map;
5247 map.put("app", app);
5248 if (activity != null) {
5249 map.put("activity", activity);
5250 }
5251
5252 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08005253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 }
5255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 private final void decPersistentCountLocked(ProcessRecord app)
5257 {
5258 app.persistentActivities--;
5259 if (app.persistentActivities > 0) {
5260 // Still more of 'em...
5261 return;
5262 }
5263 if (app.persistent) {
5264 // Ah, but the application itself is persistent. Whatever!
5265 return;
5266 }
5267
5268 // App is no longer persistent... make sure it and the ones
5269 // following it in the LRU list have the correc oom_adj.
5270 updateOomAdjLocked();
5271 }
5272
5273 public void setPersistent(IBinder token, boolean isPersistent) {
5274 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
5275 != PackageManager.PERMISSION_GRANTED) {
5276 String msg = "Permission Denial: setPersistent() from pid="
5277 + Binder.getCallingPid()
5278 + ", uid=" + Binder.getCallingUid()
5279 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005280 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005281 throw new SecurityException(msg);
5282 }
5283
5284 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005285 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005286 if (index < 0) {
5287 return;
5288 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005289 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005290 ProcessRecord app = r.app;
5291
Joe Onorato8a9b2202010-02-26 18:56:32 -08005292 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005293 TAG, "Setting persistence " + isPersistent + ": " + r);
5294
5295 if (isPersistent) {
5296 if (r.persistent) {
5297 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005298 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 return;
5300 }
5301 r.persistent = true;
5302 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005303 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 if (app.persistentActivities > 1) {
5305 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005306 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 return;
5308 }
5309 if (app.persistent) {
5310 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005311 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 return;
5313 }
5314
5315 // App is now persistent... make sure it and the ones
5316 // following it now have the correct oom_adj.
5317 final long origId = Binder.clearCallingIdentity();
5318 updateOomAdjLocked();
5319 Binder.restoreCallingIdentity(origId);
5320
5321 } else {
5322 if (!r.persistent) {
5323 // Okay okay, I heard you already!
5324 return;
5325 }
5326 r.persistent = false;
5327 final long origId = Binder.clearCallingIdentity();
5328 decPersistentCountLocked(app);
5329 Binder.restoreCallingIdentity(origId);
5330
5331 }
5332 }
5333 }
5334
5335 public boolean clearApplicationUserData(final String packageName,
5336 final IPackageDataObserver observer) {
5337 int uid = Binder.getCallingUid();
5338 int pid = Binder.getCallingPid();
5339 long callingId = Binder.clearCallingIdentity();
5340 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005341 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 int pkgUid = -1;
5343 synchronized(this) {
5344 try {
5345 pkgUid = pm.getPackageUid(packageName);
5346 } catch (RemoteException e) {
5347 }
5348 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005349 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005350 return false;
5351 }
5352 if (uid == pkgUid || checkComponentPermission(
5353 android.Manifest.permission.CLEAR_APP_USER_DATA,
5354 pid, uid, -1)
5355 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005356 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 } else {
5358 throw new SecurityException(pid+" does not have permission:"+
5359 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5360 "for process:"+packageName);
5361 }
5362 }
5363
5364 try {
5365 //clear application user data
5366 pm.clearApplicationUserData(packageName, observer);
5367 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5368 Uri.fromParts("package", packageName, null));
5369 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005370 synchronized (this) {
5371 broadcastIntentLocked(null, null, intent,
5372 null, null, 0, null, null, null,
5373 false, false, MY_PID, Process.SYSTEM_UID);
5374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 } catch (RemoteException e) {
5376 }
5377 } finally {
5378 Binder.restoreCallingIdentity(callingId);
5379 }
5380 return true;
5381 }
5382
Dianne Hackborn03abb812010-01-04 18:43:19 -08005383 public void killBackgroundProcesses(final String packageName) {
5384 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5385 != PackageManager.PERMISSION_GRANTED &&
5386 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5387 != PackageManager.PERMISSION_GRANTED) {
5388 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005389 + Binder.getCallingPid()
5390 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005391 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005392 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005393 throw new SecurityException(msg);
5394 }
5395
5396 long callingId = Binder.clearCallingIdentity();
5397 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005398 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005399 int pkgUid = -1;
5400 synchronized(this) {
5401 try {
5402 pkgUid = pm.getPackageUid(packageName);
5403 } catch (RemoteException e) {
5404 }
5405 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005406 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005407 return;
5408 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005409 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005410 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005411 }
5412 } finally {
5413 Binder.restoreCallingIdentity(callingId);
5414 }
5415 }
5416
5417 public void forceStopPackage(final String packageName) {
5418 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5419 != PackageManager.PERMISSION_GRANTED) {
5420 String msg = "Permission Denial: forceStopPackage() from pid="
5421 + Binder.getCallingPid()
5422 + ", uid=" + Binder.getCallingUid()
5423 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005424 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005425 throw new SecurityException(msg);
5426 }
5427
5428 long callingId = Binder.clearCallingIdentity();
5429 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005430 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08005431 int pkgUid = -1;
5432 synchronized(this) {
5433 try {
5434 pkgUid = pm.getPackageUid(packageName);
5435 } catch (RemoteException e) {
5436 }
5437 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005438 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005439 return;
5440 }
5441 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005442 }
5443 } finally {
5444 Binder.restoreCallingIdentity(callingId);
5445 }
5446 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005447
5448 /*
5449 * The pkg name and uid have to be specified.
5450 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5451 */
5452 public void killApplicationWithUid(String pkg, int uid) {
5453 if (pkg == null) {
5454 return;
5455 }
5456 // Make sure the uid is valid.
5457 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005458 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005459 return;
5460 }
5461 int callerUid = Binder.getCallingUid();
5462 // Only the system server can kill an application
5463 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005464 // Post an aysnc message to kill the application
5465 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5466 msg.arg1 = uid;
5467 msg.arg2 = 0;
5468 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005469 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005470 } else {
5471 throw new SecurityException(callerUid + " cannot kill pkg: " +
5472 pkg);
5473 }
5474 }
5475
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005476 public void closeSystemDialogs(String reason) {
5477 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5478 if (reason != null) {
5479 intent.putExtra("reason", reason);
5480 }
5481
5482 final int uid = Binder.getCallingUid();
5483 final long origId = Binder.clearCallingIdentity();
5484 synchronized (this) {
5485 int i = mWatchers.beginBroadcast();
5486 while (i > 0) {
5487 i--;
5488 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5489 if (w != null) {
5490 try {
5491 w.closingSystemDialogs(reason);
5492 } catch (RemoteException e) {
5493 }
5494 }
5495 }
5496 mWatchers.finishBroadcast();
5497
Dianne Hackbornffa42482009-09-23 22:20:11 -07005498 mWindowManager.closeSystemDialogs(reason);
5499
5500 for (i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005501 ActivityRecord r = (ActivityRecord)mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07005502 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5503 finishActivityLocked(r, i,
5504 Activity.RESULT_CANCELED, null, "close-sys");
5505 }
5506 }
5507
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005508 broadcastIntentLocked(null, null, intent, null,
5509 null, 0, null, null, null, false, false, -1, uid);
5510 }
5511 Binder.restoreCallingIdentity(origId);
5512 }
5513
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005514 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005515 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005516 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5517 for (int i=pids.length-1; i>=0; i--) {
5518 infos[i] = new Debug.MemoryInfo();
5519 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005520 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005521 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005522 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005523
5524 public void killApplicationProcess(String processName, int uid) {
5525 if (processName == null) {
5526 return;
5527 }
5528
5529 int callerUid = Binder.getCallingUid();
5530 // Only the system server can kill an application
5531 if (callerUid == Process.SYSTEM_UID) {
5532 synchronized (this) {
5533 ProcessRecord app = getProcessRecordLocked(processName, uid);
5534 if (app != null) {
5535 try {
5536 app.thread.scheduleSuicide();
5537 } catch (RemoteException e) {
5538 // If the other end already died, then our work here is done.
5539 }
5540 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005541 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005542 + processName + " / " + uid);
5543 }
5544 }
5545 } else {
5546 throw new SecurityException(callerUid + " cannot kill app process: " +
5547 processName);
5548 }
5549 }
5550
Dianne Hackborn03abb812010-01-04 18:43:19 -08005551 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005552 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005553 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5554 Uri.fromParts("package", packageName, null));
5555 intent.putExtra(Intent.EXTRA_UID, uid);
5556 broadcastIntentLocked(null, null, intent,
5557 null, null, 0, null, null, null,
5558 false, false, MY_PID, Process.SYSTEM_UID);
5559 }
5560
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005561 private final boolean killPackageProcessesLocked(String packageName, int uid,
5562 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005563 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005564
Dianne Hackborn03abb812010-01-04 18:43:19 -08005565 // Remove all processes this package may have touched: all with the
5566 // same UID (except for the system or root user), and all whose name
5567 // matches the package name.
5568 final String procNamePrefix = packageName + ":";
5569 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5570 final int NA = apps.size();
5571 for (int ia=0; ia<NA; ia++) {
5572 ProcessRecord app = apps.valueAt(ia);
5573 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005574 if (doit) {
5575 procs.add(app);
5576 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005577 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5578 || app.processName.equals(packageName)
5579 || app.processName.startsWith(procNamePrefix)) {
5580 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005581 if (!doit) {
5582 return true;
5583 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005584 app.removed = true;
5585 procs.add(app);
5586 }
5587 }
5588 }
5589 }
5590
5591 int N = procs.size();
5592 for (int i=0; i<N; i++) {
5593 removeProcessLocked(procs.get(i), callerWillRestart);
5594 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005595 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005596 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005597
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005598 private final boolean forceStopPackageLocked(String name, int uid,
5599 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005600 int i, N;
5601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005602 if (uid < 0) {
5603 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005604 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005605 } catch (RemoteException e) {
5606 }
5607 }
5608
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005609 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005610 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005611
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005612 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5613 while (badApps.hasNext()) {
5614 SparseArray<Long> ba = badApps.next();
5615 if (ba.get(uid) != null) {
5616 badApps.remove();
5617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005618 }
5619 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005620
5621 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5622 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623
5624 for (i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005625 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005626 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005627 if (!doit) {
5628 return true;
5629 }
5630 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005631 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005632 if (r.app != null) {
5633 r.app.removed = true;
5634 }
5635 r.app = null;
5636 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5637 }
5638 }
5639
5640 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5641 for (ServiceRecord service : mServices.values()) {
5642 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005643 if (!doit) {
5644 return true;
5645 }
5646 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005647 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005648 if (service.app != null) {
5649 service.app.removed = true;
5650 }
5651 service.app = null;
5652 services.add(service);
5653 }
5654 }
5655
5656 N = services.size();
5657 for (i=0; i<N; i++) {
5658 bringDownServiceLocked(services.get(i), true);
5659 }
5660
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005661 if (doit) {
5662 if (purgeCache) {
5663 AttributeCache ac = AttributeCache.instance();
5664 if (ac != null) {
5665 ac.removePackage(name);
5666 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005667 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005668 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005669 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005670
5671 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 }
5673
5674 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5675 final String name = app.processName;
5676 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005677 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 TAG, "Force removing process " + app + " (" + name
5679 + "/" + uid + ")");
5680
5681 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005682 if (mHeavyWeightProcess == app) {
5683 mHeavyWeightProcess = null;
5684 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005686 boolean needRestart = false;
5687 if (app.pid > 0 && app.pid != MY_PID) {
5688 int pid = app.pid;
5689 synchronized (mPidsSelfLocked) {
5690 mPidsSelfLocked.remove(pid);
5691 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5692 }
5693 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005694 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005695 Process.killProcess(pid);
5696
5697 if (app.persistent) {
5698 if (!callerWillRestart) {
5699 addAppLocked(app.info);
5700 } else {
5701 needRestart = true;
5702 }
5703 }
5704 } else {
5705 mRemovedProcesses.add(app);
5706 }
5707
5708 return needRestart;
5709 }
5710
5711 private final void processStartTimedOutLocked(ProcessRecord app) {
5712 final int pid = app.pid;
5713 boolean gone = false;
5714 synchronized (mPidsSelfLocked) {
5715 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5716 if (knownApp != null && knownApp.thread == null) {
5717 mPidsSelfLocked.remove(pid);
5718 gone = true;
5719 }
5720 }
5721
5722 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005723 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005724 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005725 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005727 if (mHeavyWeightProcess == app) {
5728 mHeavyWeightProcess = null;
5729 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5730 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005731 // Take care of any launching providers waiting for this process.
5732 checkAppInLaunchingProvidersLocked(app, true);
5733 // Take care of any services that are waiting for the process.
5734 for (int i=0; i<mPendingServices.size(); i++) {
5735 ServiceRecord sr = mPendingServices.get(i);
5736 if (app.info.uid == sr.appInfo.uid
5737 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005738 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005739 mPendingServices.remove(i);
5740 i--;
5741 bringDownServiceLocked(sr, true);
5742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005743 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005744 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005745 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005746 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005747 try {
5748 IBackupManager bm = IBackupManager.Stub.asInterface(
5749 ServiceManager.getService(Context.BACKUP_SERVICE));
5750 bm.agentDisconnected(app.info.packageName);
5751 } catch (RemoteException e) {
5752 // Can't happen; the backup manager is local
5753 }
5754 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005755 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005756 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005757 mPendingBroadcast = null;
5758 scheduleBroadcastsLocked();
5759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005761 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005762 }
5763 }
5764
5765 private final boolean attachApplicationLocked(IApplicationThread thread,
5766 int pid) {
5767
5768 // Find the application record that is being attached... either via
5769 // the pid if we are running in multiple processes, or just pull the
5770 // next app record if we are emulating process with anonymous threads.
5771 ProcessRecord app;
5772 if (pid != MY_PID && pid >= 0) {
5773 synchronized (mPidsSelfLocked) {
5774 app = mPidsSelfLocked.get(pid);
5775 }
5776 } else if (mStartingProcesses.size() > 0) {
5777 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005778 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005779 } else {
5780 app = null;
5781 }
5782
5783 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005784 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005785 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005786 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005787 if (pid > 0 && pid != MY_PID) {
5788 Process.killProcess(pid);
5789 } else {
5790 try {
5791 thread.scheduleExit();
5792 } catch (Exception e) {
5793 // Ignore exceptions.
5794 }
5795 }
5796 return false;
5797 }
5798
5799 // If this application record is still attached to a previous
5800 // process, clean it up now.
5801 if (app.thread != null) {
5802 handleAppDiedLocked(app, true);
5803 }
5804
5805 // Tell the process all about itself.
5806
Joe Onorato8a9b2202010-02-26 18:56:32 -08005807 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005808 TAG, "Binding process pid " + pid + " to record " + app);
5809
5810 String processName = app.processName;
5811 try {
5812 thread.asBinder().linkToDeath(new AppDeathRecipient(
5813 app, pid, thread), 0);
5814 } catch (RemoteException e) {
5815 app.resetPackageList();
5816 startProcessLocked(app, "link fail", processName);
5817 return false;
5818 }
5819
Doug Zongker2bec3d42009-12-04 12:52:44 -08005820 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005821
5822 app.thread = thread;
5823 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005824 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5825 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005826 app.forcingToForeground = null;
5827 app.foregroundServices = false;
5828 app.debugging = false;
5829
5830 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5831
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005832 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5833 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005834
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005835 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005836 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005837 }
5838
Joe Onorato8a9b2202010-02-26 18:56:32 -08005839 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 TAG, "New app record " + app
5841 + " thread=" + thread.asBinder() + " pid=" + pid);
5842 try {
5843 int testMode = IApplicationThread.DEBUG_OFF;
5844 if (mDebugApp != null && mDebugApp.equals(processName)) {
5845 testMode = mWaitForDebugger
5846 ? IApplicationThread.DEBUG_WAIT
5847 : IApplicationThread.DEBUG_ON;
5848 app.debugging = true;
5849 if (mDebugTransient) {
5850 mDebugApp = mOrigDebugApp;
5851 mWaitForDebugger = mOrigWaitForDebugger;
5852 }
5853 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005854
Christopher Tate181fafa2009-05-14 11:12:14 -07005855 // If the app is being launched for restore or full backup, set it up specially
5856 boolean isRestrictedBackupMode = false;
5857 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5858 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5859 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5860 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005861
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005862 ensurePackageDexOpt(app.instrumentationInfo != null
5863 ? app.instrumentationInfo.packageName
5864 : app.info.packageName);
5865 if (app.instrumentationClass != null) {
5866 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005867 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005868 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005869 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005870 thread.bindApplication(processName, app.instrumentationInfo != null
5871 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005872 app.instrumentationClass, app.instrumentationProfileFile,
5873 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005874 isRestrictedBackupMode || !normalMode,
5875 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005876 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005877 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 } catch (Exception e) {
5879 // todo: Yikes! What should we do? For now we will try to
5880 // start another process, but that could easily get us in
5881 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005882 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005883
5884 app.resetPackageList();
5885 startProcessLocked(app, "bind fail", processName);
5886 return false;
5887 }
5888
5889 // Remove this record from the list of starting applications.
5890 mPersistentStartingProcesses.remove(app);
5891 mProcessesOnHold.remove(app);
5892
5893 boolean badApp = false;
5894 boolean didSomething = false;
5895
5896 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005897 ActivityRecord hr = topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07005898 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005899 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5900 && processName.equals(hr.processName)) {
5901 try {
5902 if (realStartActivityLocked(hr, app, true, true)) {
5903 didSomething = true;
5904 }
5905 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005906 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 + hr.intent.getComponent().flattenToShortString(), e);
5908 badApp = true;
5909 }
5910 } else {
5911 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5912 }
5913 }
5914
5915 // Find any services that should be running in this process...
5916 if (!badApp && mPendingServices.size() > 0) {
5917 ServiceRecord sr = null;
5918 try {
5919 for (int i=0; i<mPendingServices.size(); i++) {
5920 sr = mPendingServices.get(i);
5921 if (app.info.uid != sr.appInfo.uid
5922 || !processName.equals(sr.processName)) {
5923 continue;
5924 }
5925
5926 mPendingServices.remove(i);
5927 i--;
5928 realStartServiceLocked(sr, app);
5929 didSomething = true;
5930 }
5931 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005932 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933 + sr.shortName, e);
5934 badApp = true;
5935 }
5936 }
5937
5938 // Check if the next broadcast receiver is in this process...
5939 BroadcastRecord br = mPendingBroadcast;
5940 if (!badApp && br != null && br.curApp == app) {
5941 try {
5942 mPendingBroadcast = null;
5943 processCurBroadcastLocked(br, app);
5944 didSomething = true;
5945 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005946 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 + br.curComponent.flattenToShortString(), e);
5948 badApp = true;
5949 logBroadcastReceiverDiscard(br);
5950 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5951 br.resultExtras, br.resultAbort, true);
5952 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005953 // We need to reset the state if we fails to start the receiver.
5954 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 }
5956 }
5957
Christopher Tate181fafa2009-05-14 11:12:14 -07005958 // Check whether the next backup agent is in this process...
5959 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005960 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005961 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005962 try {
5963 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5964 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005965 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005966 e.printStackTrace();
5967 }
5968 }
5969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970 if (badApp) {
5971 // todo: Also need to kill application to deal with all
5972 // kinds of exceptions.
5973 handleAppDiedLocked(app, false);
5974 return false;
5975 }
5976
5977 if (!didSomething) {
5978 updateOomAdjLocked();
5979 }
5980
5981 return true;
5982 }
5983
5984 public final void attachApplication(IApplicationThread thread) {
5985 synchronized (this) {
5986 int callingPid = Binder.getCallingPid();
5987 final long origId = Binder.clearCallingIdentity();
5988 attachApplicationLocked(thread, callingPid);
5989 Binder.restoreCallingIdentity(origId);
5990 }
5991 }
5992
Dianne Hackborne88846e2009-09-30 21:34:25 -07005993 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005994 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005995 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996 Binder.restoreCallingIdentity(origId);
5997 }
5998
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005999 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006000 boolean remove) {
6001 int N = mStoppingActivities.size();
6002 if (N <= 0) return null;
6003
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006004 ArrayList<ActivityRecord> stops = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006005
6006 final boolean nowVisible = mResumedActivity != null
6007 && mResumedActivity.nowVisible
6008 && !mResumedActivity.waitingVisible;
6009 for (int i=0; i<N; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006010 ActivityRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006011 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006012 + nowVisible + " waitingVisible=" + s.waitingVisible
6013 + " finishing=" + s.finishing);
6014 if (s.waitingVisible && nowVisible) {
6015 mWaitingVisibleActivities.remove(s);
6016 s.waitingVisible = false;
6017 if (s.finishing) {
6018 // If this activity is finishing, it is sitting on top of
6019 // everyone else but we now know it is no longer needed...
6020 // so get rid of it. Otherwise, we need to go through the
6021 // normal flow and hide it once we determine that it is
6022 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006023 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006024 mWindowManager.setAppVisibility(s, false);
6025 }
6026 }
6027 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006028 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006029 if (stops == null) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006030 stops = new ArrayList<ActivityRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006031 }
6032 stops.add(s);
6033 mStoppingActivities.remove(i);
6034 N--;
6035 i--;
6036 }
6037 }
6038
6039 return stops;
6040 }
6041
6042 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08006043 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006044 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006045 mWindowManager.enableScreenAfterBoot();
6046 }
6047
Dianne Hackborne88846e2009-09-30 21:34:25 -07006048 final void activityIdleInternal(IBinder token, boolean fromTimeout,
6049 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006050 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006051
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006052 ArrayList<ActivityRecord> stops = null;
6053 ArrayList<ActivityRecord> finishes = null;
6054 ArrayList<ActivityRecord> thumbnails = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006055 int NS = 0;
6056 int NF = 0;
6057 int NT = 0;
6058 IApplicationThread sendThumbnail = null;
6059 boolean booting = false;
6060 boolean enableScreen = false;
6061
6062 synchronized (this) {
6063 if (token != null) {
6064 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
6065 }
6066
6067 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07006068 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006069 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006070 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006071
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006072 if (fromTimeout) {
6073 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
6074 }
6075
Dianne Hackborne88846e2009-09-30 21:34:25 -07006076 // This is a hack to semi-deal with a race condition
6077 // in the client where it can be constructed with a
6078 // newer configuration from when we asked it to launch.
6079 // We'll update with whatever configuration it now says
6080 // it used to launch.
6081 if (config != null) {
6082 r.configuration = config;
6083 }
6084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006085 // No longer need to keep the device awake.
6086 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
6087 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
6088 mLaunchingActivity.release();
6089 }
6090
6091 // We are now idle. If someone is waiting for a thumbnail from
6092 // us, we can now deliver.
6093 r.idle = true;
6094 scheduleAppGcsLocked();
6095 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
6096 sendThumbnail = r.app.thread;
6097 r.thumbnailNeeded = false;
6098 }
6099
6100 // If this activity is fullscreen, set up to hide those under it.
6101
Joe Onorato8a9b2202010-02-26 18:56:32 -08006102 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006103 ensureActivitiesVisibleLocked(null, 0);
6104
Joe Onorato8a9b2202010-02-26 18:56:32 -08006105 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006106 if (!mBooted && !fromTimeout) {
6107 mBooted = true;
6108 enableScreen = true;
6109 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006110
6111 } else if (fromTimeout) {
6112 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006113 }
6114
6115 // Atomically retrieve all of the other things to do.
6116 stops = processStoppingActivitiesLocked(true);
6117 NS = stops != null ? stops.size() : 0;
6118 if ((NF=mFinishingActivities.size()) > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006119 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006120 mFinishingActivities.clear();
6121 }
6122 if ((NT=mCancelledThumbnails.size()) > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006123 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006124 mCancelledThumbnails.clear();
6125 }
6126
6127 booting = mBooting;
6128 mBooting = false;
6129 }
6130
6131 int i;
6132
6133 // Send thumbnail if requested.
6134 if (sendThumbnail != null) {
6135 try {
6136 sendThumbnail.requestThumbnail(token);
6137 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006138 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006139 sendPendingThumbnail(null, token, null, null, true);
6140 }
6141 }
6142
6143 // Stop any activities that are scheduled to do so but have been
6144 // waiting for the next one to start.
6145 for (i=0; i<NS; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006146 ActivityRecord r = (ActivityRecord)stops.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006147 synchronized (this) {
6148 if (r.finishing) {
6149 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
6150 } else {
6151 stopActivityLocked(r);
6152 }
6153 }
6154 }
6155
6156 // Finish any activities that are scheduled to do so but have been
6157 // waiting for the next one to start.
6158 for (i=0; i<NF; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006159 ActivityRecord r = (ActivityRecord)finishes.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006160 synchronized (this) {
6161 destroyActivityLocked(r, true);
6162 }
6163 }
6164
6165 // Report back to any thumbnail receivers.
6166 for (i=0; i<NT; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006167 ActivityRecord r = (ActivityRecord)thumbnails.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006168 sendPendingThumbnail(r, null, null, null, true);
6169 }
6170
6171 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006172 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006173 }
6174
6175 trimApplications();
6176 //dump();
6177 //mWindowManager.dump();
6178
6179 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006180 enableScreenAfterBoot();
6181 }
6182 }
6183
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006184 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006185 IntentFilter pkgFilter = new IntentFilter();
6186 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
6187 pkgFilter.addDataScheme("package");
6188 mContext.registerReceiver(new BroadcastReceiver() {
6189 @Override
6190 public void onReceive(Context context, Intent intent) {
6191 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
6192 if (pkgs != null) {
6193 for (String pkg : pkgs) {
6194 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
6195 setResultCode(Activity.RESULT_OK);
6196 return;
6197 }
6198 }
6199 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006200 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006201 }, pkgFilter);
6202
6203 synchronized (this) {
6204 // Ensure that any processes we had put on hold are now started
6205 // up.
6206 final int NP = mProcessesOnHold.size();
6207 if (NP > 0) {
6208 ArrayList<ProcessRecord> procs =
6209 new ArrayList<ProcessRecord>(mProcessesOnHold);
6210 for (int ip=0; ip<NP; ip++) {
6211 this.startProcessLocked(procs.get(ip), "on-hold", null);
6212 }
6213 }
6214
6215 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6216 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006217 broadcastIntentLocked(null, null,
6218 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
6219 null, null, 0, null, null,
6220 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
6221 false, false, MY_PID, Process.SYSTEM_UID);
6222 }
6223 }
6224 }
6225
6226 final void ensureBootCompleted() {
6227 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006228 boolean enableScreen;
6229 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006230 booting = mBooting;
6231 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006232 enableScreen = !mBooted;
6233 mBooted = true;
6234 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006235
6236 if (booting) {
6237 finishBooting();
6238 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006239
6240 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006241 enableScreenAfterBoot();
6242 }
6243 }
6244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006245 public final void activityPaused(IBinder token, Bundle icicle) {
6246 // Refuse possible leaked file descriptors
6247 if (icicle != null && icicle.hasFileDescriptors()) {
6248 throw new IllegalArgumentException("File descriptors passed in Bundle");
6249 }
6250
6251 final long origId = Binder.clearCallingIdentity();
6252 activityPaused(token, icicle, false);
6253 Binder.restoreCallingIdentity(origId);
6254 }
6255
6256 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006257 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006258 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
6259 + ", timeout=" + timeout);
6260
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006261 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006262
6263 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006264 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006265 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006266 r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006267 if (!timeout) {
6268 r.icicle = icicle;
6269 r.haveState = true;
6270 }
6271 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
6272 if (mPausingActivity == r) {
6273 r.state = ActivityState.PAUSED;
6274 completePauseLocked();
6275 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08006276 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006277 System.identityHashCode(r), r.shortComponentName,
6278 mPausingActivity != null
6279 ? mPausingActivity.shortComponentName : "(none)");
6280 }
6281 }
6282 }
6283 }
6284
6285 public final void activityStopped(IBinder token, Bitmap thumbnail,
6286 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006287 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006288 TAG, "Activity stopped: token=" + token);
6289
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006290 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006291
6292 final long origId = Binder.clearCallingIdentity();
6293
6294 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006295 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006296 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006297 r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006298 r.thumbnail = thumbnail;
6299 r.description = description;
6300 r.stopped = true;
6301 r.state = ActivityState.STOPPED;
6302 if (!r.finishing) {
6303 if (r.configDestroy) {
6304 destroyActivityLocked(r, true);
6305 resumeTopActivityLocked(null);
6306 }
6307 }
6308 }
6309 }
6310
6311 if (r != null) {
6312 sendPendingThumbnail(r, null, null, null, false);
6313 }
6314
6315 trimApplications();
6316
6317 Binder.restoreCallingIdentity(origId);
6318 }
6319
6320 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006321 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 synchronized (this) {
6323 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
6324
Dianne Hackborn75b03852009-06-12 15:43:26 -07006325 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006326 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006327 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006328 if (r.state == ActivityState.DESTROYING) {
6329 final long origId = Binder.clearCallingIdentity();
6330 removeActivityFromHistoryLocked(r);
6331 Binder.restoreCallingIdentity(origId);
6332 }
6333 }
6334 }
6335 }
6336
6337 public String getCallingPackage(IBinder token) {
6338 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006339 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07006340 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006341 }
6342 }
6343
6344 public ComponentName getCallingActivity(IBinder token) {
6345 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006346 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006347 return r != null ? r.intent.getComponent() : null;
6348 }
6349 }
6350
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006351 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006352 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006353 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006354 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006355 if (r != null) {
6356 return r.resultTo;
6357 }
6358 }
6359 return null;
6360 }
6361
6362 public ComponentName getActivityClassForToken(IBinder token) {
6363 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006364 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006365 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006366 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006367 return r.intent.getComponent();
6368 }
6369 return null;
6370 }
6371 }
6372
6373 public String getPackageForToken(IBinder token) {
6374 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006375 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006376 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006377 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006378 return r.packageName;
6379 }
6380 return null;
6381 }
6382 }
6383
6384 public IIntentSender getIntentSender(int type,
6385 String packageName, IBinder token, String resultWho,
6386 int requestCode, Intent intent, String resolvedType, int flags) {
6387 // Refuse possible leaked file descriptors
6388 if (intent != null && intent.hasFileDescriptors() == true) {
6389 throw new IllegalArgumentException("File descriptors passed in Intent");
6390 }
6391
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006392 if (type == INTENT_SENDER_BROADCAST) {
6393 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6394 throw new IllegalArgumentException(
6395 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6396 }
6397 }
6398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006399 synchronized(this) {
6400 int callingUid = Binder.getCallingUid();
6401 try {
6402 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6403 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006404 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006405 .getPackageUid(packageName);
6406 if (uid != Binder.getCallingUid()) {
6407 String msg = "Permission Denial: getIntentSender() from pid="
6408 + Binder.getCallingPid()
6409 + ", uid=" + Binder.getCallingUid()
6410 + ", (need uid=" + uid + ")"
6411 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006412 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006413 throw new SecurityException(msg);
6414 }
6415 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006416
6417 return getIntentSenderLocked(type, packageName, callingUid,
6418 token, resultWho, requestCode, intent, resolvedType, flags);
6419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420 } catch (RemoteException e) {
6421 throw new SecurityException(e);
6422 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006423 }
6424 }
6425
6426 IIntentSender getIntentSenderLocked(int type,
6427 String packageName, int callingUid, IBinder token, String resultWho,
6428 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006429 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006430 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6431 int index = indexOfTokenLocked(token);
6432 if (index < 0) {
6433 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006434 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006435 activity = (ActivityRecord)mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07006436 if (activity.finishing) {
6437 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006438 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006439 }
6440
6441 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6442 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6443 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6444 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6445 |PendingIntent.FLAG_UPDATE_CURRENT);
6446
6447 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6448 type, packageName, activity, resultWho,
6449 requestCode, intent, resolvedType, flags);
6450 WeakReference<PendingIntentRecord> ref;
6451 ref = mIntentSenderRecords.get(key);
6452 PendingIntentRecord rec = ref != null ? ref.get() : null;
6453 if (rec != null) {
6454 if (!cancelCurrent) {
6455 if (updateCurrent) {
6456 rec.key.requestIntent.replaceExtras(intent);
6457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006458 return rec;
6459 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006460 rec.canceled = true;
6461 mIntentSenderRecords.remove(key);
6462 }
6463 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006464 return rec;
6465 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006466 rec = new PendingIntentRecord(this, key, callingUid);
6467 mIntentSenderRecords.put(key, rec.ref);
6468 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6469 if (activity.pendingResults == null) {
6470 activity.pendingResults
6471 = new HashSet<WeakReference<PendingIntentRecord>>();
6472 }
6473 activity.pendingResults.add(rec.ref);
6474 }
6475 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006476 }
6477
6478 public void cancelIntentSender(IIntentSender sender) {
6479 if (!(sender instanceof PendingIntentRecord)) {
6480 return;
6481 }
6482 synchronized(this) {
6483 PendingIntentRecord rec = (PendingIntentRecord)sender;
6484 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006485 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 .getPackageUid(rec.key.packageName);
6487 if (uid != Binder.getCallingUid()) {
6488 String msg = "Permission Denial: cancelIntentSender() from pid="
6489 + Binder.getCallingPid()
6490 + ", uid=" + Binder.getCallingUid()
6491 + " is not allowed to cancel packges "
6492 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006493 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006494 throw new SecurityException(msg);
6495 }
6496 } catch (RemoteException e) {
6497 throw new SecurityException(e);
6498 }
6499 cancelIntentSenderLocked(rec, true);
6500 }
6501 }
6502
6503 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6504 rec.canceled = true;
6505 mIntentSenderRecords.remove(rec.key);
6506 if (cleanActivity && rec.key.activity != null) {
6507 rec.key.activity.pendingResults.remove(rec.ref);
6508 }
6509 }
6510
6511 public String getPackageForIntentSender(IIntentSender pendingResult) {
6512 if (!(pendingResult instanceof PendingIntentRecord)) {
6513 return null;
6514 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006515 try {
6516 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6517 return res.key.packageName;
6518 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006519 }
6520 return null;
6521 }
6522
6523 public void setProcessLimit(int max) {
6524 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6525 "setProcessLimit()");
6526 mProcessLimit = max;
6527 }
6528
6529 public int getProcessLimit() {
6530 return mProcessLimit;
6531 }
6532
6533 void foregroundTokenDied(ForegroundToken token) {
6534 synchronized (ActivityManagerService.this) {
6535 synchronized (mPidsSelfLocked) {
6536 ForegroundToken cur
6537 = mForegroundProcesses.get(token.pid);
6538 if (cur != token) {
6539 return;
6540 }
6541 mForegroundProcesses.remove(token.pid);
6542 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6543 if (pr == null) {
6544 return;
6545 }
6546 pr.forcingToForeground = null;
6547 pr.foregroundServices = false;
6548 }
6549 updateOomAdjLocked();
6550 }
6551 }
6552
6553 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6554 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6555 "setProcessForeground()");
6556 synchronized(this) {
6557 boolean changed = false;
6558
6559 synchronized (mPidsSelfLocked) {
6560 ProcessRecord pr = mPidsSelfLocked.get(pid);
6561 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006562 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006563 return;
6564 }
6565 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6566 if (oldToken != null) {
6567 oldToken.token.unlinkToDeath(oldToken, 0);
6568 mForegroundProcesses.remove(pid);
6569 pr.forcingToForeground = null;
6570 changed = true;
6571 }
6572 if (isForeground && token != null) {
6573 ForegroundToken newToken = new ForegroundToken() {
6574 public void binderDied() {
6575 foregroundTokenDied(this);
6576 }
6577 };
6578 newToken.pid = pid;
6579 newToken.token = token;
6580 try {
6581 token.linkToDeath(newToken, 0);
6582 mForegroundProcesses.put(pid, newToken);
6583 pr.forcingToForeground = token;
6584 changed = true;
6585 } catch (RemoteException e) {
6586 // If the process died while doing this, we will later
6587 // do the cleanup with the process death link.
6588 }
6589 }
6590 }
6591
6592 if (changed) {
6593 updateOomAdjLocked();
6594 }
6595 }
6596 }
6597
6598 // =========================================================
6599 // PERMISSIONS
6600 // =========================================================
6601
6602 static class PermissionController extends IPermissionController.Stub {
6603 ActivityManagerService mActivityManagerService;
6604 PermissionController(ActivityManagerService activityManagerService) {
6605 mActivityManagerService = activityManagerService;
6606 }
6607
6608 public boolean checkPermission(String permission, int pid, int uid) {
6609 return mActivityManagerService.checkPermission(permission, pid,
6610 uid) == PackageManager.PERMISSION_GRANTED;
6611 }
6612 }
6613
6614 /**
6615 * This can be called with or without the global lock held.
6616 */
6617 int checkComponentPermission(String permission, int pid, int uid,
6618 int reqUid) {
6619 // We might be performing an operation on behalf of an indirect binder
6620 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6621 // client identity accordingly before proceeding.
6622 Identity tlsIdentity = sCallerIdentity.get();
6623 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006624 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006625 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6626 uid = tlsIdentity.uid;
6627 pid = tlsIdentity.pid;
6628 }
6629
6630 // Root, system server and our own process get to do everything.
6631 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6632 !Process.supportsProcesses()) {
6633 return PackageManager.PERMISSION_GRANTED;
6634 }
6635 // If the target requires a specific UID, always fail for others.
6636 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006637 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006638 return PackageManager.PERMISSION_DENIED;
6639 }
6640 if (permission == null) {
6641 return PackageManager.PERMISSION_GRANTED;
6642 }
6643 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006644 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006645 .checkUidPermission(permission, uid);
6646 } catch (RemoteException e) {
6647 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006648 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006649 }
6650 return PackageManager.PERMISSION_DENIED;
6651 }
6652
6653 /**
6654 * As the only public entry point for permissions checking, this method
6655 * can enforce the semantic that requesting a check on a null global
6656 * permission is automatically denied. (Internally a null permission
6657 * string is used when calling {@link #checkComponentPermission} in cases
6658 * when only uid-based security is needed.)
6659 *
6660 * This can be called with or without the global lock held.
6661 */
6662 public int checkPermission(String permission, int pid, int uid) {
6663 if (permission == null) {
6664 return PackageManager.PERMISSION_DENIED;
6665 }
6666 return checkComponentPermission(permission, pid, uid, -1);
6667 }
6668
6669 /**
6670 * Binder IPC calls go through the public entry point.
6671 * This can be called with or without the global lock held.
6672 */
6673 int checkCallingPermission(String permission) {
6674 return checkPermission(permission,
6675 Binder.getCallingPid(),
6676 Binder.getCallingUid());
6677 }
6678
6679 /**
6680 * This can be called with or without the global lock held.
6681 */
6682 void enforceCallingPermission(String permission, String func) {
6683 if (checkCallingPermission(permission)
6684 == PackageManager.PERMISSION_GRANTED) {
6685 return;
6686 }
6687
6688 String msg = "Permission Denial: " + func + " from pid="
6689 + Binder.getCallingPid()
6690 + ", uid=" + Binder.getCallingUid()
6691 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006692 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006693 throw new SecurityException(msg);
6694 }
6695
6696 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6697 ProviderInfo pi, int uid, int modeFlags) {
6698 try {
6699 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6700 if ((pi.readPermission != null) &&
6701 (pm.checkUidPermission(pi.readPermission, uid)
6702 != PackageManager.PERMISSION_GRANTED)) {
6703 return false;
6704 }
6705 }
6706 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6707 if ((pi.writePermission != null) &&
6708 (pm.checkUidPermission(pi.writePermission, uid)
6709 != PackageManager.PERMISSION_GRANTED)) {
6710 return false;
6711 }
6712 }
6713 return true;
6714 } catch (RemoteException e) {
6715 return false;
6716 }
6717 }
6718
6719 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6720 int modeFlags) {
6721 // Root gets to do everything.
6722 if (uid == 0 || !Process.supportsProcesses()) {
6723 return true;
6724 }
6725 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6726 if (perms == null) return false;
6727 UriPermission perm = perms.get(uri);
6728 if (perm == null) return false;
6729 return (modeFlags&perm.modeFlags) == modeFlags;
6730 }
6731
6732 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6733 // Another redirected-binder-call permissions check as in
6734 // {@link checkComponentPermission}.
6735 Identity tlsIdentity = sCallerIdentity.get();
6736 if (tlsIdentity != null) {
6737 uid = tlsIdentity.uid;
6738 pid = tlsIdentity.pid;
6739 }
6740
6741 // Our own process gets to do everything.
6742 if (pid == MY_PID) {
6743 return PackageManager.PERMISSION_GRANTED;
6744 }
6745 synchronized(this) {
6746 return checkUriPermissionLocked(uri, uid, modeFlags)
6747 ? PackageManager.PERMISSION_GRANTED
6748 : PackageManager.PERMISSION_DENIED;
6749 }
6750 }
6751
6752 private void grantUriPermissionLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006753 String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006754 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6755 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6756 if (modeFlags == 0) {
6757 return;
6758 }
6759
Joe Onorato8a9b2202010-02-26 18:56:32 -08006760 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006761 "Requested grant " + targetPkg + " permission to " + uri);
6762
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006763 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006764
6765 // If this is not a content: uri, we can't do anything with it.
6766 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006767 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006768 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006769 return;
6770 }
6771
6772 String name = uri.getAuthority();
6773 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006774 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006775 if (cpr != null) {
6776 pi = cpr.info;
6777 } else {
6778 try {
6779 pi = pm.resolveContentProvider(name,
6780 PackageManager.GET_URI_PERMISSION_PATTERNS);
6781 } catch (RemoteException ex) {
6782 }
6783 }
6784 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006785 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006786 return;
6787 }
6788
6789 int targetUid;
6790 try {
6791 targetUid = pm.getPackageUid(targetPkg);
6792 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006793 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006794 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006795 return;
6796 }
6797 } catch (RemoteException ex) {
6798 return;
6799 }
6800
6801 // First... does the target actually need this permission?
6802 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6803 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006804 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006805 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006806 return;
6807 }
6808
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006809 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006810 if (!pi.grantUriPermissions) {
6811 throw new SecurityException("Provider " + pi.packageName
6812 + "/" + pi.name
6813 + " does not allow granting of Uri permissions (uri "
6814 + uri + ")");
6815 }
6816 if (pi.uriPermissionPatterns != null) {
6817 final int N = pi.uriPermissionPatterns.length;
6818 boolean allowed = false;
6819 for (int i=0; i<N; i++) {
6820 if (pi.uriPermissionPatterns[i] != null
6821 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6822 allowed = true;
6823 break;
6824 }
6825 }
6826 if (!allowed) {
6827 throw new SecurityException("Provider " + pi.packageName
6828 + "/" + pi.name
6829 + " does not allow granting of permission to path of Uri "
6830 + uri);
6831 }
6832 }
6833
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006834 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006835 // this uri?
6836 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6837 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6838 throw new SecurityException("Uid " + callingUid
6839 + " does not have permission to uri " + uri);
6840 }
6841 }
6842
6843 // Okay! So here we are: the caller has the assumed permission
6844 // to the uri, and the target doesn't. Let's now give this to
6845 // the target.
6846
Joe Onorato8a9b2202010-02-26 18:56:32 -08006847 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006848 "Granting " + targetPkg + " permission to " + uri);
6849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006850 HashMap<Uri, UriPermission> targetUris
6851 = mGrantedUriPermissions.get(targetUid);
6852 if (targetUris == null) {
6853 targetUris = new HashMap<Uri, UriPermission>();
6854 mGrantedUriPermissions.put(targetUid, targetUris);
6855 }
6856
6857 UriPermission perm = targetUris.get(uri);
6858 if (perm == null) {
6859 perm = new UriPermission(targetUid, uri);
6860 targetUris.put(uri, perm);
6861
6862 }
6863 perm.modeFlags |= modeFlags;
6864 if (activity == null) {
6865 perm.globalModeFlags |= modeFlags;
6866 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6867 perm.readActivities.add(activity);
6868 if (activity.readUriPermissions == null) {
6869 activity.readUriPermissions = new HashSet<UriPermission>();
6870 }
6871 activity.readUriPermissions.add(perm);
6872 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6873 perm.writeActivities.add(activity);
6874 if (activity.writeUriPermissions == null) {
6875 activity.writeUriPermissions = new HashSet<UriPermission>();
6876 }
6877 activity.writeUriPermissions.add(perm);
6878 }
6879 }
6880
6881 private void grantUriPermissionFromIntentLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006882 String targetPkg, Intent intent, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006883 if (intent == null) {
6884 return;
6885 }
6886 Uri data = intent.getData();
6887 if (data == null) {
6888 return;
6889 }
6890 grantUriPermissionLocked(callingUid, targetPkg, data,
6891 intent.getFlags(), activity);
6892 }
6893
6894 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6895 Uri uri, int modeFlags) {
6896 synchronized(this) {
6897 final ProcessRecord r = getRecordForAppLocked(caller);
6898 if (r == null) {
6899 throw new SecurityException("Unable to find app for caller "
6900 + caller
6901 + " when granting permission to uri " + uri);
6902 }
6903 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006904 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006905 return;
6906 }
6907 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006908 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006909 return;
6910 }
6911
6912 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6913 null);
6914 }
6915 }
6916
6917 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6918 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6919 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6920 HashMap<Uri, UriPermission> perms
6921 = mGrantedUriPermissions.get(perm.uid);
6922 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006923 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006924 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006925 perms.remove(perm.uri);
6926 if (perms.size() == 0) {
6927 mGrantedUriPermissions.remove(perm.uid);
6928 }
6929 }
6930 }
6931 }
6932
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006933 private void removeActivityUriPermissionsLocked(ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006934 if (activity.readUriPermissions != null) {
6935 for (UriPermission perm : activity.readUriPermissions) {
6936 perm.readActivities.remove(activity);
6937 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6938 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6939 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6940 removeUriPermissionIfNeededLocked(perm);
6941 }
6942 }
6943 }
6944 if (activity.writeUriPermissions != null) {
6945 for (UriPermission perm : activity.writeUriPermissions) {
6946 perm.writeActivities.remove(activity);
6947 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6948 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6949 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6950 removeUriPermissionIfNeededLocked(perm);
6951 }
6952 }
6953 }
6954 }
6955
6956 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6957 int modeFlags) {
6958 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6959 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6960 if (modeFlags == 0) {
6961 return;
6962 }
6963
Joe Onorato8a9b2202010-02-26 18:56:32 -08006964 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006965 "Revoking all granted permissions to " + uri);
6966
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006967 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006968
6969 final String authority = uri.getAuthority();
6970 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006971 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006972 if (cpr != null) {
6973 pi = cpr.info;
6974 } else {
6975 try {
6976 pi = pm.resolveContentProvider(authority,
6977 PackageManager.GET_URI_PERMISSION_PATTERNS);
6978 } catch (RemoteException ex) {
6979 }
6980 }
6981 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006982 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006983 return;
6984 }
6985
6986 // Does the caller have this permission on the URI?
6987 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6988 // Right now, if you are not the original owner of the permission,
6989 // you are not allowed to revoke it.
6990 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6991 throw new SecurityException("Uid " + callingUid
6992 + " does not have permission to uri " + uri);
6993 //}
6994 }
6995
6996 // Go through all of the permissions and remove any that match.
6997 final List<String> SEGMENTS = uri.getPathSegments();
6998 if (SEGMENTS != null) {
6999 final int NS = SEGMENTS.size();
7000 int N = mGrantedUriPermissions.size();
7001 for (int i=0; i<N; i++) {
7002 HashMap<Uri, UriPermission> perms
7003 = mGrantedUriPermissions.valueAt(i);
7004 Iterator<UriPermission> it = perms.values().iterator();
7005 toploop:
7006 while (it.hasNext()) {
7007 UriPermission perm = it.next();
7008 Uri targetUri = perm.uri;
7009 if (!authority.equals(targetUri.getAuthority())) {
7010 continue;
7011 }
7012 List<String> targetSegments = targetUri.getPathSegments();
7013 if (targetSegments == null) {
7014 continue;
7015 }
7016 if (targetSegments.size() < NS) {
7017 continue;
7018 }
7019 for (int j=0; j<NS; j++) {
7020 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
7021 continue toploop;
7022 }
7023 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007024 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08007025 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007026 perm.clearModes(modeFlags);
7027 if (perm.modeFlags == 0) {
7028 it.remove();
7029 }
7030 }
7031 if (perms.size() == 0) {
7032 mGrantedUriPermissions.remove(
7033 mGrantedUriPermissions.keyAt(i));
7034 N--;
7035 i--;
7036 }
7037 }
7038 }
7039 }
7040
7041 public void revokeUriPermission(IApplicationThread caller, Uri uri,
7042 int modeFlags) {
7043 synchronized(this) {
7044 final ProcessRecord r = getRecordForAppLocked(caller);
7045 if (r == null) {
7046 throw new SecurityException("Unable to find app for caller "
7047 + caller
7048 + " when revoking permission to uri " + uri);
7049 }
7050 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007051 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007052 return;
7053 }
7054
7055 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
7056 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
7057 if (modeFlags == 0) {
7058 return;
7059 }
7060
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007061 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007062
7063 final String authority = uri.getAuthority();
7064 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07007065 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007066 if (cpr != null) {
7067 pi = cpr.info;
7068 } else {
7069 try {
7070 pi = pm.resolveContentProvider(authority,
7071 PackageManager.GET_URI_PERMISSION_PATTERNS);
7072 } catch (RemoteException ex) {
7073 }
7074 }
7075 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007076 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007077 return;
7078 }
7079
7080 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
7081 }
7082 }
7083
7084 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
7085 synchronized (this) {
7086 ProcessRecord app =
7087 who != null ? getRecordForAppLocked(who) : null;
7088 if (app == null) return;
7089
7090 Message msg = Message.obtain();
7091 msg.what = WAIT_FOR_DEBUGGER_MSG;
7092 msg.obj = app;
7093 msg.arg1 = waiting ? 1 : 0;
7094 mHandler.sendMessage(msg);
7095 }
7096 }
7097
7098 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
7099 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08007100 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007101 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08007102 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007103 }
7104
7105 // =========================================================
7106 // TASK MANAGEMENT
7107 // =========================================================
7108
7109 public List getTasks(int maxNum, int flags,
7110 IThumbnailReceiver receiver) {
7111 ArrayList list = new ArrayList();
7112
7113 PendingThumbnailsRecord pending = null;
7114 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007115 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007116
7117 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007118 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007119 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
7120 + ", receiver=" + receiver);
7121
7122 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
7123 != PackageManager.PERMISSION_GRANTED) {
7124 if (receiver != null) {
7125 // If the caller wants to wait for pending thumbnails,
7126 // it ain't gonna get them.
7127 try {
7128 receiver.finished();
7129 } catch (RemoteException ex) {
7130 }
7131 }
7132 String msg = "Permission Denial: getTasks() from pid="
7133 + Binder.getCallingPid()
7134 + ", uid=" + Binder.getCallingUid()
7135 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007136 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 throw new SecurityException(msg);
7138 }
7139
7140 int pos = mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007141 ActivityRecord next =
7142 pos >= 0 ? (ActivityRecord)mHistory.get(pos) : null;
7143 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007144 CharSequence topDescription = null;
7145 TaskRecord curTask = null;
7146 int numActivities = 0;
7147 int numRunning = 0;
7148 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007149 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007150 pos--;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007151 next = pos >= 0 ? (ActivityRecord)mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007152
7153 // Initialize state for next task if needed.
7154 if (top == null ||
7155 (top.state == ActivityState.INITIALIZING
7156 && top.task == r.task)) {
7157 top = r;
7158 topDescription = r.description;
7159 curTask = r.task;
7160 numActivities = numRunning = 0;
7161 }
7162
7163 // Add 'r' into the current task.
7164 numActivities++;
7165 if (r.app != null && r.app.thread != null) {
7166 numRunning++;
7167 }
7168 if (topDescription == null) {
7169 topDescription = r.description;
7170 }
7171
Joe Onorato8a9b2202010-02-26 18:56:32 -08007172 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007173 TAG, r.intent.getComponent().flattenToShortString()
7174 + ": task=" + r.task);
7175
7176 // If the next one is a different task, generate a new
7177 // TaskInfo entry for what we have.
7178 if (next == null || next.task != curTask) {
7179 ActivityManager.RunningTaskInfo ci
7180 = new ActivityManager.RunningTaskInfo();
7181 ci.id = curTask.taskId;
7182 ci.baseActivity = r.intent.getComponent();
7183 ci.topActivity = top.intent.getComponent();
7184 ci.thumbnail = top.thumbnail;
7185 ci.description = topDescription;
7186 ci.numActivities = numActivities;
7187 ci.numRunning = numRunning;
7188 //System.out.println(
7189 // "#" + maxNum + ": " + " descr=" + ci.description);
7190 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007191 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007192 TAG, "State=" + top.state + "Idle=" + top.idle
7193 + " app=" + top.app
7194 + " thr=" + (top.app != null ? top.app.thread : null));
7195 if (top.state == ActivityState.RESUMED
7196 || top.state == ActivityState.PAUSING) {
7197 if (top.idle && top.app != null
7198 && top.app.thread != null) {
7199 topRecord = top;
7200 topThumbnail = top.app.thread;
7201 } else {
7202 top.thumbnailNeeded = true;
7203 }
7204 }
7205 if (pending == null) {
7206 pending = new PendingThumbnailsRecord(receiver);
7207 }
7208 pending.pendingRecords.add(top);
7209 }
7210 list.add(ci);
7211 maxNum--;
7212 top = null;
7213 }
7214 }
7215
7216 if (pending != null) {
7217 mPendingThumbnails.add(pending);
7218 }
7219 }
7220
Joe Onorato8a9b2202010-02-26 18:56:32 -08007221 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007222
7223 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007224 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007225 try {
7226 topThumbnail.requestThumbnail(topRecord);
7227 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007228 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007229 sendPendingThumbnail(null, topRecord, null, null, true);
7230 }
7231 }
7232
7233 if (pending == null && receiver != null) {
7234 // In this case all thumbnails were available and the client
7235 // is being asked to be told when the remaining ones come in...
7236 // which is unusually, since the top-most currently running
7237 // activity should never have a canned thumbnail! Oh well.
7238 try {
7239 receiver.finished();
7240 } catch (RemoteException ex) {
7241 }
7242 }
7243
7244 return list;
7245 }
7246
7247 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
7248 int flags) {
7249 synchronized (this) {
7250 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
7251 "getRecentTasks()");
7252
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007253 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007255 final int N = mRecentTasks.size();
7256 ArrayList<ActivityManager.RecentTaskInfo> res
7257 = new ArrayList<ActivityManager.RecentTaskInfo>(
7258 maxNum < N ? maxNum : N);
7259 for (int i=0; i<N && maxNum > 0; i++) {
7260 TaskRecord tr = mRecentTasks.get(i);
7261 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
7262 || (tr.intent == null)
7263 || ((tr.intent.getFlags()
7264 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
7265 ActivityManager.RecentTaskInfo rti
7266 = new ActivityManager.RecentTaskInfo();
7267 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
7268 rti.baseIntent = new Intent(
7269 tr.intent != null ? tr.intent : tr.affinityIntent);
7270 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007271
7272 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
7273 // Check whether this activity is currently available.
7274 try {
7275 if (rti.origActivity != null) {
7276 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
7277 continue;
7278 }
7279 } else if (rti.baseIntent != null) {
7280 if (pm.queryIntentActivities(rti.baseIntent,
7281 null, 0) == null) {
7282 continue;
7283 }
7284 }
7285 } catch (RemoteException e) {
7286 // Will never happen.
7287 }
7288 }
7289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007290 res.add(rti);
7291 maxNum--;
7292 }
7293 }
7294 return res;
7295 }
7296 }
7297
7298 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
7299 int j;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007300 TaskRecord startTask = ((ActivityRecord)mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007301 TaskRecord jt = startTask;
7302
7303 // First look backwards
7304 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007305 ActivityRecord r = (ActivityRecord)mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306 if (r.task != jt) {
7307 jt = r.task;
7308 if (affinity.equals(jt.affinity)) {
7309 return j;
7310 }
7311 }
7312 }
7313
7314 // Now look forwards
7315 final int N = mHistory.size();
7316 jt = startTask;
7317 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007318 ActivityRecord r = (ActivityRecord)mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007319 if (r.task != jt) {
7320 if (affinity.equals(jt.affinity)) {
7321 return j;
7322 }
7323 jt = r.task;
7324 }
7325 }
7326
7327 // Might it be at the top?
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007328 if (affinity.equals(((ActivityRecord)mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 return N-1;
7330 }
7331
7332 return -1;
7333 }
7334
7335 /**
7336 * Perform a reset of the given task, if needed as part of launching it.
7337 * Returns the new HistoryRecord at the top of the task.
7338 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007339 private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
7340 ActivityRecord newActivity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341 boolean forceReset = (newActivity.info.flags
7342 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
7343 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
7344 if ((newActivity.info.flags
7345 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
7346 forceReset = true;
7347 }
7348 }
7349
7350 final TaskRecord task = taskTop.task;
7351
7352 // We are going to move through the history list so that we can look
7353 // at each activity 'target' with 'below' either the interesting
7354 // activity immediately below it in the stack or null.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007355 ActivityRecord target = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007356 int targetI = 0;
7357 int taskTopI = -1;
7358 int replyChainEnd = -1;
7359 int lastReparentPos = -1;
7360 for (int i=mHistory.size()-1; i>=-1; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007361 ActivityRecord below = i >= 0 ? (ActivityRecord)mHistory.get(i) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007362
7363 if (below != null && below.finishing) {
7364 continue;
7365 }
7366 if (target == null) {
7367 target = below;
7368 targetI = i;
7369 // If we were in the middle of a reply chain before this
7370 // task, it doesn't appear like the root of the chain wants
7371 // anything interesting, so drop it.
7372 replyChainEnd = -1;
7373 continue;
7374 }
7375
7376 final int flags = target.info.flags;
7377
7378 final boolean finishOnTaskLaunch =
7379 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7380 final boolean allowTaskReparenting =
7381 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7382
7383 if (target.task == task) {
7384 // We are inside of the task being reset... we'll either
7385 // finish this activity, push it out for another task,
7386 // or leave it as-is. We only do this
7387 // for activities that are not the root of the task (since
7388 // if we finish the root, we may no longer have the task!).
7389 if (taskTopI < 0) {
7390 taskTopI = targetI;
7391 }
7392 if (below != null && below.task == task) {
7393 final boolean clearWhenTaskReset =
7394 (target.intent.getFlags()
7395 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007396 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007397 // If this activity is sending a reply to a previous
7398 // activity, we can't do anything with it now until
7399 // we reach the start of the reply chain.
7400 // XXX note that we are assuming the result is always
7401 // to the previous activity, which is almost always
7402 // the case but we really shouldn't count on.
7403 if (replyChainEnd < 0) {
7404 replyChainEnd = targetI;
7405 }
Ed Heyl73798232009-03-24 21:32:21 -07007406 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007407 && target.taskAffinity != null
7408 && !target.taskAffinity.equals(task.affinity)) {
7409 // If this activity has an affinity for another
7410 // task, then we need to move it out of here. We will
7411 // move it as far out of the way as possible, to the
7412 // bottom of the activity stack. This also keeps it
7413 // correctly ordered with any activities we previously
7414 // moved.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007415 ActivityRecord p = (ActivityRecord)mHistory.get(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007416 if (target.taskAffinity != null
7417 && target.taskAffinity.equals(p.task.affinity)) {
7418 // If the activity currently at the bottom has the
7419 // same task affinity as the one we are moving,
7420 // then merge it into the same task.
7421 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007422 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 + " out to bottom task " + p.task);
7424 } else {
7425 mCurTask++;
7426 if (mCurTask <= 0) {
7427 mCurTask = 1;
7428 }
7429 target.task = new TaskRecord(mCurTask, target.info, null,
7430 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7431 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007432 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007433 + " out to new task " + target.task);
7434 }
7435 mWindowManager.setAppGroupId(target, task.taskId);
7436 if (replyChainEnd < 0) {
7437 replyChainEnd = targetI;
7438 }
7439 int dstPos = 0;
7440 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007441 p = (ActivityRecord)mHistory.get(srcPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007442 if (p.finishing) {
7443 continue;
7444 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007445 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 + " out to target's task " + target.task);
7447 task.numActivities--;
7448 p.task = target.task;
7449 target.task.numActivities++;
7450 mHistory.remove(srcPos);
7451 mHistory.add(dstPos, p);
7452 mWindowManager.moveAppToken(dstPos, p);
7453 mWindowManager.setAppGroupId(p, p.task.taskId);
7454 dstPos++;
7455 if (VALIDATE_TOKENS) {
7456 mWindowManager.validateAppTokens(mHistory);
7457 }
7458 i++;
7459 }
7460 if (taskTop == p) {
7461 taskTop = below;
7462 }
7463 if (taskTopI == replyChainEnd) {
7464 taskTopI = -1;
7465 }
7466 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007467 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007468 } else if (forceReset || finishOnTaskLaunch
7469 || clearWhenTaskReset) {
7470 // If the activity should just be removed -- either
7471 // because it asks for it, or the task should be
7472 // cleared -- then finish it and anything that is
7473 // part of its reply chain.
7474 if (clearWhenTaskReset) {
7475 // In this case, we want to finish this activity
7476 // and everything above it, so be sneaky and pretend
7477 // like these are all in the reply chain.
7478 replyChainEnd = targetI+1;
7479 while (replyChainEnd < mHistory.size() &&
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007480 ((ActivityRecord)mHistory.get(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 replyChainEnd)).task == task) {
7482 replyChainEnd++;
7483 }
7484 replyChainEnd--;
7485 } else if (replyChainEnd < 0) {
7486 replyChainEnd = targetI;
7487 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007488 ActivityRecord p = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007489 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007490 p = (ActivityRecord)mHistory.get(srcPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007491 if (p.finishing) {
7492 continue;
7493 }
7494 if (finishActivityLocked(p, srcPos,
7495 Activity.RESULT_CANCELED, null, "reset")) {
7496 replyChainEnd--;
7497 srcPos--;
7498 }
7499 }
7500 if (taskTop == p) {
7501 taskTop = below;
7502 }
7503 if (taskTopI == replyChainEnd) {
7504 taskTopI = -1;
7505 }
7506 replyChainEnd = -1;
7507 } else {
7508 // If we were in the middle of a chain, well the
7509 // activity that started it all doesn't want anything
7510 // special, so leave it all as-is.
7511 replyChainEnd = -1;
7512 }
7513 } else {
7514 // Reached the bottom of the task -- any reply chain
7515 // should be left as-is.
7516 replyChainEnd = -1;
7517 }
7518
7519 } else if (target.resultTo != null) {
7520 // If this activity is sending a reply to a previous
7521 // activity, we can't do anything with it now until
7522 // we reach the start of the reply chain.
7523 // XXX note that we are assuming the result is always
7524 // to the previous activity, which is almost always
7525 // the case but we really shouldn't count on.
7526 if (replyChainEnd < 0) {
7527 replyChainEnd = targetI;
7528 }
7529
7530 } else if (taskTopI >= 0 && allowTaskReparenting
7531 && task.affinity != null
7532 && task.affinity.equals(target.taskAffinity)) {
7533 // We are inside of another task... if this activity has
7534 // an affinity for our task, then either remove it if we are
7535 // clearing or move it over to our task. Note that
7536 // we currently punt on the case where we are resetting a
7537 // task that is not at the top but who has activities above
7538 // with an affinity to it... this is really not a normal
7539 // case, and we will need to later pull that task to the front
7540 // and usually at that point we will do the reset and pick
7541 // up those remaining activities. (This only happens if
7542 // someone starts an activity in a new task from an activity
7543 // in a task that is not currently on top.)
7544 if (forceReset || finishOnTaskLaunch) {
7545 if (replyChainEnd < 0) {
7546 replyChainEnd = targetI;
7547 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007548 ActivityRecord p = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007550 p = (ActivityRecord)mHistory.get(srcPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 if (p.finishing) {
7552 continue;
7553 }
7554 if (finishActivityLocked(p, srcPos,
7555 Activity.RESULT_CANCELED, null, "reset")) {
7556 taskTopI--;
7557 lastReparentPos--;
7558 replyChainEnd--;
7559 srcPos--;
7560 }
7561 }
7562 replyChainEnd = -1;
7563 } else {
7564 if (replyChainEnd < 0) {
7565 replyChainEnd = targetI;
7566 }
7567 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007568 ActivityRecord p = (ActivityRecord)mHistory.get(srcPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569 if (p.finishing) {
7570 continue;
7571 }
7572 if (lastReparentPos < 0) {
7573 lastReparentPos = taskTopI;
7574 taskTop = p;
7575 } else {
7576 lastReparentPos--;
7577 }
7578 mHistory.remove(srcPos);
7579 p.task.numActivities--;
7580 p.task = task;
7581 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007582 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 + " in to resetting task " + task);
7584 task.numActivities++;
7585 mWindowManager.moveAppToken(lastReparentPos, p);
7586 mWindowManager.setAppGroupId(p, p.task.taskId);
7587 if (VALIDATE_TOKENS) {
7588 mWindowManager.validateAppTokens(mHistory);
7589 }
7590 }
7591 replyChainEnd = -1;
7592
7593 // Now we've moved it in to place... but what if this is
7594 // a singleTop activity and we have put it on top of another
7595 // instance of the same activity? Then we drop the instance
7596 // below so it remains singleTop.
7597 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7598 for (int j=lastReparentPos-1; j>=0; j--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007599 ActivityRecord p = (ActivityRecord)mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007600 if (p.finishing) {
7601 continue;
7602 }
7603 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7604 if (finishActivityLocked(p, j,
7605 Activity.RESULT_CANCELED, null, "replace")) {
7606 taskTopI--;
7607 lastReparentPos--;
7608 }
7609 }
7610 }
7611 }
7612 }
7613 }
7614
7615 target = below;
7616 targetI = i;
7617 }
7618
7619 return taskTop;
7620 }
7621
7622 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007623 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007624 */
7625 public void moveTaskToFront(int task) {
7626 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7627 "moveTaskToFront()");
7628
7629 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007630 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7631 Binder.getCallingUid(), "Task to front")) {
7632 return;
7633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007634 final long origId = Binder.clearCallingIdentity();
7635 try {
7636 int N = mRecentTasks.size();
7637 for (int i=0; i<N; i++) {
7638 TaskRecord tr = mRecentTasks.get(i);
7639 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007640 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007641 return;
7642 }
7643 }
7644 for (int i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007645 ActivityRecord hr = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007646 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007647 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007648 return;
7649 }
7650 }
7651 } finally {
7652 Binder.restoreCallingIdentity(origId);
7653 }
7654 }
7655 }
7656
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007657 private final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007658 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007659
7660 final int task = tr.taskId;
7661 int top = mHistory.size()-1;
7662
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007663 if (top < 0 || ((ActivityRecord)mHistory.get(top)).task.taskId == task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007664 // nothing to do!
7665 return;
7666 }
7667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007668 ArrayList moved = new ArrayList();
7669
7670 // Applying the affinities may have removed entries from the history,
7671 // so get the size again.
7672 top = mHistory.size()-1;
7673 int pos = top;
7674
7675 // Shift all activities with this task up to the top
7676 // of the stack, keeping them in the same internal order.
7677 while (pos >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007678 ActivityRecord r = (ActivityRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007679 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007680 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7681 boolean first = true;
7682 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007683 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007684 mHistory.remove(pos);
7685 mHistory.add(top, r);
7686 moved.add(0, r);
7687 top--;
7688 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007689 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690 first = false;
7691 }
7692 }
7693 pos--;
7694 }
7695
Joe Onorato8a9b2202010-02-26 18:56:32 -08007696 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007697 "Prepare to front transition: task=" + tr);
7698 if (reason != null &&
7699 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7700 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007701 ActivityRecord r = topRunningActivityLocked(null);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007702 if (r != null) {
7703 mNoAnimActivities.add(r);
7704 }
7705 } else {
7706 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7707 }
7708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007709 mWindowManager.moveAppTokensToTop(moved);
7710 if (VALIDATE_TOKENS) {
7711 mWindowManager.validateAppTokens(mHistory);
7712 }
7713
Josh Bartel7f208742010-02-25 11:01:44 -06007714 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007715 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007716 }
7717
Josh Bartel7f208742010-02-25 11:01:44 -06007718 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007719 resumeTopActivityLocked(null);
7720 }
7721
7722 public void moveTaskToBack(int task) {
7723 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7724 "moveTaskToBack()");
7725
7726 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007727 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7728 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7729 Binder.getCallingUid(), "Task to back")) {
7730 return;
7731 }
7732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007733 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007734 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007735 Binder.restoreCallingIdentity(origId);
7736 }
7737 }
7738
7739 /**
7740 * Moves an activity, and all of the other activities within the same task, to the bottom
7741 * of the history stack. The activity's order within the task is unchanged.
7742 *
7743 * @param token A reference to the activity we wish to move
7744 * @param nonRoot If false then this only works if the activity is the root
7745 * of a task; if true it will work for any activity in a task.
7746 * @return Returns true if the move completed, false if not.
7747 */
7748 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7749 synchronized(this) {
7750 final long origId = Binder.clearCallingIdentity();
7751 int taskId = getTaskForActivityLocked(token, !nonRoot);
7752 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007753 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007754 }
7755 Binder.restoreCallingIdentity(origId);
7756 }
7757 return false;
7758 }
7759
7760 /**
7761 * Worker method for rearranging history stack. Implements the function of moving all
7762 * activities for a specific task (gathering them if disjoint) into a single group at the
7763 * bottom of the stack.
7764 *
7765 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7766 * to premeptively cancel the move.
7767 *
7768 * @param task The taskId to collect and move to the bottom.
7769 * @return Returns true if the move completed, false if not.
7770 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007771 private final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007772 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007773
7774 // If we have a watcher, preflight the move before committing to it. First check
7775 // for *other* available tasks, but if none are available, then try again allowing the
7776 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007777 if (mController != null) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007778 ActivityRecord next = topRunningActivityLocked(null, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007779 if (next == null) {
7780 next = topRunningActivityLocked(null, 0);
7781 }
7782 if (next != null) {
7783 // ask watcher if this is allowed
7784 boolean moveOK = true;
7785 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007786 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007787 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007788 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007789 }
7790 if (!moveOK) {
7791 return false;
7792 }
7793 }
7794 }
7795
7796 ArrayList moved = new ArrayList();
7797
Joe Onorato8a9b2202010-02-26 18:56:32 -08007798 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800
7801 final int N = mHistory.size();
7802 int bottom = 0;
7803 int pos = 0;
7804
7805 // Shift all activities with this task down to the bottom
7806 // of the stack, keeping them in the same internal order.
7807 while (pos < N) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007808 ActivityRecord r = (ActivityRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007809 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7811 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007812 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007813 mHistory.remove(pos);
7814 mHistory.add(bottom, r);
7815 moved.add(r);
7816 bottom++;
7817 }
7818 pos++;
7819 }
7820
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007821 if (reason != null &&
7822 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7823 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007824 ActivityRecord r = topRunningActivityLocked(null);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007825 if (r != null) {
7826 mNoAnimActivities.add(r);
7827 }
7828 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007829 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007830 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007831 mWindowManager.moveAppTokensToBottom(moved);
7832 if (VALIDATE_TOKENS) {
7833 mWindowManager.validateAppTokens(mHistory);
7834 }
7835
Josh Bartel7f208742010-02-25 11:01:44 -06007836 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007837 return true;
7838 }
7839
7840 public void moveTaskBackwards(int task) {
7841 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7842 "moveTaskBackwards()");
7843
7844 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007845 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7846 Binder.getCallingUid(), "Task backwards")) {
7847 return;
7848 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007849 final long origId = Binder.clearCallingIdentity();
7850 moveTaskBackwardsLocked(task);
7851 Binder.restoreCallingIdentity(origId);
7852 }
7853 }
7854
7855 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007856 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007857 }
7858
7859 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7860 synchronized(this) {
7861 return getTaskForActivityLocked(token, onlyRoot);
7862 }
7863 }
7864
7865 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7866 final int N = mHistory.size();
7867 TaskRecord lastTask = null;
7868 for (int i=0; i<N; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007869 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007870 if (r == token) {
7871 if (!onlyRoot || lastTask != r.task) {
7872 return r.task.taskId;
7873 }
7874 return -1;
7875 }
7876 lastTask = r.task;
7877 }
7878
7879 return -1;
7880 }
7881
7882 /**
7883 * Returns the top activity in any existing task matching the given
7884 * Intent. Returns null if no such task is found.
7885 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007886 private ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007887 ComponentName cls = intent.getComponent();
7888 if (info.targetActivity != null) {
7889 cls = new ComponentName(info.packageName, info.targetActivity);
7890 }
7891
7892 TaskRecord cp = null;
7893
7894 final int N = mHistory.size();
7895 for (int i=(N-1); i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007896 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007897 if (!r.finishing && r.task != cp
7898 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7899 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007900 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901 // + "/aff=" + r.task.affinity + " to new cls="
7902 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7903 if (r.task.affinity != null) {
7904 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007905 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007906 return r;
7907 }
7908 } else if (r.task.intent != null
7909 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007910 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007912 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007913 return r;
7914 } else if (r.task.affinityIntent != null
7915 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007916 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007917 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007918 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007919 return r;
7920 }
7921 }
7922 }
7923
7924 return null;
7925 }
7926
7927 /**
7928 * Returns the first activity (starting from the top of the stack) that
7929 * is the same as the given activity. Returns null if no such activity
7930 * is found.
7931 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007932 private ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007933 ComponentName cls = intent.getComponent();
7934 if (info.targetActivity != null) {
7935 cls = new ComponentName(info.packageName, info.targetActivity);
7936 }
7937
7938 final int N = mHistory.size();
7939 for (int i=(N-1); i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007940 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007941 if (!r.finishing) {
7942 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007943 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007944 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007945 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946 return r;
7947 }
7948 }
7949 }
7950
7951 return null;
7952 }
7953
7954 public void finishOtherInstances(IBinder token, ComponentName className) {
7955 synchronized(this) {
7956 final long origId = Binder.clearCallingIdentity();
7957
7958 int N = mHistory.size();
7959 TaskRecord lastTask = null;
7960 for (int i=0; i<N; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007961 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007962 if (r.realActivity.equals(className)
7963 && r != token && lastTask != r.task) {
7964 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7965 null, "others")) {
7966 i--;
7967 N--;
7968 }
7969 }
7970 lastTask = r.task;
7971 }
7972
7973 Binder.restoreCallingIdentity(origId);
7974 }
7975 }
7976
7977 // =========================================================
7978 // THUMBNAILS
7979 // =========================================================
7980
7981 public void reportThumbnail(IBinder token,
7982 Bitmap thumbnail, CharSequence description) {
7983 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7984 final long origId = Binder.clearCallingIdentity();
7985 sendPendingThumbnail(null, token, thumbnail, description, true);
7986 Binder.restoreCallingIdentity(origId);
7987 }
7988
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007989 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007990 Bitmap thumbnail, CharSequence description, boolean always) {
7991 TaskRecord task = null;
7992 ArrayList receivers = null;
7993
7994 //System.out.println("Send pending thumbnail: " + r);
7995
7996 synchronized(this) {
7997 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007998 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007999 if (index < 0) {
8000 return;
8001 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008002 r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008003 }
8004 if (thumbnail == null) {
8005 thumbnail = r.thumbnail;
8006 description = r.description;
8007 }
8008 if (thumbnail == null && !always) {
8009 // If there is no thumbnail, and this entry is not actually
8010 // going away, then abort for now and pick up the next
8011 // thumbnail we get.
8012 return;
8013 }
8014 task = r.task;
8015
8016 int N = mPendingThumbnails.size();
8017 int i=0;
8018 while (i<N) {
8019 PendingThumbnailsRecord pr =
8020 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
8021 //System.out.println("Looking in " + pr.pendingRecords);
8022 if (pr.pendingRecords.remove(r)) {
8023 if (receivers == null) {
8024 receivers = new ArrayList();
8025 }
8026 receivers.add(pr);
8027 if (pr.pendingRecords.size() == 0) {
8028 pr.finished = true;
8029 mPendingThumbnails.remove(i);
8030 N--;
8031 continue;
8032 }
8033 }
8034 i++;
8035 }
8036 }
8037
8038 if (receivers != null) {
8039 final int N = receivers.size();
8040 for (int i=0; i<N; i++) {
8041 try {
8042 PendingThumbnailsRecord pr =
8043 (PendingThumbnailsRecord)receivers.get(i);
8044 pr.receiver.newThumbnail(
8045 task != null ? task.taskId : -1, thumbnail, description);
8046 if (pr.finished) {
8047 pr.receiver.finished();
8048 }
8049 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008050 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008051 }
8052 }
8053 }
8054 }
8055
8056 // =========================================================
8057 // CONTENT PROVIDERS
8058 // =========================================================
8059
8060 private final List generateApplicationProvidersLocked(ProcessRecord app) {
8061 List providers = null;
8062 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008063 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008064 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008065 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 } catch (RemoteException ex) {
8067 }
8068 if (providers != null) {
8069 final int N = providers.size();
8070 for (int i=0; i<N; i++) {
8071 ProviderInfo cpi =
8072 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008073 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008074 if (cpr == null) {
8075 cpr = new ContentProviderRecord(cpi, app.info);
8076 mProvidersByClass.put(cpi.name, cpr);
8077 }
8078 app.pubProviders.put(cpi.name, cpr);
8079 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008080 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 }
8082 }
8083 return providers;
8084 }
8085
8086 private final String checkContentProviderPermissionLocked(
8087 ProviderInfo cpi, ProcessRecord r, int mode) {
8088 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
8089 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
8090 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
8091 cpi.exported ? -1 : cpi.applicationInfo.uid)
8092 == PackageManager.PERMISSION_GRANTED
8093 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8094 return null;
8095 }
8096 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
8097 cpi.exported ? -1 : cpi.applicationInfo.uid)
8098 == PackageManager.PERMISSION_GRANTED) {
8099 return null;
8100 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07008101
8102 PathPermission[] pps = cpi.pathPermissions;
8103 if (pps != null) {
8104 int i = pps.length;
8105 while (i > 0) {
8106 i--;
8107 PathPermission pp = pps[i];
8108 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
8109 cpi.exported ? -1 : cpi.applicationInfo.uid)
8110 == PackageManager.PERMISSION_GRANTED
8111 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8112 return null;
8113 }
8114 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
8115 cpi.exported ? -1 : cpi.applicationInfo.uid)
8116 == PackageManager.PERMISSION_GRANTED) {
8117 return null;
8118 }
8119 }
8120 }
8121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008122 String msg = "Permission Denial: opening provider " + cpi.name
8123 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
8124 + ", uid=" + callingUid + ") requires "
8125 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008126 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008127 return msg;
8128 }
8129
8130 private final ContentProviderHolder getContentProviderImpl(
8131 IApplicationThread caller, String name) {
8132 ContentProviderRecord cpr;
8133 ProviderInfo cpi = null;
8134
8135 synchronized(this) {
8136 ProcessRecord r = null;
8137 if (caller != null) {
8138 r = getRecordForAppLocked(caller);
8139 if (r == null) {
8140 throw new SecurityException(
8141 "Unable to find app for caller " + caller
8142 + " (pid=" + Binder.getCallingPid()
8143 + ") when getting content provider " + name);
8144 }
8145 }
8146
8147 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07008148 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008149 if (cpr != null) {
8150 cpi = cpr.info;
8151 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8152 return new ContentProviderHolder(cpi,
8153 cpi.readPermission != null
8154 ? cpi.readPermission : cpi.writePermission);
8155 }
8156
8157 if (r != null && cpr.canRunHere(r)) {
8158 // This provider has been published or is in the process
8159 // of being published... but it is also allowed to run
8160 // in the caller's process, so don't make a connection
8161 // and just let the caller instantiate its own instance.
8162 if (cpr.provider != null) {
8163 // don't give caller the provider object, it needs
8164 // to make its own.
8165 cpr = new ContentProviderRecord(cpr);
8166 }
8167 return cpr;
8168 }
8169
8170 final long origId = Binder.clearCallingIdentity();
8171
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008172 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 // return it right away.
8174 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008175 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008176 "Adding provider requested by "
8177 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008178 + cpr.info.processName);
8179 Integer cnt = r.conProviders.get(cpr);
8180 if (cnt == null) {
8181 r.conProviders.put(cpr, new Integer(1));
8182 } else {
8183 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008186 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
8187 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07008188 // make sure to count it as being accessed and thus
8189 // back up on the LRU list. This is good because
8190 // content providers are often expensive to start.
8191 updateLruProcessLocked(cpr.app, false, true);
8192 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07008193 } else {
8194 cpr.externals++;
8195 }
8196
8197 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008198 updateOomAdjLocked(cpr.app);
8199 }
8200
8201 Binder.restoreCallingIdentity(origId);
8202
8203 } else {
8204 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008205 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008206 resolveContentProvider(name,
8207 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008208 } catch (RemoteException ex) {
8209 }
8210 if (cpi == null) {
8211 return null;
8212 }
8213
8214 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8215 return new ContentProviderHolder(cpi,
8216 cpi.readPermission != null
8217 ? cpi.readPermission : cpi.writePermission);
8218 }
8219
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008220 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
8221 && !cpi.processName.equals("system")) {
8222 // If this content provider does not run in the system
8223 // process, and the system is not yet ready to run other
8224 // processes, then fail fast instead of hanging.
8225 throw new IllegalArgumentException(
8226 "Attempt to launch content provider before system ready");
8227 }
8228
Dianne Hackborn860755f2010-06-03 18:47:52 -07008229 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008230 final boolean firstClass = cpr == null;
8231 if (firstClass) {
8232 try {
8233 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008234 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008235 getApplicationInfo(
8236 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008237 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008238 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008239 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008240 + cpi.name);
8241 return null;
8242 }
8243 cpr = new ContentProviderRecord(cpi, ai);
8244 } catch (RemoteException ex) {
8245 // pm is in same process, this will never happen.
8246 }
8247 }
8248
8249 if (r != null && cpr.canRunHere(r)) {
8250 // If this is a multiprocess provider, then just return its
8251 // info and allow the caller to instantiate it. Only do
8252 // this if the provider is the same user as the caller's
8253 // process, or can run as root (so can be in any process).
8254 return cpr;
8255 }
8256
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008257 if (DEBUG_PROVIDER) {
8258 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08008259 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008260 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008261 }
8262
8263 // This is single process, and our app is now connecting to it.
8264 // See if we are already in the process of launching this
8265 // provider.
8266 final int N = mLaunchingProviders.size();
8267 int i;
8268 for (i=0; i<N; i++) {
8269 if (mLaunchingProviders.get(i) == cpr) {
8270 break;
8271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008272 }
8273
8274 // If the provider is not already being launched, then get it
8275 // started.
8276 if (i >= N) {
8277 final long origId = Binder.clearCallingIdentity();
8278 ProcessRecord proc = startProcessLocked(cpi.processName,
8279 cpr.appInfo, false, 0, "content provider",
8280 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008281 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008282 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008283 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284 + cpi.applicationInfo.packageName + "/"
8285 + cpi.applicationInfo.uid + " for provider "
8286 + name + ": process is bad");
8287 return null;
8288 }
8289 cpr.launchingApp = proc;
8290 mLaunchingProviders.add(cpr);
8291 Binder.restoreCallingIdentity(origId);
8292 }
8293
8294 // Make sure the provider is published (the same provider class
8295 // may be published under multiple names).
8296 if (firstClass) {
8297 mProvidersByClass.put(cpi.name, cpr);
8298 }
8299 mProvidersByName.put(name, cpr);
8300
8301 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008302 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008303 "Adding provider requested by "
8304 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008305 + cpr.info.processName);
8306 Integer cnt = r.conProviders.get(cpr);
8307 if (cnt == null) {
8308 r.conProviders.put(cpr, new Integer(1));
8309 } else {
8310 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008312 cpr.clients.add(r);
8313 } else {
8314 cpr.externals++;
8315 }
8316 }
8317 }
8318
8319 // Wait for the provider to be published...
8320 synchronized (cpr) {
8321 while (cpr.provider == null) {
8322 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008323 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008324 + cpi.applicationInfo.packageName + "/"
8325 + cpi.applicationInfo.uid + " for provider "
8326 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008327 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 cpi.applicationInfo.packageName,
8329 cpi.applicationInfo.uid, name);
8330 return null;
8331 }
8332 try {
8333 cpr.wait();
8334 } catch (InterruptedException ex) {
8335 }
8336 }
8337 }
8338 return cpr;
8339 }
8340
8341 public final ContentProviderHolder getContentProvider(
8342 IApplicationThread caller, String name) {
8343 if (caller == null) {
8344 String msg = "null IApplicationThread when getting content provider "
8345 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008346 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008347 throw new SecurityException(msg);
8348 }
8349
8350 return getContentProviderImpl(caller, name);
8351 }
8352
8353 private ContentProviderHolder getContentProviderExternal(String name) {
8354 return getContentProviderImpl(null, name);
8355 }
8356
8357 /**
8358 * Drop a content provider from a ProcessRecord's bookkeeping
8359 * @param cpr
8360 */
8361 public void removeContentProvider(IApplicationThread caller, String name) {
8362 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008363 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008364 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008365 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008366 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008367 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008368 return;
8369 }
8370 final ProcessRecord r = getRecordForAppLocked(caller);
8371 if (r == null) {
8372 throw new SecurityException(
8373 "Unable to find app for caller " + caller +
8374 " when removing content provider " + name);
8375 }
8376 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008377 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008378 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008379 + r.info.processName + " from process "
8380 + localCpr.appInfo.processName);
8381 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008382 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008383 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008384 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 return;
8386 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008387 Integer cnt = r.conProviders.get(localCpr);
8388 if (cnt == null || cnt.intValue() <= 1) {
8389 localCpr.clients.remove(r);
8390 r.conProviders.remove(localCpr);
8391 } else {
8392 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008394 }
8395 updateOomAdjLocked();
8396 }
8397 }
8398
8399 private void removeContentProviderExternal(String name) {
8400 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008401 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008402 if(cpr == null) {
8403 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008404 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008405 return;
8406 }
8407
8408 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008409 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008410 localCpr.externals--;
8411 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008412 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008413 }
8414 updateOomAdjLocked();
8415 }
8416 }
8417
8418 public final void publishContentProviders(IApplicationThread caller,
8419 List<ContentProviderHolder> providers) {
8420 if (providers == null) {
8421 return;
8422 }
8423
8424 synchronized(this) {
8425 final ProcessRecord r = getRecordForAppLocked(caller);
8426 if (r == null) {
8427 throw new SecurityException(
8428 "Unable to find app for caller " + caller
8429 + " (pid=" + Binder.getCallingPid()
8430 + ") when publishing content providers");
8431 }
8432
8433 final long origId = Binder.clearCallingIdentity();
8434
8435 final int N = providers.size();
8436 for (int i=0; i<N; i++) {
8437 ContentProviderHolder src = providers.get(i);
8438 if (src == null || src.info == null || src.provider == null) {
8439 continue;
8440 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07008441 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008442 if (dst != null) {
8443 mProvidersByClass.put(dst.info.name, dst);
8444 String names[] = dst.info.authority.split(";");
8445 for (int j = 0; j < names.length; j++) {
8446 mProvidersByName.put(names[j], dst);
8447 }
8448
8449 int NL = mLaunchingProviders.size();
8450 int j;
8451 for (j=0; j<NL; j++) {
8452 if (mLaunchingProviders.get(j) == dst) {
8453 mLaunchingProviders.remove(j);
8454 j--;
8455 NL--;
8456 }
8457 }
8458 synchronized (dst) {
8459 dst.provider = src.provider;
8460 dst.app = r;
8461 dst.notifyAll();
8462 }
8463 updateOomAdjLocked(r);
8464 }
8465 }
8466
8467 Binder.restoreCallingIdentity(origId);
8468 }
8469 }
8470
8471 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008472 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008473 synchronized (mSelf) {
8474 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8475 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008476 if (providers != null) {
8477 for (int i=providers.size()-1; i>=0; i--) {
8478 ProviderInfo pi = (ProviderInfo)providers.get(i);
8479 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8480 Slog.w(TAG, "Not installing system proc provider " + pi.name
8481 + ": not system .apk");
8482 providers.remove(i);
8483 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008484 }
8485 }
8486 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008487 if (providers != null) {
8488 mSystemThread.installSystemProviders(providers);
8489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008490 }
8491
8492 // =========================================================
8493 // GLOBAL MANAGEMENT
8494 // =========================================================
8495
8496 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8497 ApplicationInfo info, String customProcess) {
8498 String proc = customProcess != null ? customProcess : info.processName;
8499 BatteryStatsImpl.Uid.Proc ps = null;
8500 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8501 synchronized (stats) {
8502 ps = stats.getProcessStatsLocked(info.uid, proc);
8503 }
8504 return new ProcessRecord(ps, thread, info, proc);
8505 }
8506
8507 final ProcessRecord addAppLocked(ApplicationInfo info) {
8508 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8509
8510 if (app == null) {
8511 app = newProcessRecordLocked(null, info, null);
8512 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008513 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008514 }
8515
8516 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8517 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8518 app.persistent = true;
8519 app.maxAdj = CORE_SERVER_ADJ;
8520 }
8521 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8522 mPersistentStartingProcesses.add(app);
8523 startProcessLocked(app, "added application", app.processName);
8524 }
8525
8526 return app;
8527 }
8528
8529 public void unhandledBack() {
8530 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8531 "unhandledBack()");
8532
8533 synchronized(this) {
8534 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008535 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008536 TAG, "Performing unhandledBack(): stack size = " + count);
8537 if (count > 1) {
8538 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008539 finishActivityLocked((ActivityRecord)mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8541 Binder.restoreCallingIdentity(origId);
8542 }
8543 }
8544 }
8545
8546 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8547 String name = uri.getAuthority();
8548 ContentProviderHolder cph = getContentProviderExternal(name);
8549 ParcelFileDescriptor pfd = null;
8550 if (cph != null) {
8551 // We record the binder invoker's uid in thread-local storage before
8552 // going to the content provider to open the file. Later, in the code
8553 // that handles all permissions checks, we look for this uid and use
8554 // that rather than the Activity Manager's own uid. The effect is that
8555 // we do the check against the caller's permissions even though it looks
8556 // to the content provider like the Activity Manager itself is making
8557 // the request.
8558 sCallerIdentity.set(new Identity(
8559 Binder.getCallingPid(), Binder.getCallingUid()));
8560 try {
8561 pfd = cph.provider.openFile(uri, "r");
8562 } catch (FileNotFoundException e) {
8563 // do nothing; pfd will be returned null
8564 } finally {
8565 // Ensure that whatever happens, we clean up the identity state
8566 sCallerIdentity.remove();
8567 }
8568
8569 // We've got the fd now, so we're done with the provider.
8570 removeContentProviderExternal(name);
8571 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008572 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008573 }
8574 return pfd;
8575 }
8576
8577 public void goingToSleep() {
8578 synchronized(this) {
8579 mSleeping = true;
8580 mWindowManager.setEventDispatching(false);
8581
8582 if (mResumedActivity != null) {
8583 pauseIfSleepingLocked();
8584 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008585 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008586 }
8587 }
8588 }
8589
Dianne Hackborn55280a92009-05-07 15:53:46 -07008590 public boolean shutdown(int timeout) {
8591 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8592 != PackageManager.PERMISSION_GRANTED) {
8593 throw new SecurityException("Requires permission "
8594 + android.Manifest.permission.SHUTDOWN);
8595 }
8596
8597 boolean timedout = false;
8598
8599 synchronized(this) {
8600 mShuttingDown = true;
8601 mWindowManager.setEventDispatching(false);
8602
8603 if (mResumedActivity != null) {
8604 pauseIfSleepingLocked();
8605 final long endTime = System.currentTimeMillis() + timeout;
8606 while (mResumedActivity != null || mPausingActivity != null) {
8607 long delay = endTime - System.currentTimeMillis();
8608 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008609 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008610 timedout = true;
8611 break;
8612 }
8613 try {
8614 this.wait();
8615 } catch (InterruptedException e) {
8616 }
8617 }
8618 }
8619 }
8620
8621 mUsageStatsService.shutdown();
8622 mBatteryStatsService.shutdown();
8623
8624 return timedout;
8625 }
8626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008627 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008628 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008629 if (!mGoingToSleep.isHeld()) {
8630 mGoingToSleep.acquire();
8631 if (mLaunchingActivity.isHeld()) {
8632 mLaunchingActivity.release();
8633 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8634 }
8635 }
8636
8637 // If we are not currently pausing an activity, get the current
8638 // one to pause. If we are pausing one, we will just let that stuff
8639 // run and release the wake lock when all done.
8640 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008641 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8642 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643 startPausingLocked(false, true);
8644 }
8645 }
8646 }
8647
8648 public void wakingUp() {
8649 synchronized(this) {
8650 if (mGoingToSleep.isHeld()) {
8651 mGoingToSleep.release();
8652 }
8653 mWindowManager.setEventDispatching(true);
8654 mSleeping = false;
8655 resumeTopActivityLocked(null);
8656 }
8657 }
8658
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008659 public void stopAppSwitches() {
8660 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8661 != PackageManager.PERMISSION_GRANTED) {
8662 throw new SecurityException("Requires permission "
8663 + android.Manifest.permission.STOP_APP_SWITCHES);
8664 }
8665
8666 synchronized(this) {
8667 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8668 + APP_SWITCH_DELAY_TIME;
8669 mDidAppSwitch = false;
8670 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8671 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8672 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8673 }
8674 }
8675
8676 public void resumeAppSwitches() {
8677 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8678 != PackageManager.PERMISSION_GRANTED) {
8679 throw new SecurityException("Requires permission "
8680 + android.Manifest.permission.STOP_APP_SWITCHES);
8681 }
8682
8683 synchronized(this) {
8684 // Note that we don't execute any pending app switches... we will
8685 // let those wait until either the timeout, or the next start
8686 // activity request.
8687 mAppSwitchesAllowedTime = 0;
8688 }
8689 }
8690
8691 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8692 String name) {
8693 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8694 return true;
8695 }
8696
8697 final int perm = checkComponentPermission(
8698 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8699 callingUid, -1);
8700 if (perm == PackageManager.PERMISSION_GRANTED) {
8701 return true;
8702 }
8703
Joe Onorato8a9b2202010-02-26 18:56:32 -08008704 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008705 return false;
8706 }
8707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008708 public void setDebugApp(String packageName, boolean waitForDebugger,
8709 boolean persistent) {
8710 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8711 "setDebugApp()");
8712
8713 // Note that this is not really thread safe if there are multiple
8714 // callers into it at the same time, but that's not a situation we
8715 // care about.
8716 if (persistent) {
8717 final ContentResolver resolver = mContext.getContentResolver();
8718 Settings.System.putString(
8719 resolver, Settings.System.DEBUG_APP,
8720 packageName);
8721 Settings.System.putInt(
8722 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8723 waitForDebugger ? 1 : 0);
8724 }
8725
8726 synchronized (this) {
8727 if (!persistent) {
8728 mOrigDebugApp = mDebugApp;
8729 mOrigWaitForDebugger = mWaitForDebugger;
8730 }
8731 mDebugApp = packageName;
8732 mWaitForDebugger = waitForDebugger;
8733 mDebugTransient = !persistent;
8734 if (packageName != null) {
8735 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008736 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008737 Binder.restoreCallingIdentity(origId);
8738 }
8739 }
8740 }
8741
8742 public void setAlwaysFinish(boolean enabled) {
8743 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8744 "setAlwaysFinish()");
8745
8746 Settings.System.putInt(
8747 mContext.getContentResolver(),
8748 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8749
8750 synchronized (this) {
8751 mAlwaysFinishActivities = enabled;
8752 }
8753 }
8754
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008755 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008756 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008757 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008758 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008759 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008760 }
8761 }
8762
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008763 public boolean isUserAMonkey() {
8764 // For now the fact that there is a controller implies
8765 // we have a monkey.
8766 synchronized (this) {
8767 return mController != null;
8768 }
8769 }
8770
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008771 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008772 synchronized (this) {
8773 mWatchers.register(watcher);
8774 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008775 }
8776
8777 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008778 synchronized (this) {
8779 mWatchers.unregister(watcher);
8780 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008781 }
8782
Daniel Sandler69a48172010-06-23 16:29:36 -04008783 public void setImmersive(IBinder token, boolean immersive) {
8784 synchronized(this) {
8785 int index = (token != null) ? indexOfTokenLocked(token) : -1;
8786 if (index < 0) {
8787 throw new IllegalArgumentException();
8788 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008789 ActivityRecord r = (ActivityRecord)mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04008790 r.immersive = immersive;
8791 }
8792 }
8793
8794 public boolean isImmersive(IBinder token) {
8795 synchronized (this) {
8796 int index = (token != null) ? indexOfTokenLocked(token) : -1;
8797 if (index < 0) {
8798 throw new IllegalArgumentException();
8799 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008800 ActivityRecord r = (ActivityRecord)mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04008801 return r.immersive;
8802 }
8803 }
8804
8805 public boolean isTopActivityImmersive() {
8806 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008807 ActivityRecord r = topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04008808 return (r != null) ? r.immersive : false;
8809 }
8810 }
8811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 public final void enterSafeMode() {
8813 synchronized(this) {
8814 // It only makes sense to do this before the system is ready
8815 // and started launching other packages.
8816 if (!mSystemReady) {
8817 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008818 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819 } catch (RemoteException e) {
8820 }
8821
8822 View v = LayoutInflater.from(mContext).inflate(
8823 com.android.internal.R.layout.safe_mode, null);
8824 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8825 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8826 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8827 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8828 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8829 lp.format = v.getBackground().getOpacity();
8830 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8831 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8832 ((WindowManager)mContext.getSystemService(
8833 Context.WINDOW_SERVICE)).addView(v, lp);
8834 }
8835 }
8836 }
8837
8838 public void noteWakeupAlarm(IIntentSender sender) {
8839 if (!(sender instanceof PendingIntentRecord)) {
8840 return;
8841 }
8842 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8843 synchronized (stats) {
8844 if (mBatteryStatsService.isOnBattery()) {
8845 mBatteryStatsService.enforceCallingPermission();
8846 PendingIntentRecord rec = (PendingIntentRecord)sender;
8847 int MY_UID = Binder.getCallingUid();
8848 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8849 BatteryStatsImpl.Uid.Pkg pkg =
8850 stats.getPackageStatsLocked(uid, rec.key.packageName);
8851 pkg.incWakeupsLocked();
8852 }
8853 }
8854 }
8855
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008856 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008857 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008858 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008859 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008860 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008861 // XXX Note: don't acquire main activity lock here, because the window
8862 // manager calls in with its locks held.
8863
8864 boolean killed = false;
8865 synchronized (mPidsSelfLocked) {
8866 int[] types = new int[pids.length];
8867 int worstType = 0;
8868 for (int i=0; i<pids.length; i++) {
8869 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8870 if (proc != null) {
8871 int type = proc.setAdj;
8872 types[i] = type;
8873 if (type > worstType) {
8874 worstType = type;
8875 }
8876 }
8877 }
8878
8879 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8880 // then constrain it so we will kill all hidden procs.
8881 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8882 worstType = HIDDEN_APP_MIN_ADJ;
8883 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008884 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008885 for (int i=0; i<pids.length; i++) {
8886 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8887 if (proc == null) {
8888 continue;
8889 }
8890 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008891 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008892 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008893 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8894 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008895 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008896 proc.killedBackground = true;
8897 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008898 }
8899 }
8900 }
8901 return killed;
8902 }
8903
8904 public void reportPss(IApplicationThread caller, int pss) {
8905 Watchdog.PssRequestor req;
8906 String name;
8907 ProcessRecord callerApp;
8908 synchronized (this) {
8909 if (caller == null) {
8910 return;
8911 }
8912 callerApp = getRecordForAppLocked(caller);
8913 if (callerApp == null) {
8914 return;
8915 }
8916 callerApp.lastPss = pss;
8917 req = callerApp;
8918 name = callerApp.processName;
8919 }
8920 Watchdog.getInstance().reportPss(req, name, pss);
8921 if (!callerApp.persistent) {
8922 removeRequestedPss(callerApp);
8923 }
8924 }
8925
8926 public void requestPss(Runnable completeCallback) {
8927 ArrayList<ProcessRecord> procs;
8928 synchronized (this) {
8929 mRequestPssCallback = completeCallback;
8930 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008931 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8932 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008933 if (!proc.persistent) {
8934 mRequestPssList.add(proc);
8935 }
8936 }
8937 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8938 }
8939
8940 int oldPri = Process.getThreadPriority(Process.myTid());
8941 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8942 for (int i=procs.size()-1; i>=0; i--) {
8943 ProcessRecord proc = procs.get(i);
8944 proc.lastPss = 0;
8945 proc.requestPss();
8946 }
8947 Process.setThreadPriority(oldPri);
8948 }
8949
8950 void removeRequestedPss(ProcessRecord proc) {
8951 Runnable callback = null;
8952 synchronized (this) {
8953 if (mRequestPssList.remove(proc)) {
8954 if (mRequestPssList.size() == 0) {
8955 callback = mRequestPssCallback;
8956 mRequestPssCallback = null;
8957 }
8958 }
8959 }
8960
8961 if (callback != null) {
8962 callback.run();
8963 }
8964 }
8965
8966 public void collectPss(Watchdog.PssStats stats) {
8967 stats.mEmptyPss = 0;
8968 stats.mEmptyCount = 0;
8969 stats.mBackgroundPss = 0;
8970 stats.mBackgroundCount = 0;
8971 stats.mServicePss = 0;
8972 stats.mServiceCount = 0;
8973 stats.mVisiblePss = 0;
8974 stats.mVisibleCount = 0;
8975 stats.mForegroundPss = 0;
8976 stats.mForegroundCount = 0;
8977 stats.mNoPssCount = 0;
8978 synchronized (this) {
8979 int i;
8980 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8981 ? mProcDeaths.length : stats.mProcDeaths.length;
8982 int aggr = 0;
8983 for (i=0; i<NPD; i++) {
8984 aggr += mProcDeaths[i];
8985 stats.mProcDeaths[i] = aggr;
8986 }
8987 while (i<stats.mProcDeaths.length) {
8988 stats.mProcDeaths[i] = 0;
8989 i++;
8990 }
8991
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008992 for (i=mLruProcesses.size()-1; i>=0; i--) {
8993 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008994 if (proc.persistent) {
8995 continue;
8996 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008997 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998 if (proc.lastPss == 0) {
8999 stats.mNoPssCount++;
9000 continue;
9001 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009002 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
9003 if (proc.empty) {
9004 stats.mEmptyPss += proc.lastPss;
9005 stats.mEmptyCount++;
9006 } else {
9007 stats.mBackgroundPss += proc.lastPss;
9008 stats.mBackgroundCount++;
9009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009010 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
9011 stats.mVisiblePss += proc.lastPss;
9012 stats.mVisibleCount++;
9013 } else {
9014 stats.mForegroundPss += proc.lastPss;
9015 stats.mForegroundCount++;
9016 }
9017 }
9018 }
9019 }
9020
9021 public final void startRunning(String pkg, String cls, String action,
9022 String data) {
9023 synchronized(this) {
9024 if (mStartRunning) {
9025 return;
9026 }
9027 mStartRunning = true;
9028 mTopComponent = pkg != null && cls != null
9029 ? new ComponentName(pkg, cls) : null;
9030 mTopAction = action != null ? action : Intent.ACTION_MAIN;
9031 mTopData = data;
9032 if (!mSystemReady) {
9033 return;
9034 }
9035 }
9036
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009037 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009038 }
9039
9040 private void retrieveSettings() {
9041 final ContentResolver resolver = mContext.getContentResolver();
9042 String debugApp = Settings.System.getString(
9043 resolver, Settings.System.DEBUG_APP);
9044 boolean waitForDebugger = Settings.System.getInt(
9045 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
9046 boolean alwaysFinishActivities = Settings.System.getInt(
9047 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
9048
9049 Configuration configuration = new Configuration();
9050 Settings.System.getConfiguration(resolver, configuration);
9051
9052 synchronized (this) {
9053 mDebugApp = mOrigDebugApp = debugApp;
9054 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
9055 mAlwaysFinishActivities = alwaysFinishActivities;
9056 // This happens before any activities are started, so we can
9057 // change mConfiguration in-place.
9058 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009059 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009060 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009061 }
9062 }
9063
9064 public boolean testIsSystemReady() {
9065 // no need to synchronize(this) just to read & return the value
9066 return mSystemReady;
9067 }
9068
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009069 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009070 // In the simulator, startRunning will never have been called, which
9071 // normally sets a few crucial variables. Do it here instead.
9072 if (!Process.supportsProcesses()) {
9073 mStartRunning = true;
9074 mTopAction = Intent.ACTION_MAIN;
9075 }
9076
9077 synchronized(this) {
9078 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009079 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009080 return;
9081 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009082
9083 // Check to see if there are any update receivers to run.
9084 if (!mDidUpdate) {
9085 if (mWaitingUpdate) {
9086 return;
9087 }
9088 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
9089 List<ResolveInfo> ris = null;
9090 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009091 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009092 intent, null, 0);
9093 } catch (RemoteException e) {
9094 }
9095 if (ris != null) {
9096 for (int i=ris.size()-1; i>=0; i--) {
9097 if ((ris.get(i).activityInfo.applicationInfo.flags
9098 &ApplicationInfo.FLAG_SYSTEM) == 0) {
9099 ris.remove(i);
9100 }
9101 }
9102 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
9103 for (int i=0; i<ris.size(); i++) {
9104 ActivityInfo ai = ris.get(i).activityInfo;
9105 intent.setComponent(new ComponentName(ai.packageName, ai.name));
9106 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08009107 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009108 finisher = new IIntentReceiver.Stub() {
9109 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07009110 String data, Bundle extras, boolean ordered,
9111 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009112 throws RemoteException {
9113 synchronized (ActivityManagerService.this) {
9114 mDidUpdate = true;
9115 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009116 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009117 }
9118 };
9119 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009120 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009121 broadcastIntentLocked(null, null, intent, null, finisher,
9122 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08009123 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009124 mWaitingUpdate = true;
9125 }
9126 }
9127 }
9128 if (mWaitingUpdate) {
9129 return;
9130 }
9131 mDidUpdate = true;
9132 }
9133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009134 mSystemReady = true;
9135 if (!mStartRunning) {
9136 return;
9137 }
9138 }
9139
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009140 ArrayList<ProcessRecord> procsToKill = null;
9141 synchronized(mPidsSelfLocked) {
9142 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
9143 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
9144 if (!isAllowedWhileBooting(proc.info)){
9145 if (procsToKill == null) {
9146 procsToKill = new ArrayList<ProcessRecord>();
9147 }
9148 procsToKill.add(proc);
9149 }
9150 }
9151 }
9152
9153 if (procsToKill != null) {
9154 synchronized(this) {
9155 for (int i=procsToKill.size()-1; i>=0; i--) {
9156 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009157 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009158 removeProcessLocked(proc, true);
9159 }
9160 }
9161 }
9162
Joe Onorato8a9b2202010-02-26 18:56:32 -08009163 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009164 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009165 SystemClock.uptimeMillis());
9166
9167 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009168 // Make sure we have no pre-ready processes sitting around.
9169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009170 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
9171 ResolveInfo ri = mContext.getPackageManager()
9172 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07009173 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009174 CharSequence errorMsg = null;
9175 if (ri != null) {
9176 ActivityInfo ai = ri.activityInfo;
9177 ApplicationInfo app = ai.applicationInfo;
9178 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
9179 mTopAction = Intent.ACTION_FACTORY_TEST;
9180 mTopData = null;
9181 mTopComponent = new ComponentName(app.packageName,
9182 ai.name);
9183 } else {
9184 errorMsg = mContext.getResources().getText(
9185 com.android.internal.R.string.factorytest_not_system);
9186 }
9187 } else {
9188 errorMsg = mContext.getResources().getText(
9189 com.android.internal.R.string.factorytest_no_action);
9190 }
9191 if (errorMsg != null) {
9192 mTopAction = null;
9193 mTopData = null;
9194 mTopComponent = null;
9195 Message msg = Message.obtain();
9196 msg.what = SHOW_FACTORY_ERROR_MSG;
9197 msg.getData().putCharSequence("msg", errorMsg);
9198 mHandler.sendMessage(msg);
9199 }
9200 }
9201 }
9202
9203 retrieveSettings();
9204
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009205 if (goingCallback != null) goingCallback.run();
9206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009207 synchronized (this) {
9208 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
9209 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009210 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009211 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009212 if (apps != null) {
9213 int N = apps.size();
9214 int i;
9215 for (i=0; i<N; i++) {
9216 ApplicationInfo info
9217 = (ApplicationInfo)apps.get(i);
9218 if (info != null &&
9219 !info.packageName.equals("android")) {
9220 addAppLocked(info);
9221 }
9222 }
9223 }
9224 } catch (RemoteException ex) {
9225 // pm is in same process, this will never happen.
9226 }
9227 }
9228
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009229 // Start up initial activity.
9230 mBooting = true;
9231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009232 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009233 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009234 Message msg = Message.obtain();
9235 msg.what = SHOW_UID_ERROR_MSG;
9236 mHandler.sendMessage(msg);
9237 }
9238 } catch (RemoteException e) {
9239 }
9240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009241 resumeTopActivityLocked(null);
9242 }
9243 }
9244
Dan Egnorb7f03672009-12-09 16:22:32 -08009245 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009246 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009247 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009248 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009249 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 startAppProblemLocked(app);
9251 app.stopFreezingAllLocked();
9252 return handleAppCrashLocked(app);
9253 }
9254
Dan Egnorb7f03672009-12-09 16:22:32 -08009255 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009256 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009257 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009258 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009259 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
9260 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009261 startAppProblemLocked(app);
9262 app.stopFreezingAllLocked();
9263 }
9264
9265 /**
9266 * Generate a process error record, suitable for attachment to a ProcessRecord.
9267 *
9268 * @param app The ProcessRecord in which the error occurred.
9269 * @param condition Crashing, Application Not Responding, etc. Values are defined in
9270 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08009271 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009272 * @param shortMsg Short message describing the crash.
9273 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08009274 * @param stackTrace Full crash stack trace, may be null.
9275 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009276 * @return Returns a fully-formed AppErrorStateInfo record.
9277 */
9278 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009279 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009280 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08009281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009282 report.condition = condition;
9283 report.processName = app.processName;
9284 report.pid = app.pid;
9285 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08009286 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009287 report.shortMsg = shortMsg;
9288 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08009289 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009290
9291 return report;
9292 }
9293
Dan Egnor42471dd2010-01-07 17:25:22 -08009294 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 synchronized (this) {
9296 app.crashing = false;
9297 app.crashingReport = null;
9298 app.notResponding = false;
9299 app.notRespondingReport = null;
9300 if (app.anrDialog == fromDialog) {
9301 app.anrDialog = null;
9302 }
9303 if (app.waitDialog == fromDialog) {
9304 app.waitDialog = null;
9305 }
9306 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009307 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07009308 Slog.i(ActivityManagerService.TAG, "Killing "
9309 + app.processName + " (pid=" + app.pid + "): user's request");
9310 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
9311 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 Process.killProcess(app.pid);
9313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009314 }
9315 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009316
Dan Egnorb7f03672009-12-09 16:22:32 -08009317 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009318 long now = SystemClock.uptimeMillis();
9319
9320 Long crashTime = mProcessCrashTimes.get(app.info.processName,
9321 app.info.uid);
9322 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
9323 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08009324 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009325 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009326 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009327 app.info.processName, app.info.uid);
9328 killServicesLocked(app, false);
9329 for (int i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009330 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009331 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009332 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009333 + r.intent.getComponent().flattenToShortString());
9334 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
9335 }
9336 }
9337 if (!app.persistent) {
9338 // We don't want to start this process again until the user
9339 // explicitly does so... but for persistent process, we really
9340 // need to keep it running. If a persistent process is actually
9341 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08009342 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009343 app.info.processName);
9344 mBadProcesses.put(app.info.processName, app.info.uid, now);
9345 app.bad = true;
9346 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
9347 app.removed = true;
9348 removeProcessLocked(app, false);
9349 return false;
9350 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009351 } else {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009352 ActivityRecord r = topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009353 if (r.app == app) {
9354 // If the top running activity is from this crashing
9355 // process, then terminate it to avoid getting in a loop.
9356 Slog.w(TAG, " Force finishing activity "
9357 + r.intent.getComponent().flattenToShortString());
9358 int index = indexOfTokenLocked(r);
9359 finishActivityLocked(r, index,
9360 Activity.RESULT_CANCELED, null, "crashed");
9361 // Also terminate an activities below it that aren't yet
9362 // stopped, to avoid a situation where one will get
9363 // re-start our crashing activity once it gets resumed again.
9364 index--;
9365 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009366 r = (ActivityRecord)mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009367 if (r.state == ActivityState.RESUMED
9368 || r.state == ActivityState.PAUSING
9369 || r.state == ActivityState.PAUSED) {
9370 if (!r.isHomeActivity) {
9371 Slog.w(TAG, " Force finishing activity "
9372 + r.intent.getComponent().flattenToShortString());
9373 finishActivityLocked(r, index,
9374 Activity.RESULT_CANCELED, null, "crashed");
9375 }
9376 }
9377 }
9378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009379 }
9380
9381 // Bump up the crash count of any services currently running in the proc.
9382 if (app.services.size() != 0) {
9383 // Any services running in the application need to be placed
9384 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009385 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009386 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009387 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009388 sr.crashCount++;
9389 }
9390 }
9391
9392 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
9393 return true;
9394 }
9395
9396 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009397 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9398 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009399 skipCurrentReceiverLocked(app);
9400 }
9401
9402 void skipCurrentReceiverLocked(ProcessRecord app) {
9403 boolean reschedule = false;
9404 BroadcastRecord r = app.curReceiver;
9405 if (r != null) {
9406 // The current broadcast is waiting for this app's receiver
9407 // to be finished. Looks like that's not going to happen, so
9408 // let the broadcast continue.
9409 logBroadcastReceiverDiscard(r);
9410 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9411 r.resultExtras, r.resultAbort, true);
9412 reschedule = true;
9413 }
9414 r = mPendingBroadcast;
9415 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009416 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009417 "skip & discard pending app " + r);
9418 logBroadcastReceiverDiscard(r);
9419 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9420 r.resultExtras, r.resultAbort, true);
9421 reschedule = true;
9422 }
9423 if (reschedule) {
9424 scheduleBroadcastsLocked();
9425 }
9426 }
9427
Dan Egnor60d87622009-12-16 16:32:58 -08009428 /**
9429 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9430 * The application process will exit immediately after this call returns.
9431 * @param app object of the crashing app, null for the system server
9432 * @param crashInfo describing the exception
9433 */
9434 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9435 ProcessRecord r = findAppProcess(app);
9436
9437 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9438 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009439 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009440 crashInfo.exceptionClassName,
9441 crashInfo.exceptionMessage,
9442 crashInfo.throwFileName,
9443 crashInfo.throwLineNumber);
9444
Dan Egnor42471dd2010-01-07 17:25:22 -08009445 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009446
9447 crashApplication(r, crashInfo);
9448 }
9449
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009450 public void handleApplicationStrictModeViolation(
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009451 IBinder app, int violationMask, ApplicationErrorReport.CrashInfo crashInfo) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009452 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009453
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009454 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009455 Integer stackFingerprint = crashInfo.stackTrace.hashCode();
9456 boolean logIt = true;
9457 synchronized (mAlreadyLoggedViolatedStacks) {
9458 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
9459 logIt = false;
9460 // TODO: sub-sample into EventLog for these, with
9461 // the crashInfo.durationMillis? Then we'd get
9462 // the relative pain numbers, without logging all
9463 // the stack traces repeatedly. We'd want to do
9464 // likewise in the client code, which also does
9465 // dup suppression, before the Binder call.
9466 } else {
9467 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
9468 mAlreadyLoggedViolatedStacks.clear();
9469 }
9470 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
9471 }
9472 }
9473 if (logIt) {
9474 addErrorToDropBox("strictmode", r, null, null, null, null, null, crashInfo);
9475 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009476 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009477
9478 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
9479 AppErrorResult result = new AppErrorResult();
9480 synchronized (this) {
9481 final long origId = Binder.clearCallingIdentity();
9482
9483 Message msg = Message.obtain();
9484 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
9485 HashMap<String, Object> data = new HashMap<String, Object>();
9486 data.put("result", result);
9487 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009488 data.put("violationMask", violationMask);
9489 data.put("crashInfo", crashInfo);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009490 msg.obj = data;
9491 mHandler.sendMessage(msg);
9492
9493 Binder.restoreCallingIdentity(origId);
9494 }
9495 int res = result.get();
9496 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
9497 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009498 }
9499
Dan Egnor60d87622009-12-16 16:32:58 -08009500 /**
9501 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9502 * @param app object of the crashing app, null for the system server
9503 * @param tag reported by the caller
9504 * @param crashInfo describing the context of the error
9505 * @return true if the process should exit immediately (WTF is fatal)
9506 */
9507 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009508 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009509 ProcessRecord r = findAppProcess(app);
9510
9511 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9512 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009513 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009514 tag, crashInfo.exceptionMessage);
9515
Dan Egnor42471dd2010-01-07 17:25:22 -08009516 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009517
Doug Zongker43866e02010-01-07 12:09:54 -08009518 if (Settings.Secure.getInt(mContext.getContentResolver(),
9519 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009520 crashApplication(r, crashInfo);
9521 return true;
9522 } else {
9523 return false;
9524 }
9525 }
9526
9527 /**
9528 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9529 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9530 */
9531 private ProcessRecord findAppProcess(IBinder app) {
9532 if (app == null) {
9533 return null;
9534 }
9535
9536 synchronized (this) {
9537 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9538 final int NA = apps.size();
9539 for (int ia=0; ia<NA; ia++) {
9540 ProcessRecord p = apps.valueAt(ia);
9541 if (p.thread != null && p.thread.asBinder() == app) {
9542 return p;
9543 }
9544 }
9545 }
9546
Joe Onorato8a9b2202010-02-26 18:56:32 -08009547 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009548 return null;
9549 }
9550 }
9551
9552 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009553 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009554 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009555 * @param process which caused the error, null means the system server
9556 * @param activity which triggered the error, null if unknown
9557 * @param parent activity related to the error, null if unknown
9558 * @param subject line related to the error, null if absent
9559 * @param report in long form describing the error, null if absent
9560 * @param logFile to include in the report, null if none
9561 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009562 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009563 public void addErrorToDropBox(String eventType,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009564 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
Dan Egnora455d192010-03-12 08:52:28 -08009565 final String report, final File logFile,
9566 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009567 // NOTE -- this must never acquire the ActivityManagerService lock,
9568 // otherwise the watchdog may be prevented from resetting the system.
9569
Dan Egnora455d192010-03-12 08:52:28 -08009570 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009571 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009572 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009573 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009574 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009575 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009576 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009577 }
9578
Dan Egnora455d192010-03-12 08:52:28 -08009579 final String dropboxTag = prefix + eventType;
9580 final DropBoxManager dbox = (DropBoxManager)
9581 mContext.getSystemService(Context.DROPBOX_SERVICE);
9582
9583 // Exit early if the dropbox isn't configured to accept this report type.
9584 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9585
9586 final StringBuilder sb = new StringBuilder(1024);
9587 if (process == null || process.pid == MY_PID) {
9588 sb.append("Process: system_server\n");
9589 } else {
9590 sb.append("Process: ").append(process.processName).append("\n");
9591 }
9592 if (process != null) {
9593 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009594 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08009595 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9596 for (String pkg : process.pkgList) {
9597 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009598 try {
Dan Egnora455d192010-03-12 08:52:28 -08009599 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9600 if (pi != null) {
9601 sb.append(" v").append(pi.versionCode);
9602 if (pi.versionName != null) {
9603 sb.append(" (").append(pi.versionName).append(")");
9604 }
9605 }
9606 } catch (RemoteException e) {
9607 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009608 }
Dan Egnora455d192010-03-12 08:52:28 -08009609 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009610 }
Dan Egnora455d192010-03-12 08:52:28 -08009611 }
9612 if (activity != null) {
9613 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9614 }
9615 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9616 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9617 }
9618 if (parent != null && parent != activity) {
9619 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9620 }
9621 if (subject != null) {
9622 sb.append("Subject: ").append(subject).append("\n");
9623 }
9624 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Brad Fitzpatrick04b243d2010-06-21 08:01:13 -07009625 if (crashInfo != null && crashInfo.durationMillis != -1) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009626 sb.append("Duration-Millis: ").append(crashInfo.durationMillis).append("\n");
9627 }
Dan Egnora455d192010-03-12 08:52:28 -08009628 sb.append("\n");
9629
9630 // Do the rest in a worker thread to avoid blocking the caller on I/O
9631 // (After this point, we shouldn't access AMS internal data structures.)
9632 Thread worker = new Thread("Error dump: " + dropboxTag) {
9633 @Override
9634 public void run() {
9635 if (report != null) {
9636 sb.append(report);
9637 }
9638 if (logFile != null) {
9639 try {
9640 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9641 } catch (IOException e) {
9642 Slog.e(TAG, "Error reading " + logFile, e);
9643 }
9644 }
9645 if (crashInfo != null && crashInfo.stackTrace != null) {
9646 sb.append(crashInfo.stackTrace);
9647 }
9648
9649 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9650 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9651 if (lines > 0) {
9652 sb.append("\n");
9653
9654 // Merge several logcat streams, and take the last N lines
9655 InputStreamReader input = null;
9656 try {
9657 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9658 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9659 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9660
9661 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9662 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9663 input = new InputStreamReader(logcat.getInputStream());
9664
9665 int num;
9666 char[] buf = new char[8192];
9667 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9668 } catch (IOException e) {
9669 Slog.e(TAG, "Error running logcat", e);
9670 } finally {
9671 if (input != null) try { input.close(); } catch (IOException e) {}
9672 }
9673 }
9674
9675 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009676 }
Dan Egnora455d192010-03-12 08:52:28 -08009677 };
9678
9679 if (process == null || process.pid == MY_PID) {
9680 worker.run(); // We may be about to die -- need to run this synchronously
9681 } else {
9682 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009683 }
9684 }
9685
9686 /**
9687 * Bring up the "unexpected error" dialog box for a crashing app.
9688 * Deal with edge cases (intercepts from instrumented applications,
9689 * ActivityController, error intent receivers, that sort of thing).
9690 * @param r the application crashing
9691 * @param crashInfo describing the failure
9692 */
9693 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009694 long timeMillis = System.currentTimeMillis();
9695 String shortMsg = crashInfo.exceptionClassName;
9696 String longMsg = crashInfo.exceptionMessage;
9697 String stackTrace = crashInfo.stackTrace;
9698 if (shortMsg != null && longMsg != null) {
9699 longMsg = shortMsg + ": " + longMsg;
9700 } else if (shortMsg != null) {
9701 longMsg = shortMsg;
9702 }
9703
Dan Egnor60d87622009-12-16 16:32:58 -08009704 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009705 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009706 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009707 try {
9708 String name = r != null ? r.processName : null;
9709 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009710 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009711 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009712 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009713 + " at watcher's request");
9714 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009715 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009716 }
9717 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009718 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009719 }
9720 }
9721
9722 final long origId = Binder.clearCallingIdentity();
9723
9724 // If this process is running instrumentation, finish it.
9725 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009726 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009727 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009728 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9729 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009730 Bundle info = new Bundle();
9731 info.putString("shortMsg", shortMsg);
9732 info.putString("longMsg", longMsg);
9733 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9734 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009735 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009736 }
9737
Dan Egnor60d87622009-12-16 16:32:58 -08009738 // If we can't identify the process or it's already exceeded its crash quota,
9739 // quit right away without showing a crash dialog.
9740 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009741 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009742 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009743 }
9744
9745 Message msg = Message.obtain();
9746 msg.what = SHOW_ERROR_MSG;
9747 HashMap data = new HashMap();
9748 data.put("result", result);
9749 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009750 msg.obj = data;
9751 mHandler.sendMessage(msg);
9752
9753 Binder.restoreCallingIdentity(origId);
9754 }
9755
9756 int res = result.get();
9757
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009758 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009759 synchronized (this) {
9760 if (r != null) {
9761 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9762 SystemClock.uptimeMillis());
9763 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009764 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009765 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009766 }
9767 }
9768
9769 if (appErrorIntent != null) {
9770 try {
9771 mContext.startActivity(appErrorIntent);
9772 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009773 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009776 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009777
9778 Intent createAppErrorIntentLocked(ProcessRecord r,
9779 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9780 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009781 if (report == null) {
9782 return null;
9783 }
9784 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9785 result.setComponent(r.errorReportReceiver);
9786 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9787 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9788 return result;
9789 }
9790
Dan Egnorb7f03672009-12-09 16:22:32 -08009791 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9792 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009793 if (r.errorReportReceiver == null) {
9794 return null;
9795 }
9796
9797 if (!r.crashing && !r.notResponding) {
9798 return null;
9799 }
9800
Dan Egnorb7f03672009-12-09 16:22:32 -08009801 ApplicationErrorReport report = new ApplicationErrorReport();
9802 report.packageName = r.info.packageName;
9803 report.installerPackageName = r.errorReportReceiver.getPackageName();
9804 report.processName = r.processName;
9805 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009806 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009807
Dan Egnorb7f03672009-12-09 16:22:32 -08009808 if (r.crashing) {
9809 report.type = ApplicationErrorReport.TYPE_CRASH;
9810 report.crashInfo = crashInfo;
9811 } else if (r.notResponding) {
9812 report.type = ApplicationErrorReport.TYPE_ANR;
9813 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009814
Dan Egnorb7f03672009-12-09 16:22:32 -08009815 report.anrInfo.activity = r.notRespondingReport.tag;
9816 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9817 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009818 }
9819
Dan Egnorb7f03672009-12-09 16:22:32 -08009820 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009821 }
9822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009823 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9824 // assume our apps are happy - lazy create the list
9825 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9826
9827 synchronized (this) {
9828
9829 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009830 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9831 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9833 // This one's in trouble, so we'll generate a report for it
9834 // crashes are higher priority (in case there's a crash *and* an anr)
9835 ActivityManager.ProcessErrorStateInfo report = null;
9836 if (app.crashing) {
9837 report = app.crashingReport;
9838 } else if (app.notResponding) {
9839 report = app.notRespondingReport;
9840 }
9841
9842 if (report != null) {
9843 if (errList == null) {
9844 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9845 }
9846 errList.add(report);
9847 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009848 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009849 " crashing = " + app.crashing +
9850 " notResponding = " + app.notResponding);
9851 }
9852 }
9853 }
9854 }
9855
9856 return errList;
9857 }
9858
9859 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9860 // Lazy instantiation of list
9861 List<ActivityManager.RunningAppProcessInfo> runList = null;
9862 synchronized (this) {
9863 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009864 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9865 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009866 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9867 // Generate process state info for running application
9868 ActivityManager.RunningAppProcessInfo currApp =
9869 new ActivityManager.RunningAppProcessInfo(app.processName,
9870 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009871 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07009872 if (mHeavyWeightProcess == app) {
9873 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
9874 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009875 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009876 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009877 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9878 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9879 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009880 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9881 } else if (adj >= HOME_APP_ADJ) {
9882 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9883 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009884 } else if (adj >= SECONDARY_SERVER_ADJ) {
9885 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07009886 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
9887 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
9888 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
9889 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009890 } else if (adj >= VISIBLE_APP_ADJ) {
9891 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9892 } else {
9893 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9894 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009895 currApp.importanceReasonCode = app.adjTypeCode;
9896 if (app.adjSource instanceof ProcessRecord) {
9897 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009898 } else if (app.adjSource instanceof ActivityRecord) {
9899 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009900 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9901 }
9902 if (app.adjTarget instanceof ComponentName) {
9903 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9904 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009905 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009906 // + " lru=" + currApp.lru);
9907 if (runList == null) {
9908 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9909 }
9910 runList.add(currApp);
9911 }
9912 }
9913 }
9914 return runList;
9915 }
9916
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009917 public List<ApplicationInfo> getRunningExternalApplications() {
9918 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9919 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9920 if (runningApps != null && runningApps.size() > 0) {
9921 Set<String> extList = new HashSet<String>();
9922 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9923 if (app.pkgList != null) {
9924 for (String pkg : app.pkgList) {
9925 extList.add(pkg);
9926 }
9927 }
9928 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009929 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009930 for (String pkg : extList) {
9931 try {
9932 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9933 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9934 retList.add(info);
9935 }
9936 } catch (RemoteException e) {
9937 }
9938 }
9939 }
9940 return retList;
9941 }
9942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 @Override
9944 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009945 if (checkCallingPermission(android.Manifest.permission.DUMP)
9946 != PackageManager.PERMISSION_GRANTED) {
9947 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9948 + Binder.getCallingPid()
9949 + ", uid=" + Binder.getCallingUid()
9950 + " without permission "
9951 + android.Manifest.permission.DUMP);
9952 return;
9953 }
9954
9955 boolean dumpAll = false;
9956
9957 int opti = 0;
9958 while (opti < args.length) {
9959 String opt = args[opti];
9960 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9961 break;
9962 }
9963 opti++;
9964 if ("-a".equals(opt)) {
9965 dumpAll = true;
9966 } else if ("-h".equals(opt)) {
9967 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009968 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009969 pw.println(" cmd may be one of:");
9970 pw.println(" activities: activity stack state");
9971 pw.println(" broadcasts: broadcast state");
9972 pw.println(" intents: pending intent state");
9973 pw.println(" processes: process state");
9974 pw.println(" providers: content provider state");
9975 pw.println(" services: service state");
9976 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009977 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009978 } else {
9979 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009980 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009981 }
9982
9983 // Is the caller requesting to dump a particular piece of data?
9984 if (opti < args.length) {
9985 String cmd = args[opti];
9986 opti++;
9987 if ("activities".equals(cmd) || "a".equals(cmd)) {
9988 synchronized (this) {
9989 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009990 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009991 return;
9992 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9993 synchronized (this) {
9994 dumpBroadcastsLocked(fd, pw, args, opti, true);
9995 }
9996 return;
9997 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9998 synchronized (this) {
9999 dumpPendingIntentsLocked(fd, pw, args, opti, true);
10000 }
10001 return;
10002 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
10003 synchronized (this) {
10004 dumpProcessesLocked(fd, pw, args, opti, true);
10005 }
10006 return;
10007 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
10008 synchronized (this) {
10009 dumpProvidersLocked(fd, pw, args, opti, true);
10010 }
10011 return;
10012 } else if ("service".equals(cmd)) {
10013 dumpService(fd, pw, args, opti, true);
10014 return;
10015 } else if ("services".equals(cmd) || "s".equals(cmd)) {
10016 synchronized (this) {
10017 dumpServicesLocked(fd, pw, args, opti, true);
10018 }
10019 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010020 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010021 }
10022
10023 // No piece of data specified, dump everything.
10024 synchronized (this) {
10025 boolean needSep;
10026 if (dumpAll) {
10027 pw.println("Providers in Current Activity Manager State:");
10028 }
10029 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
10030 if (needSep) {
10031 pw.println(" ");
10032 }
10033 if (dumpAll) {
10034 pw.println("-------------------------------------------------------------------------------");
10035 pw.println("Broadcasts in Current Activity Manager State:");
10036 }
10037 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
10038 if (needSep) {
10039 pw.println(" ");
10040 }
10041 if (dumpAll) {
10042 pw.println("-------------------------------------------------------------------------------");
10043 pw.println("Services in Current Activity Manager State:");
10044 }
10045 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
10046 if (needSep) {
10047 pw.println(" ");
10048 }
10049 if (dumpAll) {
10050 pw.println("-------------------------------------------------------------------------------");
10051 pw.println("PendingIntents in Current Activity Manager State:");
10052 }
10053 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
10054 if (needSep) {
10055 pw.println(" ");
10056 }
10057 if (dumpAll) {
10058 pw.println("-------------------------------------------------------------------------------");
10059 pw.println("Activities in Current Activity Manager State:");
10060 }
10061 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
10062 if (needSep) {
10063 pw.println(" ");
10064 }
10065 if (dumpAll) {
10066 pw.println("-------------------------------------------------------------------------------");
10067 pw.println("Processes in Current Activity Manager State:");
10068 }
10069 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
10070 }
10071 }
10072
10073 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10074 int opti, boolean dumpAll, boolean needHeader) {
10075 if (needHeader) {
10076 pw.println(" Activity stack:");
10077 }
10078 dumpHistoryList(pw, mHistory, " ", "Hist", true);
10079 pw.println(" ");
10080 pw.println(" Running activities (most recent first):");
10081 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
10082 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010083 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010084 pw.println(" Activities waiting for another to become visible:");
10085 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
10086 }
10087 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010088 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010089 pw.println(" Activities waiting to stop:");
10090 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
10091 }
10092 if (mFinishingActivities.size() > 0) {
10093 pw.println(" ");
10094 pw.println(" Activities waiting to finish:");
10095 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
10096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010097
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010098 pw.println(" ");
10099 pw.println(" mPausingActivity: " + mPausingActivity);
10100 pw.println(" mResumedActivity: " + mResumedActivity);
10101 pw.println(" mFocusedActivity: " + mFocusedActivity);
10102 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010103
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010104 if (dumpAll && mRecentTasks.size() > 0) {
10105 pw.println(" ");
10106 pw.println("Recent tasks in Current Activity Manager State:");
10107
10108 final int N = mRecentTasks.size();
10109 for (int i=0; i<N; i++) {
10110 TaskRecord tr = mRecentTasks.get(i);
10111 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
10112 pw.println(tr);
10113 mRecentTasks.get(i).dump(pw, " ");
10114 }
10115 }
10116
10117 pw.println(" ");
10118 pw.println(" mCurTask: " + mCurTask);
10119
10120 return true;
10121 }
10122
10123 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10124 int opti, boolean dumpAll) {
10125 boolean needSep = false;
10126 int numPers = 0;
10127
10128 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010129 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
10130 final int NA = procs.size();
10131 for (int ia=0; ia<NA; ia++) {
10132 if (!needSep) {
10133 pw.println(" All known processes:");
10134 needSep = true;
10135 }
10136 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010137 pw.print(r.persistent ? " *PERS*" : " *APP*");
10138 pw.print(" UID "); pw.print(procs.keyAt(ia));
10139 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 r.dump(pw, " ");
10141 if (r.persistent) {
10142 numPers++;
10143 }
10144 }
10145 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010146 }
10147
10148 if (mLruProcesses.size() > 0) {
10149 if (needSep) pw.println(" ");
10150 needSep = true;
10151 pw.println(" Running processes (most recent first):");
10152 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010153 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010154 needSep = true;
10155 }
10156
10157 synchronized (mPidsSelfLocked) {
10158 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010159 if (needSep) pw.println(" ");
10160 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010161 pw.println(" PID mappings:");
10162 for (int i=0; i<mPidsSelfLocked.size(); i++) {
10163 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
10164 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010165 }
10166 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010167 }
10168
10169 if (mForegroundProcesses.size() > 0) {
10170 if (needSep) pw.println(" ");
10171 needSep = true;
10172 pw.println(" Foreground Processes:");
10173 for (int i=0; i<mForegroundProcesses.size(); i++) {
10174 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
10175 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010176 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010177 }
10178
10179 if (mPersistentStartingProcesses.size() > 0) {
10180 if (needSep) pw.println(" ");
10181 needSep = true;
10182 pw.println(" Persisent processes that are starting:");
10183 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
10184 "Starting Norm", "Restarting PERS", false);
10185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010186
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010187 if (mStartingProcesses.size() > 0) {
10188 if (needSep) pw.println(" ");
10189 needSep = true;
10190 pw.println(" Processes that are starting:");
10191 dumpProcessList(pw, this, mStartingProcesses, " ",
10192 "Starting Norm", "Starting PERS", false);
10193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010194
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010195 if (mRemovedProcesses.size() > 0) {
10196 if (needSep) pw.println(" ");
10197 needSep = true;
10198 pw.println(" Processes that are being removed:");
10199 dumpProcessList(pw, this, mRemovedProcesses, " ",
10200 "Removed Norm", "Removed PERS", false);
10201 }
10202
10203 if (mProcessesOnHold.size() > 0) {
10204 if (needSep) pw.println(" ");
10205 needSep = true;
10206 pw.println(" Processes that are on old until the system is ready:");
10207 dumpProcessList(pw, this, mProcessesOnHold, " ",
10208 "OnHold Norm", "OnHold PERS", false);
10209 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010210
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010211 if (mProcessesToGc.size() > 0) {
10212 if (needSep) pw.println(" ");
10213 needSep = true;
10214 pw.println(" Processes that are waiting to GC:");
10215 long now = SystemClock.uptimeMillis();
10216 for (int i=0; i<mProcessesToGc.size(); i++) {
10217 ProcessRecord proc = mProcessesToGc.get(i);
10218 pw.print(" Process "); pw.println(proc);
10219 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
10220 pw.print(", last gced=");
10221 pw.print(now-proc.lastRequestedGc);
10222 pw.print(" ms ago, last lowMem=");
10223 pw.print(now-proc.lastLowMemory);
10224 pw.println(" ms ago");
10225
10226 }
10227 }
10228
10229 if (mProcessCrashTimes.getMap().size() > 0) {
10230 if (needSep) pw.println(" ");
10231 needSep = true;
10232 pw.println(" Time since processes crashed:");
10233 long now = SystemClock.uptimeMillis();
10234 for (Map.Entry<String, SparseArray<Long>> procs
10235 : mProcessCrashTimes.getMap().entrySet()) {
10236 SparseArray<Long> uids = procs.getValue();
10237 final int N = uids.size();
10238 for (int i=0; i<N; i++) {
10239 pw.print(" Process "); pw.print(procs.getKey());
10240 pw.print(" uid "); pw.print(uids.keyAt(i));
10241 pw.print(": last crashed ");
10242 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010243 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010244 }
10245 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010246 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010247
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010248 if (mBadProcesses.getMap().size() > 0) {
10249 if (needSep) pw.println(" ");
10250 needSep = true;
10251 pw.println(" Bad processes:");
10252 for (Map.Entry<String, SparseArray<Long>> procs
10253 : mBadProcesses.getMap().entrySet()) {
10254 SparseArray<Long> uids = procs.getValue();
10255 final int N = uids.size();
10256 for (int i=0; i<N; i++) {
10257 pw.print(" Bad process "); pw.print(procs.getKey());
10258 pw.print(" uid "); pw.print(uids.keyAt(i));
10259 pw.print(": crashed at time ");
10260 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010261 }
10262 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010264
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010265 pw.println(" ");
10266 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010267 if (mHeavyWeightProcess != null) {
10268 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
10269 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010270 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -070010271 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010272 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
10273 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
10274 || mOrigWaitForDebugger) {
10275 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
10276 + " mDebugTransient=" + mDebugTransient
10277 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
10278 }
10279 if (mAlwaysFinishActivities || mController != null) {
10280 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
10281 + " mController=" + mController);
10282 }
10283 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010285 pw.println(" mStartRunning=" + mStartRunning
10286 + " mSystemReady=" + mSystemReady
10287 + " mBooting=" + mBooting
10288 + " mBooted=" + mBooted
10289 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010290 pw.println(" mGoingToSleep=" + mGoingToSleep);
10291 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -070010292 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010293 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010294
10295 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010296 }
10297
10298 /**
10299 * There are three ways to call this:
10300 * - no service specified: dump all the services
10301 * - a flattened component name that matched an existing service was specified as the
10302 * first arg: dump that one service
10303 * - the first arg isn't the flattened component name of an existing service:
10304 * dump all services whose component contains the first arg as a substring
10305 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010306 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
10307 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010308 String[] newArgs;
10309 String componentNameString;
10310 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -080010311 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010312 componentNameString = null;
10313 newArgs = EMPTY_STRING_ARRAY;
10314 r = null;
10315 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010316 componentNameString = args[opti];
10317 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010318 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
10319 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010320 newArgs = new String[args.length - opti];
10321 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010322 }
10323
10324 if (r != null) {
10325 dumpService(fd, pw, r, newArgs);
10326 } else {
10327 for (ServiceRecord r1 : mServices.values()) {
10328 if (componentNameString == null
10329 || r1.name.flattenToString().contains(componentNameString)) {
10330 dumpService(fd, pw, r1, newArgs);
10331 }
10332 }
10333 }
10334 }
10335
10336 /**
10337 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
10338 * there is a thread associated with the service.
10339 */
10340 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
10341 pw.println(" Service " + r.name.flattenToString());
10342 if (r.app != null && r.app.thread != null) {
10343 try {
10344 // flush anything that is already in the PrintWriter since the thread is going
10345 // to write to the file descriptor directly
10346 pw.flush();
10347 r.app.thread.dumpService(fd, r, args);
10348 pw.print("\n");
10349 } catch (RemoteException e) {
10350 pw.println("got a RemoteException while dumping the service");
10351 }
10352 }
10353 }
10354
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010355 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10356 int opti, boolean dumpAll) {
10357 boolean needSep = false;
10358
10359 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010360 if (mRegisteredReceivers.size() > 0) {
10361 pw.println(" ");
10362 pw.println(" Registered Receivers:");
10363 Iterator it = mRegisteredReceivers.values().iterator();
10364 while (it.hasNext()) {
10365 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010366 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367 r.dump(pw, " ");
10368 }
10369 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371 pw.println(" ");
10372 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010373 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010374 needSep = true;
10375 }
10376
10377 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
10378 || mPendingBroadcast != null) {
10379 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010380 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010381 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010382 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010383 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10384 pw.println(" Broadcast #" + i + ":");
10385 mParallelBroadcasts.get(i).dump(pw, " ");
10386 }
10387 if (mOrderedBroadcasts.size() > 0) {
10388 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010389 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010390 }
10391 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10392 pw.println(" Serialized Broadcast #" + i + ":");
10393 mOrderedBroadcasts.get(i).dump(pw, " ");
10394 }
10395 pw.println(" ");
10396 pw.println(" Pending broadcast:");
10397 if (mPendingBroadcast != null) {
10398 mPendingBroadcast.dump(pw, " ");
10399 } else {
10400 pw.println(" (null)");
10401 }
10402 needSep = true;
10403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010404
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010405 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010406 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -080010407 pw.println(" Historical broadcasts:");
10408 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
10409 BroadcastRecord r = mBroadcastHistory[i];
10410 if (r == null) {
10411 break;
10412 }
10413 pw.println(" Historical Broadcast #" + i + ":");
10414 r.dump(pw, " ");
10415 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010416 needSep = true;
10417 }
10418
10419 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010420 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010421 pw.println(" Sticky broadcasts:");
10422 StringBuilder sb = new StringBuilder(128);
10423 for (Map.Entry<String, ArrayList<Intent>> ent
10424 : mStickyBroadcasts.entrySet()) {
10425 pw.print(" * Sticky action "); pw.print(ent.getKey());
10426 pw.println(":");
10427 ArrayList<Intent> intents = ent.getValue();
10428 final int N = intents.size();
10429 for (int i=0; i<N; i++) {
10430 sb.setLength(0);
10431 sb.append(" Intent: ");
10432 intents.get(i).toShortString(sb, true, false);
10433 pw.println(sb.toString());
10434 Bundle bundle = intents.get(i).getExtras();
10435 if (bundle != null) {
10436 pw.print(" ");
10437 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010438 }
10439 }
10440 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010441 needSep = true;
10442 }
10443
10444 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010445 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010446 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010447 pw.println(" mHandler:");
10448 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010449 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010450 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010451
10452 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010453 }
10454
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010455 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10456 int opti, boolean dumpAll) {
10457 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010458
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010459 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010460 if (mServices.size() > 0) {
10461 pw.println(" Active services:");
10462 Iterator<ServiceRecord> it = mServices.values().iterator();
10463 while (it.hasNext()) {
10464 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010465 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010466 r.dump(pw, " ");
10467 }
10468 needSep = true;
10469 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010471
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010472 if (mPendingServices.size() > 0) {
10473 if (needSep) pw.println(" ");
10474 pw.println(" Pending services:");
10475 for (int i=0; i<mPendingServices.size(); i++) {
10476 ServiceRecord r = mPendingServices.get(i);
10477 pw.print(" * Pending "); pw.println(r);
10478 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010480 needSep = true;
10481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010482
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010483 if (mRestartingServices.size() > 0) {
10484 if (needSep) pw.println(" ");
10485 pw.println(" Restarting services:");
10486 for (int i=0; i<mRestartingServices.size(); i++) {
10487 ServiceRecord r = mRestartingServices.get(i);
10488 pw.print(" * Restarting "); pw.println(r);
10489 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010490 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010491 needSep = true;
10492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010493
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010494 if (mStoppingServices.size() > 0) {
10495 if (needSep) pw.println(" ");
10496 pw.println(" Stopping services:");
10497 for (int i=0; i<mStoppingServices.size(); i++) {
10498 ServiceRecord r = mStoppingServices.get(i);
10499 pw.print(" * Stopping "); pw.println(r);
10500 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010501 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010502 needSep = true;
10503 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010504
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010505 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010506 if (mServiceConnections.size() > 0) {
10507 if (needSep) pw.println(" ");
10508 pw.println(" Connection bindings to services:");
10509 Iterator<ConnectionRecord> it
10510 = mServiceConnections.values().iterator();
10511 while (it.hasNext()) {
10512 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010513 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010514 r.dump(pw, " ");
10515 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010516 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010517 }
10518 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010519
10520 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010521 }
10522
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010523 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10524 int opti, boolean dumpAll) {
10525 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010526
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010527 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528 if (mProvidersByClass.size() > 0) {
10529 if (needSep) pw.println(" ");
10530 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010531 Iterator<Map.Entry<String, ContentProviderRecord>> it
10532 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010533 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010534 Map.Entry<String, ContentProviderRecord> e = it.next();
10535 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010536 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010537 r.dump(pw, " ");
10538 }
10539 needSep = true;
10540 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010541
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010542 if (mProvidersByName.size() > 0) {
10543 pw.println(" ");
10544 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010545 Iterator<Map.Entry<String, ContentProviderRecord>> it
10546 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010547 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010548 Map.Entry<String, ContentProviderRecord> e = it.next();
10549 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010550 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10551 pw.println(r);
10552 }
10553 needSep = true;
10554 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010555 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010556
10557 if (mLaunchingProviders.size() > 0) {
10558 if (needSep) pw.println(" ");
10559 pw.println(" Launching content providers:");
10560 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10561 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10562 pw.println(mLaunchingProviders.get(i));
10563 }
10564 needSep = true;
10565 }
10566
10567 if (mGrantedUriPermissions.size() > 0) {
10568 pw.println();
10569 pw.println("Granted Uri Permissions:");
10570 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10571 int uid = mGrantedUriPermissions.keyAt(i);
10572 HashMap<Uri, UriPermission> perms
10573 = mGrantedUriPermissions.valueAt(i);
10574 pw.print(" * UID "); pw.print(uid);
10575 pw.println(" holds:");
10576 for (UriPermission perm : perms.values()) {
10577 pw.print(" "); pw.println(perm);
10578 perm.dump(pw, " ");
10579 }
10580 }
10581 needSep = true;
10582 }
10583
10584 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 }
10586
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010587 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10588 int opti, boolean dumpAll) {
10589 boolean needSep = false;
10590
10591 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010592 if (this.mIntentSenderRecords.size() > 0) {
10593 Iterator<WeakReference<PendingIntentRecord>> it
10594 = mIntentSenderRecords.values().iterator();
10595 while (it.hasNext()) {
10596 WeakReference<PendingIntentRecord> ref = it.next();
10597 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010598 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010599 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010600 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010601 rec.dump(pw, " ");
10602 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010603 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010604 }
10605 }
10606 }
10607 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010608
10609 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010610 }
10611
10612 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010613 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 TaskRecord lastTask = null;
10615 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010616 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010617 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010618 if (lastTask != r.task) {
10619 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010620 pw.print(prefix);
10621 pw.print(full ? "* " : " ");
10622 pw.println(lastTask);
10623 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010624 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010625 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010626 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010627 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10628 pw.print(" #"); pw.print(i); pw.print(": ");
10629 pw.println(r);
10630 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010631 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010632 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010633 }
10634 }
10635
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010636 private static String buildOomTag(String prefix, String space, int val, int base) {
10637 if (val == base) {
10638 if (space == null) return prefix;
10639 return prefix + " ";
10640 }
10641 return prefix + "+" + Integer.toString(val-base);
10642 }
10643
10644 private static final int dumpProcessList(PrintWriter pw,
10645 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010646 String prefix, String normalLabel, String persistentLabel,
10647 boolean inclOomAdj) {
10648 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010649 final int N = list.size()-1;
10650 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010651 ProcessRecord r = (ProcessRecord)list.get(i);
10652 if (false) {
10653 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10654 + " #" + i + ":");
10655 r.dump(pw, prefix + " ");
10656 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010657 String oomAdj;
10658 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010659 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010660 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010661 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10662 } else if (r.setAdj >= HOME_APP_ADJ) {
10663 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10664 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10665 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10666 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10667 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010668 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
10669 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
10670 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
10671 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010672 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10673 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10674 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10675 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010676 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010677 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010678 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010679 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010680 } else {
10681 oomAdj = Integer.toString(r.setAdj);
10682 }
10683 String schedGroup;
10684 switch (r.setSchedGroup) {
10685 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10686 schedGroup = "B";
10687 break;
10688 case Process.THREAD_GROUP_DEFAULT:
10689 schedGroup = "F";
10690 break;
10691 default:
10692 schedGroup = Integer.toString(r.setSchedGroup);
10693 break;
10694 }
10695 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010696 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010697 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010698 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010699 pw.print(prefix);
10700 pw.print(" ");
10701 if (r.adjTarget instanceof ComponentName) {
10702 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
10703 } else if (r.adjTarget != null) {
10704 pw.print(r.adjTarget.toString());
10705 } else {
10706 pw.print("{null}");
10707 }
10708 pw.print("<=");
10709 if (r.adjSource instanceof ProcessRecord) {
10710 pw.print("Proc{");
10711 pw.print(((ProcessRecord)r.adjSource).toShortString());
10712 pw.println("}");
10713 } else if (r.adjSource != null) {
10714 pw.println(r.adjSource.toString());
10715 } else {
10716 pw.println("{null}");
10717 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010719 } else {
10720 pw.println(String.format("%s%s #%2d: %s",
10721 prefix, (r.persistent ? persistentLabel : normalLabel),
10722 i, r.toString()));
10723 }
10724 if (r.persistent) {
10725 numPers++;
10726 }
10727 }
10728 return numPers;
10729 }
10730
Dianne Hackborn472ad872010-04-07 17:31:48 -070010731 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010732 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010733 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010734 long uptime = SystemClock.uptimeMillis();
10735 long realtime = SystemClock.elapsedRealtime();
10736
10737 if (isCheckinRequest) {
10738 // short checkin version
10739 pw.println(uptime + "," + realtime);
10740 pw.flush();
10741 } else {
10742 pw.println("Applications Memory Usage (kB):");
10743 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10744 }
10745 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10746 ProcessRecord r = (ProcessRecord)list.get(i);
10747 if (r.thread != null) {
10748 if (!isCheckinRequest) {
10749 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10750 pw.flush();
10751 }
10752 try {
10753 r.thread.asBinder().dump(fd, args);
10754 } catch (RemoteException e) {
10755 if (!isCheckinRequest) {
10756 pw.println("Got RemoteException!");
10757 pw.flush();
10758 }
10759 }
10760 }
10761 }
10762 }
10763
10764 /**
10765 * Searches array of arguments for the specified string
10766 * @param args array of argument strings
10767 * @param value value to search for
10768 * @return true if the value is contained in the array
10769 */
10770 private static boolean scanArgs(String[] args, String value) {
10771 if (args != null) {
10772 for (String arg : args) {
10773 if (value.equals(arg)) {
10774 return true;
10775 }
10776 }
10777 }
10778 return false;
10779 }
10780
Dianne Hackborn75b03852009-06-12 15:43:26 -070010781 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 int count = mHistory.size();
10783
10784 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010785 int index = -1;
10786 for (int i=count-1; i>=0; i--) {
10787 Object o = mHistory.get(i);
10788 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789 index = i;
10790 break;
10791 }
10792 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010793
10794 return index;
10795 }
10796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010797 private final void killServicesLocked(ProcessRecord app,
10798 boolean allowRestart) {
10799 // Report disconnected services.
10800 if (false) {
10801 // XXX we are letting the client link to the service for
10802 // death notifications.
10803 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010804 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010806 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010807 if (r.connections.size() > 0) {
10808 Iterator<ConnectionRecord> jt
10809 = r.connections.values().iterator();
10810 while (jt.hasNext()) {
10811 ConnectionRecord c = jt.next();
10812 if (c.binding.client != app) {
10813 try {
10814 //c.conn.connected(r.className, null);
10815 } catch (Exception e) {
10816 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010817 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010818 + r.shortName
10819 + " from app " + app.processName, e);
10820 }
10821 }
10822 }
10823 }
10824 }
10825 }
10826 }
10827
10828 // Clean up any connections this application has to other services.
10829 if (app.connections.size() > 0) {
10830 Iterator<ConnectionRecord> it = app.connections.iterator();
10831 while (it.hasNext()) {
10832 ConnectionRecord r = it.next();
10833 removeConnectionLocked(r, app, null);
10834 }
10835 }
10836 app.connections.clear();
10837
10838 if (app.services.size() != 0) {
10839 // Any services running in the application need to be placed
10840 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010841 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010842 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010843 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010844 synchronized (sr.stats.getBatteryStats()) {
10845 sr.stats.stopLaunchedLocked();
10846 }
10847 sr.app = null;
10848 sr.executeNesting = 0;
10849 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010850
10851 boolean hasClients = sr.bindings.size() > 0;
10852 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010853 Iterator<IntentBindRecord> bindings
10854 = sr.bindings.values().iterator();
10855 while (bindings.hasNext()) {
10856 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010857 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010858 + ": shouldUnbind=" + b.hasBound);
10859 b.binder = null;
10860 b.requested = b.received = b.hasBound = false;
10861 }
10862 }
10863
10864 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010865 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010866 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010867 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010868 sr.crashCount, sr.shortName, app.pid);
10869 bringDownServiceLocked(sr, true);
10870 } else if (!allowRestart) {
10871 bringDownServiceLocked(sr, true);
10872 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010873 boolean canceled = scheduleServiceRestartLocked(sr, true);
10874
10875 // Should the service remain running? Note that in the
10876 // extreme case of so many attempts to deliver a command
10877 // that it failed, that we also will stop it here.
10878 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10879 if (sr.pendingStarts.size() == 0) {
10880 sr.startRequested = false;
10881 if (!hasClients) {
10882 // Whoops, no reason to restart!
10883 bringDownServiceLocked(sr, true);
10884 }
10885 }
10886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010887 }
10888 }
10889
10890 if (!allowRestart) {
10891 app.services.clear();
10892 }
10893 }
10894
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010895 // Make sure we have no more records on the stopping list.
10896 int i = mStoppingServices.size();
10897 while (i > 0) {
10898 i--;
10899 ServiceRecord sr = mStoppingServices.get(i);
10900 if (sr.app == app) {
10901 mStoppingServices.remove(i);
10902 }
10903 }
10904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010905 app.executingServices.clear();
10906 }
10907
10908 private final void removeDyingProviderLocked(ProcessRecord proc,
10909 ContentProviderRecord cpr) {
10910 synchronized (cpr) {
10911 cpr.launchingApp = null;
10912 cpr.notifyAll();
10913 }
10914
10915 mProvidersByClass.remove(cpr.info.name);
10916 String names[] = cpr.info.authority.split(";");
10917 for (int j = 0; j < names.length; j++) {
10918 mProvidersByName.remove(names[j]);
10919 }
10920
10921 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10922 while (cit.hasNext()) {
10923 ProcessRecord capp = cit.next();
10924 if (!capp.persistent && capp.thread != null
10925 && capp.pid != 0
10926 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010927 Slog.i(TAG, "Kill " + capp.processName
10928 + " (pid " + capp.pid + "): provider " + cpr.info.name
10929 + " in dying process " + proc.processName);
10930 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10931 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010932 Process.killProcess(capp.pid);
10933 }
10934 }
10935
10936 mLaunchingProviders.remove(cpr);
10937 }
10938
10939 /**
10940 * Main code for cleaning up a process when it has gone away. This is
10941 * called both as a result of the process dying, or directly when stopping
10942 * a process when running in single process mode.
10943 */
10944 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10945 boolean restarting, int index) {
10946 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010947 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 }
10949
Dianne Hackborn36124872009-10-08 16:22:03 -070010950 mProcessesToGc.remove(app);
10951
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010952 // Dismiss any open dialogs.
10953 if (app.crashDialog != null) {
10954 app.crashDialog.dismiss();
10955 app.crashDialog = null;
10956 }
10957 if (app.anrDialog != null) {
10958 app.anrDialog.dismiss();
10959 app.anrDialog = null;
10960 }
10961 if (app.waitDialog != null) {
10962 app.waitDialog.dismiss();
10963 app.waitDialog = null;
10964 }
10965
10966 app.crashing = false;
10967 app.notResponding = false;
10968
10969 app.resetPackageList();
10970 app.thread = null;
10971 app.forcingToForeground = null;
10972 app.foregroundServices = false;
10973
10974 killServicesLocked(app, true);
10975
10976 boolean restart = false;
10977
10978 int NL = mLaunchingProviders.size();
10979
10980 // Remove published content providers.
10981 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010982 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010983 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010984 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 cpr.provider = null;
10986 cpr.app = null;
10987
10988 // See if someone is waiting for this provider... in which
10989 // case we don't remove it, but just let it restart.
10990 int i = 0;
10991 if (!app.bad) {
10992 for (; i<NL; i++) {
10993 if (mLaunchingProviders.get(i) == cpr) {
10994 restart = true;
10995 break;
10996 }
10997 }
10998 } else {
10999 i = NL;
11000 }
11001
11002 if (i >= NL) {
11003 removeDyingProviderLocked(app, cpr);
11004 NL = mLaunchingProviders.size();
11005 }
11006 }
11007 app.pubProviders.clear();
11008 }
11009
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011010 // Take care of any launching providers waiting for this process.
11011 if (checkAppInLaunchingProvidersLocked(app, false)) {
11012 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011013 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011015 // Unregister from connected content providers.
11016 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070011017 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 while (it.hasNext()) {
11019 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
11020 cpr.clients.remove(app);
11021 }
11022 app.conProviders.clear();
11023 }
11024
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011025 // At this point there may be remaining entries in mLaunchingProviders
11026 // where we were the only one waiting, so they are no longer of use.
11027 // Look for these and clean up if found.
11028 // XXX Commented out for now. Trying to figure out a way to reproduce
11029 // the actual situation to identify what is actually going on.
11030 if (false) {
11031 for (int i=0; i<NL; i++) {
11032 ContentProviderRecord cpr = (ContentProviderRecord)
11033 mLaunchingProviders.get(i);
11034 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
11035 synchronized (cpr) {
11036 cpr.launchingApp = null;
11037 cpr.notifyAll();
11038 }
11039 }
11040 }
11041 }
11042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011043 skipCurrentReceiverLocked(app);
11044
11045 // Unregister any receivers.
11046 if (app.receivers.size() > 0) {
11047 Iterator<ReceiverList> it = app.receivers.iterator();
11048 while (it.hasNext()) {
11049 removeReceiverLocked(it.next());
11050 }
11051 app.receivers.clear();
11052 }
11053
Christopher Tate181fafa2009-05-14 11:12:14 -070011054 // If the app is undergoing backup, tell the backup manager about it
11055 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011056 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070011057 try {
11058 IBackupManager bm = IBackupManager.Stub.asInterface(
11059 ServiceManager.getService(Context.BACKUP_SERVICE));
11060 bm.agentDisconnected(app.info.packageName);
11061 } catch (RemoteException e) {
11062 // can't happen; backup manager is local
11063 }
11064 }
11065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011066 // If the caller is restarting this app, then leave it in its
11067 // current lists and let the caller take care of it.
11068 if (restarting) {
11069 return;
11070 }
11071
11072 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011073 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011074 "Removing non-persistent process during cleanup: " + app);
11075 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070011076 if (mHeavyWeightProcess == app) {
11077 mHeavyWeightProcess = null;
11078 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
11079 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080 } else if (!app.removed) {
11081 // This app is persistent, so we need to keep its record around.
11082 // If it is not already on the pending app list, add it there
11083 // and start a new process for it.
11084 app.thread = null;
11085 app.forcingToForeground = null;
11086 app.foregroundServices = false;
11087 if (mPersistentStartingProcesses.indexOf(app) < 0) {
11088 mPersistentStartingProcesses.add(app);
11089 restart = true;
11090 }
11091 }
11092 mProcessesOnHold.remove(app);
11093
The Android Open Source Project4df24232009-03-05 14:34:35 -080011094 if (app == mHomeProcess) {
11095 mHomeProcess = null;
11096 }
11097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011098 if (restart) {
11099 // We have components that still need to be running in the
11100 // process, so re-launch it.
11101 mProcessNames.put(app.processName, app.info.uid, app);
11102 startProcessLocked(app, "restart", app.processName);
11103 } else if (app.pid > 0 && app.pid != MY_PID) {
11104 // Goodbye!
11105 synchronized (mPidsSelfLocked) {
11106 mPidsSelfLocked.remove(app.pid);
11107 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
11108 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070011109 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 }
11111 }
11112
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011113 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
11114 // Look through the content providers we are waiting to have launched,
11115 // and if any run in this process then either schedule a restart of
11116 // the process or kill the client waiting for it if this process has
11117 // gone bad.
11118 int NL = mLaunchingProviders.size();
11119 boolean restart = false;
11120 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011121 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011122 if (cpr.launchingApp == app) {
11123 if (!alwaysBad && !app.bad) {
11124 restart = true;
11125 } else {
11126 removeDyingProviderLocked(app, cpr);
11127 NL = mLaunchingProviders.size();
11128 }
11129 }
11130 }
11131 return restart;
11132 }
11133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011134 // =========================================================
11135 // SERVICES
11136 // =========================================================
11137
11138 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
11139 ActivityManager.RunningServiceInfo info =
11140 new ActivityManager.RunningServiceInfo();
11141 info.service = r.name;
11142 if (r.app != null) {
11143 info.pid = r.app.pid;
11144 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011145 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011146 info.process = r.processName;
11147 info.foreground = r.isForeground;
11148 info.activeSince = r.createTime;
11149 info.started = r.startRequested;
11150 info.clientCount = r.connections.size();
11151 info.crashCount = r.crashCount;
11152 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011153 if (r.isForeground) {
11154 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
11155 }
11156 if (r.startRequested) {
11157 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
11158 }
Dan Egnor42471dd2010-01-07 17:25:22 -080011159 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011160 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
11161 }
11162 if (r.app != null && r.app.persistent) {
11163 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
11164 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011165 for (ConnectionRecord conn : r.connections.values()) {
11166 if (conn.clientLabel != 0) {
11167 info.clientPackage = conn.binding.client.info.packageName;
11168 info.clientLabel = conn.clientLabel;
11169 break;
11170 }
11171 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011172 return info;
11173 }
11174
11175 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
11176 int flags) {
11177 synchronized (this) {
11178 ArrayList<ActivityManager.RunningServiceInfo> res
11179 = new ArrayList<ActivityManager.RunningServiceInfo>();
11180
11181 if (mServices.size() > 0) {
11182 Iterator<ServiceRecord> it = mServices.values().iterator();
11183 while (it.hasNext() && res.size() < maxNum) {
11184 res.add(makeRunningServiceInfoLocked(it.next()));
11185 }
11186 }
11187
11188 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
11189 ServiceRecord r = mRestartingServices.get(i);
11190 ActivityManager.RunningServiceInfo info =
11191 makeRunningServiceInfoLocked(r);
11192 info.restarting = r.nextRestartTime;
11193 res.add(info);
11194 }
11195
11196 return res;
11197 }
11198 }
11199
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011200 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
11201 synchronized (this) {
11202 ServiceRecord r = mServices.get(name);
11203 if (r != null) {
11204 for (ConnectionRecord conn : r.connections.values()) {
11205 if (conn.clientIntent != null) {
11206 return conn.clientIntent;
11207 }
11208 }
11209 }
11210 }
11211 return null;
11212 }
11213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 private final ServiceRecord findServiceLocked(ComponentName name,
11215 IBinder token) {
11216 ServiceRecord r = mServices.get(name);
11217 return r == token ? r : null;
11218 }
11219
11220 private final class ServiceLookupResult {
11221 final ServiceRecord record;
11222 final String permission;
11223
11224 ServiceLookupResult(ServiceRecord _record, String _permission) {
11225 record = _record;
11226 permission = _permission;
11227 }
11228 };
11229
11230 private ServiceLookupResult findServiceLocked(Intent service,
11231 String resolvedType) {
11232 ServiceRecord r = null;
11233 if (service.getComponent() != null) {
11234 r = mServices.get(service.getComponent());
11235 }
11236 if (r == null) {
11237 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11238 r = mServicesByIntent.get(filter);
11239 }
11240
11241 if (r == null) {
11242 try {
11243 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011244 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011245 service, resolvedType, 0);
11246 ServiceInfo sInfo =
11247 rInfo != null ? rInfo.serviceInfo : null;
11248 if (sInfo == null) {
11249 return null;
11250 }
11251
11252 ComponentName name = new ComponentName(
11253 sInfo.applicationInfo.packageName, sInfo.name);
11254 r = mServices.get(name);
11255 } catch (RemoteException ex) {
11256 // pm is in same process, this will never happen.
11257 }
11258 }
11259 if (r != null) {
11260 int callingPid = Binder.getCallingPid();
11261 int callingUid = Binder.getCallingUid();
11262 if (checkComponentPermission(r.permission,
11263 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11264 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011265 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 + " from pid=" + callingPid
11267 + ", uid=" + callingUid
11268 + " requires " + r.permission);
11269 return new ServiceLookupResult(null, r.permission);
11270 }
11271 return new ServiceLookupResult(r, null);
11272 }
11273 return null;
11274 }
11275
11276 private class ServiceRestarter implements Runnable {
11277 private ServiceRecord mService;
11278
11279 void setService(ServiceRecord service) {
11280 mService = service;
11281 }
11282
11283 public void run() {
11284 synchronized(ActivityManagerService.this) {
11285 performServiceRestartLocked(mService);
11286 }
11287 }
11288 }
11289
11290 private ServiceLookupResult retrieveServiceLocked(Intent service,
11291 String resolvedType, int callingPid, int callingUid) {
11292 ServiceRecord r = null;
11293 if (service.getComponent() != null) {
11294 r = mServices.get(service.getComponent());
11295 }
11296 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11297 r = mServicesByIntent.get(filter);
11298 if (r == null) {
11299 try {
11300 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011301 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011302 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011303 ServiceInfo sInfo =
11304 rInfo != null ? rInfo.serviceInfo : null;
11305 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011306 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011307 ": not found");
11308 return null;
11309 }
11310
11311 ComponentName name = new ComponentName(
11312 sInfo.applicationInfo.packageName, sInfo.name);
11313 r = mServices.get(name);
11314 if (r == null) {
11315 filter = new Intent.FilterComparison(service.cloneFilter());
11316 ServiceRestarter res = new ServiceRestarter();
11317 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11318 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11319 synchronized (stats) {
11320 ss = stats.getServiceStatsLocked(
11321 sInfo.applicationInfo.uid, sInfo.packageName,
11322 sInfo.name);
11323 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080011324 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011325 res.setService(r);
11326 mServices.put(name, r);
11327 mServicesByIntent.put(filter, r);
11328
11329 // Make sure this component isn't in the pending list.
11330 int N = mPendingServices.size();
11331 for (int i=0; i<N; i++) {
11332 ServiceRecord pr = mPendingServices.get(i);
11333 if (pr.name.equals(name)) {
11334 mPendingServices.remove(i);
11335 i--;
11336 N--;
11337 }
11338 }
11339 }
11340 } catch (RemoteException ex) {
11341 // pm is in same process, this will never happen.
11342 }
11343 }
11344 if (r != null) {
11345 if (checkComponentPermission(r.permission,
11346 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11347 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011348 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011349 + " from pid=" + Binder.getCallingPid()
11350 + ", uid=" + Binder.getCallingUid()
11351 + " requires " + r.permission);
11352 return new ServiceLookupResult(null, r.permission);
11353 }
11354 return new ServiceLookupResult(r, null);
11355 }
11356 return null;
11357 }
11358
11359 private final void bumpServiceExecutingLocked(ServiceRecord r) {
11360 long now = SystemClock.uptimeMillis();
11361 if (r.executeNesting == 0 && r.app != null) {
11362 if (r.app.executingServices.size() == 0) {
11363 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11364 msg.obj = r.app;
11365 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
11366 }
11367 r.app.executingServices.add(r);
11368 }
11369 r.executeNesting++;
11370 r.executingStart = now;
11371 }
11372
11373 private final void sendServiceArgsLocked(ServiceRecord r,
11374 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011375 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011376 if (N == 0) {
11377 return;
11378 }
11379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011380 int i = 0;
11381 while (i < N) {
11382 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011383 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011384 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011385 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070011386 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011387 // If somehow we got a dummy start at the front, then
11388 // just drop it here.
11389 i++;
11390 continue;
11391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011392 bumpServiceExecutingLocked(r);
11393 if (!oomAdjusted) {
11394 oomAdjusted = true;
11395 updateOomAdjLocked(r.app);
11396 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011397 int flags = 0;
11398 if (si.deliveryCount > 0) {
11399 flags |= Service.START_FLAG_RETRY;
11400 }
11401 if (si.doneExecutingCount > 0) {
11402 flags |= Service.START_FLAG_REDELIVERY;
11403 }
11404 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
11405 si.deliveredTime = SystemClock.uptimeMillis();
11406 r.deliveredStarts.add(si);
11407 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011409 } catch (RemoteException e) {
11410 // Remote process gone... we'll let the normal cleanup take
11411 // care of this.
11412 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011413 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011414 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011415 break;
11416 }
11417 }
11418 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011419 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011420 } else {
11421 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011422 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011423 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011424 }
11425 }
11426 }
11427
11428 private final boolean requestServiceBindingLocked(ServiceRecord r,
11429 IntentBindRecord i, boolean rebind) {
11430 if (r.app == null || r.app.thread == null) {
11431 // If service is not currently running, can't yet bind.
11432 return false;
11433 }
11434 if ((!i.requested || rebind) && i.apps.size() > 0) {
11435 try {
11436 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011437 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011438 + ": shouldUnbind=" + i.hasBound);
11439 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11440 if (!rebind) {
11441 i.requested = true;
11442 }
11443 i.hasBound = true;
11444 i.doRebind = false;
11445 } catch (RemoteException e) {
11446 return false;
11447 }
11448 }
11449 return true;
11450 }
11451
11452 private final void requestServiceBindingsLocked(ServiceRecord r) {
11453 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11454 while (bindings.hasNext()) {
11455 IntentBindRecord i = bindings.next();
11456 if (!requestServiceBindingLocked(r, i, false)) {
11457 break;
11458 }
11459 }
11460 }
11461
11462 private final void realStartServiceLocked(ServiceRecord r,
11463 ProcessRecord app) throws RemoteException {
11464 if (app.thread == null) {
11465 throw new RemoteException();
11466 }
11467
11468 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011469 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470
11471 app.services.add(r);
11472 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011473 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474
11475 boolean created = false;
11476 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011477 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011478 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011479 mStringBuilder.setLength(0);
11480 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011481 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011482 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011483 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011484 synchronized (r.stats.getBatteryStats()) {
11485 r.stats.startLaunchedLocked();
11486 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011487 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011488 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011489 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011490 created = true;
11491 } finally {
11492 if (!created) {
11493 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011494 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011495 }
11496 }
11497
11498 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011499
11500 // If the service is in the started state, and there are no
11501 // pending arguments, then fake up one so its onStartCommand() will
11502 // be called.
11503 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11504 r.lastStartId++;
11505 if (r.lastStartId < 1) {
11506 r.lastStartId = 1;
11507 }
11508 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11509 }
11510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 sendServiceArgsLocked(r, true);
11512 }
11513
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011514 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11515 boolean allowCancel) {
11516 boolean canceled = false;
11517
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011518 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011519 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011520 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011521
11522 // Any delivered but not yet finished starts should be put back
11523 // on the pending list.
11524 final int N = r.deliveredStarts.size();
11525 if (N > 0) {
11526 for (int i=N-1; i>=0; i--) {
11527 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11528 if (si.intent == null) {
11529 // We'll generate this again if needed.
11530 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11531 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11532 r.pendingStarts.add(0, si);
11533 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11534 dur *= 2;
11535 if (minDuration < dur) minDuration = dur;
11536 if (resetTime < dur) resetTime = dur;
11537 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011538 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011539 + r.name);
11540 canceled = true;
11541 }
11542 }
11543 r.deliveredStarts.clear();
11544 }
11545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011546 r.totalRestartCount++;
11547 if (r.restartDelay == 0) {
11548 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011549 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011550 } else {
11551 // If it has been a "reasonably long time" since the service
11552 // was started, then reset our restart duration back to
11553 // the beginning, so we don't infinitely increase the duration
11554 // on a service that just occasionally gets killed (which is
11555 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011556 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011557 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011558 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011559 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011560 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011561 if (r.restartDelay < minDuration) {
11562 r.restartDelay = minDuration;
11563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011564 }
11565 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011566
11567 r.nextRestartTime = now + r.restartDelay;
11568
11569 // Make sure that we don't end up restarting a bunch of services
11570 // all at the same time.
11571 boolean repeat;
11572 do {
11573 repeat = false;
11574 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11575 ServiceRecord r2 = mRestartingServices.get(i);
11576 if (r2 != r && r.nextRestartTime
11577 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11578 && r.nextRestartTime
11579 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11580 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11581 r.restartDelay = r.nextRestartTime - now;
11582 repeat = true;
11583 break;
11584 }
11585 }
11586 } while (repeat);
11587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011588 if (!mRestartingServices.contains(r)) {
11589 mRestartingServices.add(r);
11590 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011591
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011592 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011595 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011596 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011597 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011599 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011600 r.shortName, r.restartDelay);
11601
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011602 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011603 }
11604
11605 final void performServiceRestartLocked(ServiceRecord r) {
11606 if (!mRestartingServices.contains(r)) {
11607 return;
11608 }
11609 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11610 }
11611
11612 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11613 if (r.restartDelay == 0) {
11614 return false;
11615 }
11616 r.resetRestartCounter();
11617 mRestartingServices.remove(r);
11618 mHandler.removeCallbacks(r.restarter);
11619 return true;
11620 }
11621
11622 private final boolean bringUpServiceLocked(ServiceRecord r,
11623 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011624 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011625 //r.dump(" ");
11626
Dianne Hackborn36124872009-10-08 16:22:03 -070011627 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628 sendServiceArgsLocked(r, false);
11629 return true;
11630 }
11631
11632 if (!whileRestarting && r.restartDelay > 0) {
11633 // If waiting for a restart, then do nothing.
11634 return true;
11635 }
11636
Joe Onorato8a9b2202010-02-26 18:56:32 -080011637 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011638 + " " + r.intent);
11639
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011640 // We are now bringing the service up, so no longer in the
11641 // restarting state.
11642 mRestartingServices.remove(r);
11643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011644 final String appName = r.processName;
11645 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11646 if (app != null && app.thread != null) {
11647 try {
11648 realStartServiceLocked(r, app);
11649 return true;
11650 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011651 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011652 }
11653
11654 // If a dead object exception was thrown -- fall through to
11655 // restart the application.
11656 }
11657
Dianne Hackborn36124872009-10-08 16:22:03 -070011658 // Not running -- get it started, and enqueue this service record
11659 // to be executed when the app comes up.
11660 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11661 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011662 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011663 + r.appInfo.packageName + "/"
11664 + r.appInfo.uid + " for service "
11665 + r.intent.getIntent() + ": process is bad");
11666 bringDownServiceLocked(r, true);
11667 return false;
11668 }
11669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011670 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011671 mPendingServices.add(r);
11672 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011674 return true;
11675 }
11676
11677 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011678 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011679 //r.dump(" ");
11680
11681 // Does it still need to run?
11682 if (!force && r.startRequested) {
11683 return;
11684 }
11685 if (r.connections.size() > 0) {
11686 if (!force) {
11687 // XXX should probably keep a count of the number of auto-create
11688 // connections directly in the service.
11689 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11690 while (it.hasNext()) {
11691 ConnectionRecord cr = it.next();
11692 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11693 return;
11694 }
11695 }
11696 }
11697
11698 // Report to all of the connections that the service is no longer
11699 // available.
11700 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11701 while (it.hasNext()) {
11702 ConnectionRecord c = it.next();
11703 try {
11704 // todo: shouldn't be a synchronous call!
11705 c.conn.connected(r.name, null);
11706 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011707 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011708 " to connection " + c.conn.asBinder() +
11709 " (in " + c.binding.client.processName + ")", e);
11710 }
11711 }
11712 }
11713
11714 // Tell the service that it has been unbound.
11715 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11716 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11717 while (it.hasNext()) {
11718 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011719 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011720 + ": hasBound=" + ibr.hasBound);
11721 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11722 try {
11723 bumpServiceExecutingLocked(r);
11724 updateOomAdjLocked(r.app);
11725 ibr.hasBound = false;
11726 r.app.thread.scheduleUnbindService(r,
11727 ibr.intent.getIntent());
11728 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011729 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011730 + r.shortName, e);
11731 serviceDoneExecutingLocked(r, true);
11732 }
11733 }
11734 }
11735 }
11736
Joe Onorato8a9b2202010-02-26 18:56:32 -080011737 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011738 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011739 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011740 System.identityHashCode(r), r.shortName,
11741 (r.app != null) ? r.app.pid : -1);
11742
11743 mServices.remove(r.name);
11744 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011745 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011746 r.totalRestartCount = 0;
11747 unscheduleServiceRestartLocked(r);
11748
11749 // Also make sure it is not on the pending list.
11750 int N = mPendingServices.size();
11751 for (int i=0; i<N; i++) {
11752 if (mPendingServices.get(i) == r) {
11753 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011754 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011755 TAG, "Removed pending service: " + r.shortName);
11756 i--;
11757 N--;
11758 }
11759 }
11760
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011761 r.cancelNotification();
11762 r.isForeground = false;
11763 r.foregroundId = 0;
11764 r.foregroundNoti = null;
11765
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011766 // Clear start entries.
11767 r.deliveredStarts.clear();
11768 r.pendingStarts.clear();
11769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011770 if (r.app != null) {
11771 synchronized (r.stats.getBatteryStats()) {
11772 r.stats.stopLaunchedLocked();
11773 }
11774 r.app.services.remove(r);
11775 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011776 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011777 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011778 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 bumpServiceExecutingLocked(r);
11780 mStoppingServices.add(r);
11781 updateOomAdjLocked(r.app);
11782 r.app.thread.scheduleStopService(r);
11783 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011784 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785 + r.shortName, e);
11786 serviceDoneExecutingLocked(r, true);
11787 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011788 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011789 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011790 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011791 TAG, "Removed service that has no process: " + r.shortName);
11792 }
11793 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011794 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011795 TAG, "Removed service that is not running: " + r.shortName);
11796 }
11797 }
11798
11799 ComponentName startServiceLocked(IApplicationThread caller,
11800 Intent service, String resolvedType,
11801 int callingPid, int callingUid) {
11802 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011803 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804 + " type=" + resolvedType + " args=" + service.getExtras());
11805
11806 if (caller != null) {
11807 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11808 if (callerApp == null) {
11809 throw new SecurityException(
11810 "Unable to find app for caller " + caller
11811 + " (pid=" + Binder.getCallingPid()
11812 + ") when starting service " + service);
11813 }
11814 }
11815
11816 ServiceLookupResult res =
11817 retrieveServiceLocked(service, resolvedType,
11818 callingPid, callingUid);
11819 if (res == null) {
11820 return null;
11821 }
11822 if (res.record == null) {
11823 return new ComponentName("!", res.permission != null
11824 ? res.permission : "private to package");
11825 }
11826 ServiceRecord r = res.record;
11827 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011828 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011829 + r.shortName);
11830 }
11831 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011832 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011833 r.lastStartId++;
11834 if (r.lastStartId < 1) {
11835 r.lastStartId = 1;
11836 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011837 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011838 r.lastActivity = SystemClock.uptimeMillis();
11839 synchronized (r.stats.getBatteryStats()) {
11840 r.stats.startRunningLocked();
11841 }
11842 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11843 return new ComponentName("!", "Service process is bad");
11844 }
11845 return r.name;
11846 }
11847 }
11848
11849 public ComponentName startService(IApplicationThread caller, Intent service,
11850 String resolvedType) {
11851 // Refuse possible leaked file descriptors
11852 if (service != null && service.hasFileDescriptors() == true) {
11853 throw new IllegalArgumentException("File descriptors passed in Intent");
11854 }
11855
11856 synchronized(this) {
11857 final int callingPid = Binder.getCallingPid();
11858 final int callingUid = Binder.getCallingUid();
11859 final long origId = Binder.clearCallingIdentity();
11860 ComponentName res = startServiceLocked(caller, service,
11861 resolvedType, callingPid, callingUid);
11862 Binder.restoreCallingIdentity(origId);
11863 return res;
11864 }
11865 }
11866
11867 ComponentName startServiceInPackage(int uid,
11868 Intent service, String resolvedType) {
11869 synchronized(this) {
11870 final long origId = Binder.clearCallingIdentity();
11871 ComponentName res = startServiceLocked(null, service,
11872 resolvedType, -1, uid);
11873 Binder.restoreCallingIdentity(origId);
11874 return res;
11875 }
11876 }
11877
11878 public int stopService(IApplicationThread caller, Intent service,
11879 String resolvedType) {
11880 // Refuse possible leaked file descriptors
11881 if (service != null && service.hasFileDescriptors() == true) {
11882 throw new IllegalArgumentException("File descriptors passed in Intent");
11883 }
11884
11885 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011886 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011887 + " type=" + resolvedType);
11888
11889 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11890 if (caller != null && callerApp == null) {
11891 throw new SecurityException(
11892 "Unable to find app for caller " + caller
11893 + " (pid=" + Binder.getCallingPid()
11894 + ") when stopping service " + service);
11895 }
11896
11897 // If this service is active, make sure it is stopped.
11898 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11899 if (r != null) {
11900 if (r.record != null) {
11901 synchronized (r.record.stats.getBatteryStats()) {
11902 r.record.stats.stopRunningLocked();
11903 }
11904 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011905 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011906 final long origId = Binder.clearCallingIdentity();
11907 bringDownServiceLocked(r.record, false);
11908 Binder.restoreCallingIdentity(origId);
11909 return 1;
11910 }
11911 return -1;
11912 }
11913 }
11914
11915 return 0;
11916 }
11917
11918 public IBinder peekService(Intent service, String resolvedType) {
11919 // Refuse possible leaked file descriptors
11920 if (service != null && service.hasFileDescriptors() == true) {
11921 throw new IllegalArgumentException("File descriptors passed in Intent");
11922 }
11923
11924 IBinder ret = null;
11925
11926 synchronized(this) {
11927 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11928
11929 if (r != null) {
11930 // r.record is null if findServiceLocked() failed the caller permission check
11931 if (r.record == null) {
11932 throw new SecurityException(
11933 "Permission Denial: Accessing service " + r.record.name
11934 + " from pid=" + Binder.getCallingPid()
11935 + ", uid=" + Binder.getCallingUid()
11936 + " requires " + r.permission);
11937 }
11938 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11939 if (ib != null) {
11940 ret = ib.binder;
11941 }
11942 }
11943 }
11944
11945 return ret;
11946 }
11947
11948 public boolean stopServiceToken(ComponentName className, IBinder token,
11949 int startId) {
11950 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011951 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 + " " + token + " startId=" + startId);
11953 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011954 if (r != null) {
11955 if (startId >= 0) {
11956 // Asked to only stop if done with all work. Note that
11957 // to avoid leaks, we will take this as dropping all
11958 // start items up to and including this one.
11959 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11960 if (si != null) {
11961 while (r.deliveredStarts.size() > 0) {
11962 if (r.deliveredStarts.remove(0) == si) {
11963 break;
11964 }
11965 }
11966 }
11967
11968 if (r.lastStartId != startId) {
11969 return false;
11970 }
11971
11972 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011973 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011974 + " is last, but have " + r.deliveredStarts.size()
11975 + " remaining args");
11976 }
11977 }
11978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011979 synchronized (r.stats.getBatteryStats()) {
11980 r.stats.stopRunningLocked();
11981 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011982 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011983 }
11984 final long origId = Binder.clearCallingIdentity();
11985 bringDownServiceLocked(r, false);
11986 Binder.restoreCallingIdentity(origId);
11987 return true;
11988 }
11989 }
11990 return false;
11991 }
11992
11993 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011994 int id, Notification notification, boolean removeNotification) {
11995 final long origId = Binder.clearCallingIdentity();
11996 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011997 synchronized(this) {
11998 ServiceRecord r = findServiceLocked(className, token);
11999 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012000 if (id != 0) {
12001 if (notification == null) {
12002 throw new IllegalArgumentException("null notification");
12003 }
12004 if (r.foregroundId != id) {
12005 r.cancelNotification();
12006 r.foregroundId = id;
12007 }
12008 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
12009 r.foregroundNoti = notification;
12010 r.isForeground = true;
12011 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012012 if (r.app != null) {
12013 updateServiceForegroundLocked(r.app, true);
12014 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012015 } else {
12016 if (r.isForeground) {
12017 r.isForeground = false;
12018 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070012019 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012020 updateServiceForegroundLocked(r.app, true);
12021 }
12022 }
12023 if (removeNotification) {
12024 r.cancelNotification();
12025 r.foregroundId = 0;
12026 r.foregroundNoti = null;
12027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012028 }
12029 }
12030 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070012031 } finally {
12032 Binder.restoreCallingIdentity(origId);
12033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012034 }
12035
12036 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
12037 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070012038 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012039 if (sr.isForeground) {
12040 anyForeground = true;
12041 break;
12042 }
12043 }
12044 if (anyForeground != proc.foregroundServices) {
12045 proc.foregroundServices = anyForeground;
12046 if (oomAdj) {
12047 updateOomAdjLocked();
12048 }
12049 }
12050 }
12051
12052 public int bindService(IApplicationThread caller, IBinder token,
12053 Intent service, String resolvedType,
12054 IServiceConnection connection, int flags) {
12055 // Refuse possible leaked file descriptors
12056 if (service != null && service.hasFileDescriptors() == true) {
12057 throw new IllegalArgumentException("File descriptors passed in Intent");
12058 }
12059
12060 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012061 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012062 + " type=" + resolvedType + " conn=" + connection.asBinder()
12063 + " flags=0x" + Integer.toHexString(flags));
12064 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12065 if (callerApp == null) {
12066 throw new SecurityException(
12067 "Unable to find app for caller " + caller
12068 + " (pid=" + Binder.getCallingPid()
12069 + ") when binding service " + service);
12070 }
12071
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012072 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012073 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070012074 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012075 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012076 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012077 return 0;
12078 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012079 activity = (ActivityRecord)mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012080 }
12081
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012082 int clientLabel = 0;
12083 PendingIntent clientIntent = null;
12084
12085 if (callerApp.info.uid == Process.SYSTEM_UID) {
12086 // Hacky kind of thing -- allow system stuff to tell us
12087 // what they are, so we can report this elsewhere for
12088 // others to know why certain services are running.
12089 try {
12090 clientIntent = (PendingIntent)service.getParcelableExtra(
12091 Intent.EXTRA_CLIENT_INTENT);
12092 } catch (RuntimeException e) {
12093 }
12094 if (clientIntent != null) {
12095 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
12096 if (clientLabel != 0) {
12097 // There are no useful extras in the intent, trash them.
12098 // System code calling with this stuff just needs to know
12099 // this will happen.
12100 service = service.cloneFilter();
12101 }
12102 }
12103 }
12104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012105 ServiceLookupResult res =
12106 retrieveServiceLocked(service, resolvedType,
12107 Binder.getCallingPid(), Binder.getCallingUid());
12108 if (res == null) {
12109 return 0;
12110 }
12111 if (res.record == null) {
12112 return -1;
12113 }
12114 ServiceRecord s = res.record;
12115
12116 final long origId = Binder.clearCallingIdentity();
12117
12118 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012119 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012120 + s.shortName);
12121 }
12122
12123 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
12124 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012125 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012126
12127 IBinder binder = connection.asBinder();
12128 s.connections.put(binder, c);
12129 b.connections.add(c);
12130 if (activity != null) {
12131 if (activity.connections == null) {
12132 activity.connections = new HashSet<ConnectionRecord>();
12133 }
12134 activity.connections.add(c);
12135 }
12136 b.client.connections.add(c);
12137 mServiceConnections.put(binder, c);
12138
12139 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
12140 s.lastActivity = SystemClock.uptimeMillis();
12141 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
12142 return 0;
12143 }
12144 }
12145
12146 if (s.app != null) {
12147 // This could have made the service more important.
12148 updateOomAdjLocked(s.app);
12149 }
12150
Joe Onorato8a9b2202010-02-26 18:56:32 -080012151 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012152 + ": received=" + b.intent.received
12153 + " apps=" + b.intent.apps.size()
12154 + " doRebind=" + b.intent.doRebind);
12155
12156 if (s.app != null && b.intent.received) {
12157 // Service is already running, so we can immediately
12158 // publish the connection.
12159 try {
12160 c.conn.connected(s.name, b.intent.binder);
12161 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012162 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012163 + " to connection " + c.conn.asBinder()
12164 + " (in " + c.binding.client.processName + ")", e);
12165 }
12166
12167 // If this is the first app connected back to this binding,
12168 // and the service had previously asked to be told when
12169 // rebound, then do so.
12170 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
12171 requestServiceBindingLocked(s, b.intent, true);
12172 }
12173 } else if (!b.intent.requested) {
12174 requestServiceBindingLocked(s, b.intent, false);
12175 }
12176
12177 Binder.restoreCallingIdentity(origId);
12178 }
12179
12180 return 1;
12181 }
12182
12183 private void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012184 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012185 IBinder binder = c.conn.asBinder();
12186 AppBindRecord b = c.binding;
12187 ServiceRecord s = b.service;
12188 s.connections.remove(binder);
12189 b.connections.remove(c);
12190 if (c.activity != null && c.activity != skipAct) {
12191 if (c.activity.connections != null) {
12192 c.activity.connections.remove(c);
12193 }
12194 }
12195 if (b.client != skipApp) {
12196 b.client.connections.remove(c);
12197 }
12198 mServiceConnections.remove(binder);
12199
12200 if (b.connections.size() == 0) {
12201 b.intent.apps.remove(b.client);
12202 }
12203
Joe Onorato8a9b2202010-02-26 18:56:32 -080012204 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012205 + ": shouldUnbind=" + b.intent.hasBound);
12206 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
12207 && b.intent.hasBound) {
12208 try {
12209 bumpServiceExecutingLocked(s);
12210 updateOomAdjLocked(s.app);
12211 b.intent.hasBound = false;
12212 // Assume the client doesn't want to know about a rebind;
12213 // we will deal with that later if it asks for one.
12214 b.intent.doRebind = false;
12215 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
12216 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012217 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012218 serviceDoneExecutingLocked(s, true);
12219 }
12220 }
12221
12222 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
12223 bringDownServiceLocked(s, false);
12224 }
12225 }
12226
12227 public boolean unbindService(IServiceConnection connection) {
12228 synchronized (this) {
12229 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012230 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012231 ConnectionRecord r = mServiceConnections.get(binder);
12232 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012233 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012234 + connection.asBinder());
12235 return false;
12236 }
12237
12238 final long origId = Binder.clearCallingIdentity();
12239
12240 removeConnectionLocked(r, null, null);
12241
12242 if (r.binding.service.app != null) {
12243 // This could have made the service less important.
12244 updateOomAdjLocked(r.binding.service.app);
12245 }
12246
12247 Binder.restoreCallingIdentity(origId);
12248 }
12249
12250 return true;
12251 }
12252
12253 public void publishService(IBinder token, Intent intent, IBinder service) {
12254 // Refuse possible leaked file descriptors
12255 if (intent != null && intent.hasFileDescriptors() == true) {
12256 throw new IllegalArgumentException("File descriptors passed in Intent");
12257 }
12258
12259 synchronized(this) {
12260 if (!(token instanceof ServiceRecord)) {
12261 throw new IllegalArgumentException("Invalid service token");
12262 }
12263 ServiceRecord r = (ServiceRecord)token;
12264
12265 final long origId = Binder.clearCallingIdentity();
12266
Joe Onorato8a9b2202010-02-26 18:56:32 -080012267 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012268 + " " + intent + ": " + service);
12269 if (r != null) {
12270 Intent.FilterComparison filter
12271 = new Intent.FilterComparison(intent);
12272 IntentBindRecord b = r.bindings.get(filter);
12273 if (b != null && !b.received) {
12274 b.binder = service;
12275 b.requested = true;
12276 b.received = true;
12277 if (r.connections.size() > 0) {
12278 Iterator<ConnectionRecord> it
12279 = r.connections.values().iterator();
12280 while (it.hasNext()) {
12281 ConnectionRecord c = it.next();
12282 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012283 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012284 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012285 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012286 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012287 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012288 TAG, "Published intent: " + intent);
12289 continue;
12290 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012291 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012292 try {
12293 c.conn.connected(r.name, service);
12294 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012295 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012296 " to connection " + c.conn.asBinder() +
12297 " (in " + c.binding.client.processName + ")", e);
12298 }
12299 }
12300 }
12301 }
12302
12303 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12304
12305 Binder.restoreCallingIdentity(origId);
12306 }
12307 }
12308 }
12309
12310 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
12311 // Refuse possible leaked file descriptors
12312 if (intent != null && intent.hasFileDescriptors() == true) {
12313 throw new IllegalArgumentException("File descriptors passed in Intent");
12314 }
12315
12316 synchronized(this) {
12317 if (!(token instanceof ServiceRecord)) {
12318 throw new IllegalArgumentException("Invalid service token");
12319 }
12320 ServiceRecord r = (ServiceRecord)token;
12321
12322 final long origId = Binder.clearCallingIdentity();
12323
12324 if (r != null) {
12325 Intent.FilterComparison filter
12326 = new Intent.FilterComparison(intent);
12327 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012328 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012329 + " at " + b + ": apps="
12330 + (b != null ? b.apps.size() : 0));
12331 if (b != null) {
12332 if (b.apps.size() > 0) {
12333 // Applications have already bound since the last
12334 // unbind, so just rebind right here.
12335 requestServiceBindingLocked(r, b, true);
12336 } else {
12337 // Note to tell the service the next time there is
12338 // a new client.
12339 b.doRebind = true;
12340 }
12341 }
12342
12343 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12344
12345 Binder.restoreCallingIdentity(origId);
12346 }
12347 }
12348 }
12349
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012350 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012351 synchronized(this) {
12352 if (!(token instanceof ServiceRecord)) {
12353 throw new IllegalArgumentException("Invalid service token");
12354 }
12355 ServiceRecord r = (ServiceRecord)token;
12356 boolean inStopping = mStoppingServices.contains(token);
12357 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012358 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012359 + ": nesting=" + r.executeNesting
12360 + ", inStopping=" + inStopping);
12361 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012362 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012363 + " with incorrect token: given " + token
12364 + ", expected " + r);
12365 return;
12366 }
12367
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012368 if (type == 1) {
12369 // This is a call from a service start... take care of
12370 // book-keeping.
12371 r.callStart = true;
12372 switch (res) {
12373 case Service.START_STICKY_COMPATIBILITY:
12374 case Service.START_STICKY: {
12375 // We are done with the associated start arguments.
12376 r.findDeliveredStart(startId, true);
12377 // Don't stop if killed.
12378 r.stopIfKilled = false;
12379 break;
12380 }
12381 case Service.START_NOT_STICKY: {
12382 // We are done with the associated start arguments.
12383 r.findDeliveredStart(startId, true);
12384 if (r.lastStartId == startId) {
12385 // There is no more work, and this service
12386 // doesn't want to hang around if killed.
12387 r.stopIfKilled = true;
12388 }
12389 break;
12390 }
12391 case Service.START_REDELIVER_INTENT: {
12392 // We'll keep this item until they explicitly
12393 // call stop for it, but keep track of the fact
12394 // that it was delivered.
12395 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12396 if (si != null) {
12397 si.deliveryCount = 0;
12398 si.doneExecutingCount++;
12399 // Don't stop if killed.
12400 r.stopIfKilled = true;
12401 }
12402 break;
12403 }
12404 default:
12405 throw new IllegalArgumentException(
12406 "Unknown service start result: " + res);
12407 }
12408 if (res == Service.START_STICKY_COMPATIBILITY) {
12409 r.callStart = false;
12410 }
12411 }
12412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012413 final long origId = Binder.clearCallingIdentity();
12414 serviceDoneExecutingLocked(r, inStopping);
12415 Binder.restoreCallingIdentity(origId);
12416 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012417 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012418 + " with token " + token);
12419 }
12420 }
12421 }
12422
12423 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
12424 r.executeNesting--;
12425 if (r.executeNesting <= 0 && r.app != null) {
12426 r.app.executingServices.remove(r);
12427 if (r.app.executingServices.size() == 0) {
12428 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
12429 }
12430 if (inStopping) {
12431 mStoppingServices.remove(r);
12432 }
12433 updateOomAdjLocked(r.app);
12434 }
12435 }
12436
12437 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012438 String anrMessage = null;
12439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012440 synchronized(this) {
12441 if (proc.executingServices.size() == 0 || proc.thread == null) {
12442 return;
12443 }
12444 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12445 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12446 ServiceRecord timeout = null;
12447 long nextTime = 0;
12448 while (it.hasNext()) {
12449 ServiceRecord sr = it.next();
12450 if (sr.executingStart < maxTime) {
12451 timeout = sr;
12452 break;
12453 }
12454 if (sr.executingStart > nextTime) {
12455 nextTime = sr.executingStart;
12456 }
12457 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012458 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012459 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012460 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012461 } else {
12462 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12463 msg.obj = proc;
12464 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12465 }
12466 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012467
12468 if (anrMessage != null) {
12469 appNotResponding(proc, null, null, anrMessage);
12470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012471 }
12472
12473 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012474 // BACKUP AND RESTORE
12475 // =========================================================
12476
12477 // Cause the target app to be launched if necessary and its backup agent
12478 // instantiated. The backup agent will invoke backupAgentCreated() on the
12479 // activity manager to announce its creation.
12480 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012481 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012482 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12483
12484 synchronized(this) {
12485 // !!! TODO: currently no check here that we're already bound
12486 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12487 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12488 synchronized (stats) {
12489 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12490 }
12491
12492 BackupRecord r = new BackupRecord(ss, app, backupMode);
12493 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12494 // startProcessLocked() returns existing proc's record if it's already running
12495 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012496 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012497 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012498 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012499 return false;
12500 }
12501
12502 r.app = proc;
12503 mBackupTarget = r;
12504 mBackupAppName = app.packageName;
12505
Christopher Tate6fa95972009-06-05 18:43:55 -070012506 // Try not to kill the process during backup
12507 updateOomAdjLocked(proc);
12508
Christopher Tate181fafa2009-05-14 11:12:14 -070012509 // If the process is already attached, schedule the creation of the backup agent now.
12510 // If it is not yet live, this will be done when it attaches to the framework.
12511 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012512 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012513 try {
12514 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12515 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012516 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012517 }
12518 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012519 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012520 }
12521 // Invariants: at this point, the target app process exists and the application
12522 // is either already running or in the process of coming up. mBackupTarget and
12523 // mBackupAppName describe the app, so that when it binds back to the AM we
12524 // know that it's scheduled for a backup-agent operation.
12525 }
12526
12527 return true;
12528 }
12529
12530 // A backup agent has just come up
12531 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012532 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012533 + " = " + agent);
12534
12535 synchronized(this) {
12536 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012537 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012538 return;
12539 }
12540
Christopher Tate043dadc2009-06-02 16:11:00 -070012541 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012542 try {
12543 IBackupManager bm = IBackupManager.Stub.asInterface(
12544 ServiceManager.getService(Context.BACKUP_SERVICE));
12545 bm.agentConnected(agentPackageName, agent);
12546 } catch (RemoteException e) {
12547 // can't happen; the backup manager service is local
12548 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012549 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012550 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012551 } finally {
12552 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012553 }
12554 }
12555 }
12556
12557 // done with this agent
12558 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012559 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012560 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012561 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012562 return;
12563 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012564
12565 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012566 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012567 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012568 return;
12569 }
12570
Christopher Tate181fafa2009-05-14 11:12:14 -070012571 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012572 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012573 return;
12574 }
12575
Christopher Tate6fa95972009-06-05 18:43:55 -070012576 ProcessRecord proc = mBackupTarget.app;
12577 mBackupTarget = null;
12578 mBackupAppName = null;
12579
12580 // Not backing this app up any more; reset its OOM adjustment
12581 updateOomAdjLocked(proc);
12582
Christopher Tatec7b31e32009-06-10 15:49:30 -070012583 // If the app crashed during backup, 'thread' will be null here
12584 if (proc.thread != null) {
12585 try {
12586 proc.thread.scheduleDestroyBackupAgent(appInfo);
12587 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012588 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012589 e.printStackTrace();
12590 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012591 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012592 }
12593 }
12594 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012595 // BROADCASTS
12596 // =========================================================
12597
Josh Bartel7f208742010-02-25 11:01:44 -060012598 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012599 List cur) {
12600 final ContentResolver resolver = mContext.getContentResolver();
12601 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12602 if (list == null) {
12603 return cur;
12604 }
12605 int N = list.size();
12606 for (int i=0; i<N; i++) {
12607 Intent intent = list.get(i);
12608 if (filter.match(resolver, intent, true, TAG) >= 0) {
12609 if (cur == null) {
12610 cur = new ArrayList<Intent>();
12611 }
12612 cur.add(intent);
12613 }
12614 }
12615 return cur;
12616 }
12617
12618 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012619 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012620 + mBroadcastsScheduled);
12621
12622 if (mBroadcastsScheduled) {
12623 return;
12624 }
12625 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12626 mBroadcastsScheduled = true;
12627 }
12628
12629 public Intent registerReceiver(IApplicationThread caller,
12630 IIntentReceiver receiver, IntentFilter filter, String permission) {
12631 synchronized(this) {
12632 ProcessRecord callerApp = null;
12633 if (caller != null) {
12634 callerApp = getRecordForAppLocked(caller);
12635 if (callerApp == null) {
12636 throw new SecurityException(
12637 "Unable to find app for caller " + caller
12638 + " (pid=" + Binder.getCallingPid()
12639 + ") when registering receiver " + receiver);
12640 }
12641 }
12642
12643 List allSticky = null;
12644
12645 // Look for any matching sticky broadcasts...
12646 Iterator actions = filter.actionsIterator();
12647 if (actions != null) {
12648 while (actions.hasNext()) {
12649 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012650 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012651 }
12652 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012653 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012654 }
12655
12656 // The first sticky in the list is returned directly back to
12657 // the client.
12658 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12659
Joe Onorato8a9b2202010-02-26 18:56:32 -080012660 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012661 + ": " + sticky);
12662
12663 if (receiver == null) {
12664 return sticky;
12665 }
12666
12667 ReceiverList rl
12668 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12669 if (rl == null) {
12670 rl = new ReceiverList(this, callerApp,
12671 Binder.getCallingPid(),
12672 Binder.getCallingUid(), receiver);
12673 if (rl.app != null) {
12674 rl.app.receivers.add(rl);
12675 } else {
12676 try {
12677 receiver.asBinder().linkToDeath(rl, 0);
12678 } catch (RemoteException e) {
12679 return sticky;
12680 }
12681 rl.linkedToDeath = true;
12682 }
12683 mRegisteredReceivers.put(receiver.asBinder(), rl);
12684 }
12685 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12686 rl.add(bf);
12687 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012688 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012689 }
12690 mReceiverResolver.addFilter(bf);
12691
12692 // Enqueue broadcasts for all existing stickies that match
12693 // this filter.
12694 if (allSticky != null) {
12695 ArrayList receivers = new ArrayList();
12696 receivers.add(bf);
12697
12698 int N = allSticky.size();
12699 for (int i=0; i<N; i++) {
12700 Intent intent = (Intent)allSticky.get(i);
12701 BroadcastRecord r = new BroadcastRecord(intent, null,
12702 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012703 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012704 if (mParallelBroadcasts.size() == 0) {
12705 scheduleBroadcastsLocked();
12706 }
12707 mParallelBroadcasts.add(r);
12708 }
12709 }
12710
12711 return sticky;
12712 }
12713 }
12714
12715 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012716 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012717
12718 boolean doNext = false;
12719
12720 synchronized(this) {
12721 ReceiverList rl
12722 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12723 if (rl != null) {
12724 if (rl.curBroadcast != null) {
12725 BroadcastRecord r = rl.curBroadcast;
12726 doNext = finishReceiverLocked(
12727 receiver.asBinder(), r.resultCode, r.resultData,
12728 r.resultExtras, r.resultAbort, true);
12729 }
12730
12731 if (rl.app != null) {
12732 rl.app.receivers.remove(rl);
12733 }
12734 removeReceiverLocked(rl);
12735 if (rl.linkedToDeath) {
12736 rl.linkedToDeath = false;
12737 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12738 }
12739 }
12740 }
12741
12742 if (!doNext) {
12743 return;
12744 }
12745
12746 final long origId = Binder.clearCallingIdentity();
12747 processNextBroadcast(false);
12748 trimApplications();
12749 Binder.restoreCallingIdentity(origId);
12750 }
12751
12752 void removeReceiverLocked(ReceiverList rl) {
12753 mRegisteredReceivers.remove(rl.receiver.asBinder());
12754 int N = rl.size();
12755 for (int i=0; i<N; i++) {
12756 mReceiverResolver.removeFilter(rl.get(i));
12757 }
12758 }
12759
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012760 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12761 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12762 ProcessRecord r = mLruProcesses.get(i);
12763 if (r.thread != null) {
12764 try {
12765 r.thread.dispatchPackageBroadcast(cmd, packages);
12766 } catch (RemoteException ex) {
12767 }
12768 }
12769 }
12770 }
12771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012772 private final int broadcastIntentLocked(ProcessRecord callerApp,
12773 String callerPackage, Intent intent, String resolvedType,
12774 IIntentReceiver resultTo, int resultCode, String resultData,
12775 Bundle map, String requiredPermission,
12776 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12777 intent = new Intent(intent);
12778
Joe Onorato8a9b2202010-02-26 18:56:32 -080012779 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012780 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12781 + " ordered=" + ordered);
12782 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012783 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012784 }
12785
12786 // Handle special intents: if this broadcast is from the package
12787 // manager about a package being removed, we need to remove all of
12788 // its activities from the history stack.
12789 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12790 intent.getAction());
12791 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12792 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012793 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012794 || uidRemoved) {
12795 if (checkComponentPermission(
12796 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12797 callingPid, callingUid, -1)
12798 == PackageManager.PERMISSION_GRANTED) {
12799 if (uidRemoved) {
12800 final Bundle intentExtras = intent.getExtras();
12801 final int uid = intentExtras != null
12802 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12803 if (uid >= 0) {
12804 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12805 synchronized (bs) {
12806 bs.removeUidStatsLocked(uid);
12807 }
12808 }
12809 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012810 // If resources are unvailble just force stop all
12811 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012812 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012813 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12814 if (list != null && (list.length > 0)) {
12815 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012816 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012817 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012818 sendPackageBroadcastLocked(
12819 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012820 }
12821 } else {
12822 Uri data = intent.getData();
12823 String ssp;
12824 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12825 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12826 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012827 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012828 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012829 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
12830 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12831 new String[] {ssp});
12832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012833 }
12834 }
12835 }
12836 } else {
12837 String msg = "Permission Denial: " + intent.getAction()
12838 + " broadcast from " + callerPackage + " (pid=" + callingPid
12839 + ", uid=" + callingUid + ")"
12840 + " requires "
12841 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012842 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012843 throw new SecurityException(msg);
12844 }
12845 }
12846
12847 /*
12848 * If this is the time zone changed action, queue up a message that will reset the timezone
12849 * of all currently running processes. This message will get queued up before the broadcast
12850 * happens.
12851 */
12852 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12853 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12854 }
12855
Dianne Hackborn854060af2009-07-09 18:14:31 -070012856 /*
12857 * Prevent non-system code (defined here to be non-persistent
12858 * processes) from sending protected broadcasts.
12859 */
12860 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12861 || callingUid == Process.SHELL_UID || callingUid == 0) {
12862 // Always okay.
12863 } else if (callerApp == null || !callerApp.persistent) {
12864 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012865 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070012866 intent.getAction())) {
12867 String msg = "Permission Denial: not allowed to send broadcast "
12868 + intent.getAction() + " from pid="
12869 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012870 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012871 throw new SecurityException(msg);
12872 }
12873 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012874 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012875 return BROADCAST_SUCCESS;
12876 }
12877 }
12878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012879 // Add to the sticky list if requested.
12880 if (sticky) {
12881 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12882 callingPid, callingUid)
12883 != PackageManager.PERMISSION_GRANTED) {
12884 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12885 + callingPid + ", uid=" + callingUid
12886 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012887 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012888 throw new SecurityException(msg);
12889 }
12890 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012891 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012892 + " and enforce permission " + requiredPermission);
12893 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12894 }
12895 if (intent.getComponent() != null) {
12896 throw new SecurityException(
12897 "Sticky broadcasts can't target a specific component");
12898 }
12899 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12900 if (list == null) {
12901 list = new ArrayList<Intent>();
12902 mStickyBroadcasts.put(intent.getAction(), list);
12903 }
12904 int N = list.size();
12905 int i;
12906 for (i=0; i<N; i++) {
12907 if (intent.filterEquals(list.get(i))) {
12908 // This sticky already exists, replace it.
12909 list.set(i, new Intent(intent));
12910 break;
12911 }
12912 }
12913 if (i >= N) {
12914 list.add(new Intent(intent));
12915 }
12916 }
12917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012918 // Figure out who all will receive this broadcast.
12919 List receivers = null;
12920 List<BroadcastFilter> registeredReceivers = null;
12921 try {
12922 if (intent.getComponent() != null) {
12923 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012924 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012925 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012926 if (ai != null) {
12927 receivers = new ArrayList();
12928 ResolveInfo ri = new ResolveInfo();
12929 ri.activityInfo = ai;
12930 receivers.add(ri);
12931 }
12932 } else {
12933 // Need to resolve the intent to interested receivers...
12934 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12935 == 0) {
12936 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012937 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012938 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012939 }
Mihai Preda074edef2009-05-18 17:13:31 +020012940 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012941 }
12942 } catch (RemoteException ex) {
12943 // pm is in same process, this will never happen.
12944 }
12945
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012946 final boolean replacePending =
12947 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12948
Joe Onorato8a9b2202010-02-26 18:56:32 -080012949 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012950 + " replacePending=" + replacePending);
12951
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012952 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12953 if (!ordered && NR > 0) {
12954 // If we are not serializing this broadcast, then send the
12955 // registered receivers separately so they don't wait for the
12956 // components to be launched.
12957 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12958 callerPackage, callingPid, callingUid, requiredPermission,
12959 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012960 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012961 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012962 TAG, "Enqueueing parallel broadcast " + r
12963 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012964 boolean replaced = false;
12965 if (replacePending) {
12966 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12967 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012968 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012969 "***** DROPPING PARALLEL: " + intent);
12970 mParallelBroadcasts.set(i, r);
12971 replaced = true;
12972 break;
12973 }
12974 }
12975 }
12976 if (!replaced) {
12977 mParallelBroadcasts.add(r);
12978 scheduleBroadcastsLocked();
12979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012980 registeredReceivers = null;
12981 NR = 0;
12982 }
12983
12984 // Merge into one list.
12985 int ir = 0;
12986 if (receivers != null) {
12987 // A special case for PACKAGE_ADDED: do not allow the package
12988 // being added to see this broadcast. This prevents them from
12989 // using this as a back door to get run as soon as they are
12990 // installed. Maybe in the future we want to have a special install
12991 // broadcast or such for apps, but we'd like to deliberately make
12992 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012993 String skipPackages[] = null;
12994 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12995 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12996 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12997 Uri data = intent.getData();
12998 if (data != null) {
12999 String pkgName = data.getSchemeSpecificPart();
13000 if (pkgName != null) {
13001 skipPackages = new String[] { pkgName };
13002 }
13003 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080013004 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013005 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070013006 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080013007 if (skipPackages != null && (skipPackages.length > 0)) {
13008 for (String skipPackage : skipPackages) {
13009 if (skipPackage != null) {
13010 int NT = receivers.size();
13011 for (int it=0; it<NT; it++) {
13012 ResolveInfo curt = (ResolveInfo)receivers.get(it);
13013 if (curt.activityInfo.packageName.equals(skipPackage)) {
13014 receivers.remove(it);
13015 it--;
13016 NT--;
13017 }
13018 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013019 }
13020 }
13021 }
13022
13023 int NT = receivers != null ? receivers.size() : 0;
13024 int it = 0;
13025 ResolveInfo curt = null;
13026 BroadcastFilter curr = null;
13027 while (it < NT && ir < NR) {
13028 if (curt == null) {
13029 curt = (ResolveInfo)receivers.get(it);
13030 }
13031 if (curr == null) {
13032 curr = registeredReceivers.get(ir);
13033 }
13034 if (curr.getPriority() >= curt.priority) {
13035 // Insert this broadcast record into the final list.
13036 receivers.add(it, curr);
13037 ir++;
13038 curr = null;
13039 it++;
13040 NT++;
13041 } else {
13042 // Skip to the next ResolveInfo in the final list.
13043 it++;
13044 curt = null;
13045 }
13046 }
13047 }
13048 while (ir < NR) {
13049 if (receivers == null) {
13050 receivers = new ArrayList();
13051 }
13052 receivers.add(registeredReceivers.get(ir));
13053 ir++;
13054 }
13055
13056 if ((receivers != null && receivers.size() > 0)
13057 || resultTo != null) {
13058 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
13059 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013060 receivers, resultTo, resultCode, resultData, map, ordered,
13061 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013062 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013063 TAG, "Enqueueing ordered broadcast " + r
13064 + ": prev had " + mOrderedBroadcasts.size());
13065 if (DEBUG_BROADCAST) {
13066 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013067 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013068 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013069 boolean replaced = false;
13070 if (replacePending) {
13071 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
13072 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013073 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013074 "***** DROPPING ORDERED: " + intent);
13075 mOrderedBroadcasts.set(i, r);
13076 replaced = true;
13077 break;
13078 }
13079 }
13080 }
13081 if (!replaced) {
13082 mOrderedBroadcasts.add(r);
13083 scheduleBroadcastsLocked();
13084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013085 }
13086
13087 return BROADCAST_SUCCESS;
13088 }
13089
13090 public final int broadcastIntent(IApplicationThread caller,
13091 Intent intent, String resolvedType, IIntentReceiver resultTo,
13092 int resultCode, String resultData, Bundle map,
13093 String requiredPermission, boolean serialized, boolean sticky) {
13094 // Refuse possible leaked file descriptors
13095 if (intent != null && intent.hasFileDescriptors() == true) {
13096 throw new IllegalArgumentException("File descriptors passed in Intent");
13097 }
13098
13099 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013100 int flags = intent.getFlags();
13101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013102 if (!mSystemReady) {
13103 // if the caller really truly claims to know what they're doing, go
13104 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013105 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
13106 intent = new Intent(intent);
13107 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
13108 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080013109 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013110 + " before boot completion");
13111 throw new IllegalStateException("Cannot broadcast before boot completed");
13112 }
13113 }
13114
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013115 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
13116 throw new IllegalArgumentException(
13117 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
13118 }
13119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013120 final ProcessRecord callerApp = getRecordForAppLocked(caller);
13121 final int callingPid = Binder.getCallingPid();
13122 final int callingUid = Binder.getCallingUid();
13123 final long origId = Binder.clearCallingIdentity();
13124 int res = broadcastIntentLocked(callerApp,
13125 callerApp != null ? callerApp.info.packageName : null,
13126 intent, resolvedType, resultTo,
13127 resultCode, resultData, map, requiredPermission, serialized,
13128 sticky, callingPid, callingUid);
13129 Binder.restoreCallingIdentity(origId);
13130 return res;
13131 }
13132 }
13133
13134 int broadcastIntentInPackage(String packageName, int uid,
13135 Intent intent, String resolvedType, IIntentReceiver resultTo,
13136 int resultCode, String resultData, Bundle map,
13137 String requiredPermission, boolean serialized, boolean sticky) {
13138 synchronized(this) {
13139 final long origId = Binder.clearCallingIdentity();
13140 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
13141 resultTo, resultCode, resultData, map, requiredPermission,
13142 serialized, sticky, -1, uid);
13143 Binder.restoreCallingIdentity(origId);
13144 return res;
13145 }
13146 }
13147
13148 public final void unbroadcastIntent(IApplicationThread caller,
13149 Intent intent) {
13150 // Refuse possible leaked file descriptors
13151 if (intent != null && intent.hasFileDescriptors() == true) {
13152 throw new IllegalArgumentException("File descriptors passed in Intent");
13153 }
13154
13155 synchronized(this) {
13156 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
13157 != PackageManager.PERMISSION_GRANTED) {
13158 String msg = "Permission Denial: unbroadcastIntent() from pid="
13159 + Binder.getCallingPid()
13160 + ", uid=" + Binder.getCallingUid()
13161 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013162 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013163 throw new SecurityException(msg);
13164 }
13165 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
13166 if (list != null) {
13167 int N = list.size();
13168 int i;
13169 for (i=0; i<N; i++) {
13170 if (intent.filterEquals(list.get(i))) {
13171 list.remove(i);
13172 break;
13173 }
13174 }
13175 }
13176 }
13177 }
13178
13179 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
13180 String resultData, Bundle resultExtras, boolean resultAbort,
13181 boolean explicit) {
13182 if (mOrderedBroadcasts.size() == 0) {
13183 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013184 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013185 }
13186 return false;
13187 }
13188 BroadcastRecord r = mOrderedBroadcasts.get(0);
13189 if (r.receiver == null) {
13190 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013191 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013192 }
13193 return false;
13194 }
13195 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013196 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013197 return false;
13198 }
13199 int state = r.state;
13200 r.state = r.IDLE;
13201 if (state == r.IDLE) {
13202 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013203 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013204 }
13205 }
13206 r.receiver = null;
13207 r.intent.setComponent(null);
13208 if (r.curApp != null) {
13209 r.curApp.curReceiver = null;
13210 }
13211 if (r.curFilter != null) {
13212 r.curFilter.receiverList.curBroadcast = null;
13213 }
13214 r.curFilter = null;
13215 r.curApp = null;
13216 r.curComponent = null;
13217 r.curReceiver = null;
13218 mPendingBroadcast = null;
13219
13220 r.resultCode = resultCode;
13221 r.resultData = resultData;
13222 r.resultExtras = resultExtras;
13223 r.resultAbort = resultAbort;
13224
13225 // We will process the next receiver right now if this is finishing
13226 // an app receiver (which is always asynchronous) or after we have
13227 // come back from calling a receiver.
13228 return state == BroadcastRecord.APP_RECEIVE
13229 || state == BroadcastRecord.CALL_DONE_RECEIVE;
13230 }
13231
13232 public void finishReceiver(IBinder who, int resultCode, String resultData,
13233 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013234 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013235
13236 // Refuse possible leaked file descriptors
13237 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
13238 throw new IllegalArgumentException("File descriptors passed in Bundle");
13239 }
13240
13241 boolean doNext;
13242
13243 final long origId = Binder.clearCallingIdentity();
13244
13245 synchronized(this) {
13246 doNext = finishReceiverLocked(
13247 who, resultCode, resultData, resultExtras, resultAbort, true);
13248 }
13249
13250 if (doNext) {
13251 processNextBroadcast(false);
13252 }
13253 trimApplications();
13254
13255 Binder.restoreCallingIdentity(origId);
13256 }
13257
13258 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
13259 if (r.nextReceiver > 0) {
13260 Object curReceiver = r.receivers.get(r.nextReceiver-1);
13261 if (curReceiver instanceof BroadcastFilter) {
13262 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080013263 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013264 System.identityHashCode(r),
13265 r.intent.getAction(),
13266 r.nextReceiver - 1,
13267 System.identityHashCode(bf));
13268 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080013269 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013270 System.identityHashCode(r),
13271 r.intent.getAction(),
13272 r.nextReceiver - 1,
13273 ((ResolveInfo)curReceiver).toString());
13274 }
13275 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013276 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013277 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013278 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013279 System.identityHashCode(r),
13280 r.intent.getAction(),
13281 r.nextReceiver,
13282 "NONE");
13283 }
13284 }
13285
13286 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013287 ProcessRecord app = null;
13288 String anrMessage = null;
13289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013290 synchronized (this) {
13291 if (mOrderedBroadcasts.size() == 0) {
13292 return;
13293 }
13294 long now = SystemClock.uptimeMillis();
13295 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013296 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013297 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013298 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013299 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013300 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013301 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013302 return;
13303 }
13304
Joe Onorato8a9b2202010-02-26 18:56:32 -080013305 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013306 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013307 r.anrCount++;
13308
13309 // Current receiver has passed its expiration date.
13310 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013311 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013312 return;
13313 }
13314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013315 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013316 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013317 logBroadcastReceiverDiscard(r);
13318 if (curReceiver instanceof BroadcastFilter) {
13319 BroadcastFilter bf = (BroadcastFilter)curReceiver;
13320 if (bf.receiverList.pid != 0
13321 && bf.receiverList.pid != MY_PID) {
13322 synchronized (this.mPidsSelfLocked) {
13323 app = this.mPidsSelfLocked.get(
13324 bf.receiverList.pid);
13325 }
13326 }
13327 } else {
13328 app = r.curApp;
13329 }
13330
13331 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013332 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013333 }
13334
13335 if (mPendingBroadcast == r) {
13336 mPendingBroadcast = null;
13337 }
13338
13339 // Move on to the next receiver.
13340 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13341 r.resultExtras, r.resultAbort, true);
13342 scheduleBroadcastsLocked();
13343 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013344
13345 if (anrMessage != null) {
13346 appNotResponding(app, null, null, anrMessage);
13347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013348 }
13349
13350 private final void processCurBroadcastLocked(BroadcastRecord r,
13351 ProcessRecord app) throws RemoteException {
13352 if (app.thread == null) {
13353 throw new RemoteException();
13354 }
13355 r.receiver = app.thread.asBinder();
13356 r.curApp = app;
13357 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013358 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013359
13360 // Tell the application to launch this receiver.
13361 r.intent.setComponent(r.curComponent);
13362
13363 boolean started = false;
13364 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013365 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013366 "Delivering to component " + r.curComponent
13367 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070013368 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013369 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
13370 r.resultCode, r.resultData, r.resultExtras, r.ordered);
13371 started = true;
13372 } finally {
13373 if (!started) {
13374 r.receiver = null;
13375 r.curApp = null;
13376 app.curReceiver = null;
13377 }
13378 }
13379
13380 }
13381
13382 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013383 Intent intent, int resultCode, String data, Bundle extras,
13384 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013385 if (app != null && app.thread != null) {
13386 // If we have an app thread, do the call through that so it is
13387 // correctly ordered with other one-way calls.
13388 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013389 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013390 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013391 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013392 }
13393 }
13394
13395 private final void deliverToRegisteredReceiver(BroadcastRecord r,
13396 BroadcastFilter filter, boolean ordered) {
13397 boolean skip = false;
13398 if (filter.requiredPermission != null) {
13399 int perm = checkComponentPermission(filter.requiredPermission,
13400 r.callingPid, r.callingUid, -1);
13401 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013402 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013403 + r.intent.toString()
13404 + " from " + r.callerPackage + " (pid="
13405 + r.callingPid + ", uid=" + r.callingUid + ")"
13406 + " requires " + filter.requiredPermission
13407 + " due to registered receiver " + filter);
13408 skip = true;
13409 }
13410 }
13411 if (r.requiredPermission != null) {
13412 int perm = checkComponentPermission(r.requiredPermission,
13413 filter.receiverList.pid, filter.receiverList.uid, -1);
13414 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013415 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013416 + r.intent.toString()
13417 + " to " + filter.receiverList.app
13418 + " (pid=" + filter.receiverList.pid
13419 + ", uid=" + filter.receiverList.uid + ")"
13420 + " requires " + r.requiredPermission
13421 + " due to sender " + r.callerPackage
13422 + " (uid " + r.callingUid + ")");
13423 skip = true;
13424 }
13425 }
13426
13427 if (!skip) {
13428 // If this is not being sent as an ordered broadcast, then we
13429 // don't want to touch the fields that keep track of the current
13430 // state of ordered broadcasts.
13431 if (ordered) {
13432 r.receiver = filter.receiverList.receiver.asBinder();
13433 r.curFilter = filter;
13434 filter.receiverList.curBroadcast = r;
13435 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013436 if (filter.receiverList.app != null) {
13437 // Bump hosting application to no longer be in background
13438 // scheduling class. Note that we can't do that if there
13439 // isn't an app... but we can only be in that case for
13440 // things that directly call the IActivityManager API, which
13441 // are already core system stuff so don't matter for this.
13442 r.curApp = filter.receiverList.app;
13443 filter.receiverList.app.curReceiver = r;
13444 updateOomAdjLocked();
13445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013446 }
13447 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013448 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013449 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013450 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013451 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013452 }
13453 performReceive(filter.receiverList.app, filter.receiverList.receiver,
13454 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013455 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013456 if (ordered) {
13457 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13458 }
13459 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013460 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013461 if (ordered) {
13462 r.receiver = null;
13463 r.curFilter = null;
13464 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013465 if (filter.receiverList.app != null) {
13466 filter.receiverList.app.curReceiver = null;
13467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013468 }
13469 }
13470 }
13471 }
13472
Dianne Hackborn12527f92009-11-11 17:39:50 -080013473 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13474 if (r.callingUid < 0) {
13475 // This was from a registerReceiver() call; ignore it.
13476 return;
13477 }
13478 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13479 MAX_BROADCAST_HISTORY-1);
13480 r.finishTime = SystemClock.uptimeMillis();
13481 mBroadcastHistory[0] = r;
13482 }
13483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013484 private final void processNextBroadcast(boolean fromMsg) {
13485 synchronized(this) {
13486 BroadcastRecord r;
13487
Joe Onorato8a9b2202010-02-26 18:56:32 -080013488 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013489 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013490 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013491
13492 updateCpuStats();
13493
13494 if (fromMsg) {
13495 mBroadcastsScheduled = false;
13496 }
13497
13498 // First, deliver any non-serialized broadcasts right away.
13499 while (mParallelBroadcasts.size() > 0) {
13500 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013501 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013502 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013503 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013504 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013505 for (int i=0; i<N; i++) {
13506 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013507 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013508 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013509 + target + ": " + r);
13510 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13511 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013512 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013513 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013514 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013515 }
13516
13517 // Now take care of the next serialized one...
13518
13519 // If we are waiting for a process to come up to handle the next
13520 // broadcast, then do nothing at this point. Just in case, we
13521 // check that the process we're waiting for still exists.
13522 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013523 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013524 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013525 + mPendingBroadcast.curApp);
13526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013527
13528 boolean isDead;
13529 synchronized (mPidsSelfLocked) {
13530 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13531 }
13532 if (!isDead) {
13533 // It's still alive, so keep waiting
13534 return;
13535 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013536 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013537 + " died before responding to broadcast");
13538 mPendingBroadcast = null;
13539 }
13540 }
13541
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013542 boolean looped = false;
13543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013544 do {
13545 if (mOrderedBroadcasts.size() == 0) {
13546 // No more broadcasts pending, so all done!
13547 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013548 if (looped) {
13549 // If we had finished the last ordered broadcast, then
13550 // make sure all processes have correct oom and sched
13551 // adjustments.
13552 updateOomAdjLocked();
13553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013554 return;
13555 }
13556 r = mOrderedBroadcasts.get(0);
13557 boolean forceReceive = false;
13558
13559 // Ensure that even if something goes awry with the timeout
13560 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013561 // and continue to make progress.
13562 //
13563 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
13564 // receivers don't get executed with with timeouts. They're intended for
13565 // one time heavy lifting after system upgrades and can take
13566 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013567 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013568 if (mSystemReady && r.dispatchTime > 0) {
13569 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013570 if ((numReceivers > 0) &&
13571 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013572 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013573 + " now=" + now
13574 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013575 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013576 + " intent=" + r.intent
13577 + " numReceivers=" + numReceivers
13578 + " nextReceiver=" + r.nextReceiver
13579 + " state=" + r.state);
13580 broadcastTimeout(); // forcibly finish this broadcast
13581 forceReceive = true;
13582 r.state = BroadcastRecord.IDLE;
13583 }
13584 }
13585
13586 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013587 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013588 "processNextBroadcast() called when not idle (state="
13589 + r.state + ")");
13590 return;
13591 }
13592
13593 if (r.receivers == null || r.nextReceiver >= numReceivers
13594 || r.resultAbort || forceReceive) {
13595 // No more receivers for this broadcast! Send the final
13596 // result if requested...
13597 if (r.resultTo != null) {
13598 try {
13599 if (DEBUG_BROADCAST) {
13600 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013601 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013602 + " seq=" + seq + " app=" + r.callerApp);
13603 }
13604 performReceive(r.callerApp, r.resultTo,
13605 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013606 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013607 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013608 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013609 }
13610 }
13611
Joe Onorato8a9b2202010-02-26 18:56:32 -080013612 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013613 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13614
Joe Onorato8a9b2202010-02-26 18:56:32 -080013615 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013616 + r);
13617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013618 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013619 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013620 mOrderedBroadcasts.remove(0);
13621 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013622 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013623 continue;
13624 }
13625 } while (r == null);
13626
13627 // Get the next receiver...
13628 int recIdx = r.nextReceiver++;
13629
13630 // Keep track of when this receiver started, and make sure there
13631 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013632 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013633 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013634 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013635
Joe Onorato8a9b2202010-02-26 18:56:32 -080013636 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013637 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013638 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013639 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013640 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013641 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013642 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013643 }
13644
13645 Object nextReceiver = r.receivers.get(recIdx);
13646 if (nextReceiver instanceof BroadcastFilter) {
13647 // Simple case: this is a registered receiver who gets
13648 // a direct call.
13649 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013650 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013651 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013652 + filter + ": " + r);
13653 deliverToRegisteredReceiver(r, filter, r.ordered);
13654 if (r.receiver == null || !r.ordered) {
13655 // The receiver has already finished, so schedule to
13656 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013657 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13658 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013659 r.state = BroadcastRecord.IDLE;
13660 scheduleBroadcastsLocked();
13661 }
13662 return;
13663 }
13664
13665 // Hard case: need to instantiate the receiver, possibly
13666 // starting its application process to host it.
13667
13668 ResolveInfo info =
13669 (ResolveInfo)nextReceiver;
13670
13671 boolean skip = false;
13672 int perm = checkComponentPermission(info.activityInfo.permission,
13673 r.callingPid, r.callingUid,
13674 info.activityInfo.exported
13675 ? -1 : info.activityInfo.applicationInfo.uid);
13676 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013677 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013678 + r.intent.toString()
13679 + " from " + r.callerPackage + " (pid=" + r.callingPid
13680 + ", uid=" + r.callingUid + ")"
13681 + " requires " + info.activityInfo.permission
13682 + " due to receiver " + info.activityInfo.packageName
13683 + "/" + info.activityInfo.name);
13684 skip = true;
13685 }
13686 if (r.callingUid != Process.SYSTEM_UID &&
13687 r.requiredPermission != null) {
13688 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013689 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013690 checkPermission(r.requiredPermission,
13691 info.activityInfo.applicationInfo.packageName);
13692 } catch (RemoteException e) {
13693 perm = PackageManager.PERMISSION_DENIED;
13694 }
13695 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013696 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013697 + r.intent + " to "
13698 + info.activityInfo.applicationInfo.packageName
13699 + " requires " + r.requiredPermission
13700 + " due to sender " + r.callerPackage
13701 + " (uid " + r.callingUid + ")");
13702 skip = true;
13703 }
13704 }
13705 if (r.curApp != null && r.curApp.crashing) {
13706 // If the target process is crashing, just skip it.
13707 skip = true;
13708 }
13709
13710 if (skip) {
13711 r.receiver = null;
13712 r.curFilter = null;
13713 r.state = BroadcastRecord.IDLE;
13714 scheduleBroadcastsLocked();
13715 return;
13716 }
13717
13718 r.state = BroadcastRecord.APP_RECEIVE;
13719 String targetProcess = info.activityInfo.processName;
13720 r.curComponent = new ComponentName(
13721 info.activityInfo.applicationInfo.packageName,
13722 info.activityInfo.name);
13723 r.curReceiver = info.activityInfo;
13724
13725 // Is this receiver's application already running?
13726 ProcessRecord app = getProcessRecordLocked(targetProcess,
13727 info.activityInfo.applicationInfo.uid);
13728 if (app != null && app.thread != null) {
13729 try {
13730 processCurBroadcastLocked(r, app);
13731 return;
13732 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013733 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013734 + r.curComponent, e);
13735 }
13736
13737 // If a dead object exception was thrown -- fall through to
13738 // restart the application.
13739 }
13740
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013741 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013742 if ((r.curApp=startProcessLocked(targetProcess,
13743 info.activityInfo.applicationInfo, true,
13744 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013745 "broadcast", r.curComponent,
13746 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13747 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013748 // Ah, this recipient is unavailable. Finish it if necessary,
13749 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013750 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013751 + info.activityInfo.applicationInfo.packageName + "/"
13752 + info.activityInfo.applicationInfo.uid + " for broadcast "
13753 + r.intent + ": process is bad");
13754 logBroadcastReceiverDiscard(r);
13755 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13756 r.resultExtras, r.resultAbort, true);
13757 scheduleBroadcastsLocked();
13758 r.state = BroadcastRecord.IDLE;
13759 return;
13760 }
13761
13762 mPendingBroadcast = r;
13763 }
13764 }
13765
13766 // =========================================================
13767 // INSTRUMENTATION
13768 // =========================================================
13769
13770 public boolean startInstrumentation(ComponentName className,
13771 String profileFile, int flags, Bundle arguments,
13772 IInstrumentationWatcher watcher) {
13773 // Refuse possible leaked file descriptors
13774 if (arguments != null && arguments.hasFileDescriptors()) {
13775 throw new IllegalArgumentException("File descriptors passed in Bundle");
13776 }
13777
13778 synchronized(this) {
13779 InstrumentationInfo ii = null;
13780 ApplicationInfo ai = null;
13781 try {
13782 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013783 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013784 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013785 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013786 } catch (PackageManager.NameNotFoundException e) {
13787 }
13788 if (ii == null) {
13789 reportStartInstrumentationFailure(watcher, className,
13790 "Unable to find instrumentation info for: " + className);
13791 return false;
13792 }
13793 if (ai == null) {
13794 reportStartInstrumentationFailure(watcher, className,
13795 "Unable to find instrumentation target package: " + ii.targetPackage);
13796 return false;
13797 }
13798
13799 int match = mContext.getPackageManager().checkSignatures(
13800 ii.targetPackage, ii.packageName);
13801 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13802 String msg = "Permission Denial: starting instrumentation "
13803 + className + " from pid="
13804 + Binder.getCallingPid()
13805 + ", uid=" + Binder.getCallingPid()
13806 + " not allowed because package " + ii.packageName
13807 + " does not have a signature matching the target "
13808 + ii.targetPackage;
13809 reportStartInstrumentationFailure(watcher, className, msg);
13810 throw new SecurityException(msg);
13811 }
13812
13813 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013814 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013815 ProcessRecord app = addAppLocked(ai);
13816 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013817 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013818 app.instrumentationProfileFile = profileFile;
13819 app.instrumentationArguments = arguments;
13820 app.instrumentationWatcher = watcher;
13821 app.instrumentationResultClass = className;
13822 Binder.restoreCallingIdentity(origId);
13823 }
13824
13825 return true;
13826 }
13827
13828 /**
13829 * Report errors that occur while attempting to start Instrumentation. Always writes the
13830 * error to the logs, but if somebody is watching, send the report there too. This enables
13831 * the "am" command to report errors with more information.
13832 *
13833 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13834 * @param cn The component name of the instrumentation.
13835 * @param report The error report.
13836 */
13837 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13838 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013839 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013840 try {
13841 if (watcher != null) {
13842 Bundle results = new Bundle();
13843 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13844 results.putString("Error", report);
13845 watcher.instrumentationStatus(cn, -1, results);
13846 }
13847 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013848 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013849 }
13850 }
13851
13852 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13853 if (app.instrumentationWatcher != null) {
13854 try {
13855 // NOTE: IInstrumentationWatcher *must* be oneway here
13856 app.instrumentationWatcher.instrumentationFinished(
13857 app.instrumentationClass,
13858 resultCode,
13859 results);
13860 } catch (RemoteException e) {
13861 }
13862 }
13863 app.instrumentationWatcher = null;
13864 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013865 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013866 app.instrumentationProfileFile = null;
13867 app.instrumentationArguments = null;
13868
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013869 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013870 }
13871
13872 public void finishInstrumentation(IApplicationThread target,
13873 int resultCode, Bundle results) {
13874 // Refuse possible leaked file descriptors
13875 if (results != null && results.hasFileDescriptors()) {
13876 throw new IllegalArgumentException("File descriptors passed in Intent");
13877 }
13878
13879 synchronized(this) {
13880 ProcessRecord app = getRecordForAppLocked(target);
13881 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013882 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013883 return;
13884 }
13885 final long origId = Binder.clearCallingIdentity();
13886 finishInstrumentationLocked(app, resultCode, results);
13887 Binder.restoreCallingIdentity(origId);
13888 }
13889 }
13890
13891 // =========================================================
13892 // CONFIGURATION
13893 // =========================================================
13894
13895 public ConfigurationInfo getDeviceConfigurationInfo() {
13896 ConfigurationInfo config = new ConfigurationInfo();
13897 synchronized (this) {
13898 config.reqTouchScreen = mConfiguration.touchscreen;
13899 config.reqKeyboardType = mConfiguration.keyboard;
13900 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013901 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13902 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013903 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13904 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013905 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13906 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013907 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13908 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013909 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013910 }
13911 return config;
13912 }
13913
13914 public Configuration getConfiguration() {
13915 Configuration ci;
13916 synchronized(this) {
13917 ci = new Configuration(mConfiguration);
13918 }
13919 return ci;
13920 }
13921
13922 public void updateConfiguration(Configuration values) {
13923 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13924 "updateConfiguration()");
13925
13926 synchronized(this) {
13927 if (values == null && mWindowManager != null) {
13928 // sentinel: fetch the current configuration from the window manager
13929 values = mWindowManager.computeNewConfiguration();
13930 }
13931
13932 final long origId = Binder.clearCallingIdentity();
13933 updateConfigurationLocked(values, null);
13934 Binder.restoreCallingIdentity(origId);
13935 }
13936 }
13937
13938 /**
13939 * Do either or both things: (1) change the current configuration, and (2)
13940 * make sure the given activity is running with the (now) current
13941 * configuration. Returns true if the activity has been left running, or
13942 * false if <var>starting</var> is being destroyed to match the new
13943 * configuration.
13944 */
13945 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013946 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013947 int changes = 0;
13948
13949 boolean kept = true;
13950
13951 if (values != null) {
13952 Configuration newConfig = new Configuration(mConfiguration);
13953 changes = newConfig.updateFrom(values);
13954 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013955 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013956 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013957 }
13958
Doug Zongker2bec3d42009-12-04 12:52:44 -080013959 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013960
13961 if (values.locale != null) {
13962 saveLocaleLocked(values.locale,
13963 !values.locale.equals(mConfiguration.locale),
13964 values.userSetLocale);
13965 }
13966
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013967 mConfigurationSeq++;
13968 if (mConfigurationSeq <= 0) {
13969 mConfigurationSeq = 1;
13970 }
13971 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013972 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013973 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013974
13975 AttributeCache ac = AttributeCache.instance();
13976 if (ac != null) {
13977 ac.updateConfiguration(mConfiguration);
13978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013979
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013980 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13981 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13982 msg.obj = new Configuration(mConfiguration);
13983 mHandler.sendMessage(msg);
13984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013985
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013986 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13987 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013988 try {
13989 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013990 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013991 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013992 app.thread.scheduleConfigurationChanged(mConfiguration);
13993 }
13994 } catch (Exception e) {
13995 }
13996 }
13997 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013998 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13999 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014000 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
14001 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080014002 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
14003 broadcastIntentLocked(null, null,
14004 new Intent(Intent.ACTION_LOCALE_CHANGED),
14005 null, null, 0, null, null,
14006 null, false, false, MY_PID, Process.SYSTEM_UID);
14007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014008 }
14009 }
14010
14011 if (changes != 0 && starting == null) {
14012 // If the configuration changed, and the caller is not already
14013 // in the process of starting an activity, then find the top
14014 // activity to check if its configuration needs to change.
14015 starting = topRunningActivityLocked(null);
14016 }
14017
14018 if (starting != null) {
14019 kept = ensureActivityConfigurationLocked(starting, changes);
14020 if (kept) {
14021 // If this didn't result in the starting activity being
14022 // destroyed, then we need to make sure at this point that all
14023 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014024 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014025 + ", ensuring others are correct.");
14026 ensureActivitiesVisibleLocked(starting, changes);
14027 }
14028 }
14029
Dianne Hackborne36d6e22010-02-17 19:46:25 -080014030 if (values != null && mWindowManager != null) {
14031 mWindowManager.setNewConfiguration(mConfiguration);
14032 }
14033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014034 return kept;
14035 }
14036
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014037 private final boolean relaunchActivityLocked(ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014038 int changes, boolean andResume) {
14039 List<ResultInfo> results = null;
14040 List<Intent> newIntents = null;
14041 if (andResume) {
14042 results = r.results;
14043 newIntents = r.newIntents;
14044 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014045 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014046 + " with results=" + results + " newIntents=" + newIntents
14047 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080014048 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
14049 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014050 r.task.taskId, r.shortComponentName);
14051
14052 r.startFreezingScreenLocked(r.app, 0);
14053
14054 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014055 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014056 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080014057 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014058 // Note: don't need to call pauseIfSleepingLocked() here, because
14059 // the caller will only pass in 'andResume' if this activity is
14060 // currently resumed, which implies we aren't sleeping.
14061 } catch (RemoteException e) {
14062 return false;
14063 }
14064
14065 if (andResume) {
14066 r.results = null;
14067 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070014068 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014069 }
14070
14071 return true;
14072 }
14073
14074 /**
14075 * Make sure the given activity matches the current configuration. Returns
14076 * false if the activity had to be destroyed. Returns true if the
14077 * configuration is the same, or the activity will remain running as-is
14078 * for whatever reason. Ensures the HistoryRecord is updated with the
14079 * correct configuration and all other bookkeeping is handled.
14080 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014081 private final boolean ensureActivityConfigurationLocked(ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014082 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070014083 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070014084 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
14085 "Skipping config check (will change): " + r);
14086 return true;
14087 }
14088
Joe Onorato8a9b2202010-02-26 18:56:32 -080014089 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014090 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014091
14092 // Short circuit: if the two configurations are the exact same
14093 // object (the common case), then there is nothing to do.
14094 Configuration newConfig = mConfiguration;
14095 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014096 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014097 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014098 return true;
14099 }
14100
14101 // We don't worry about activities that are finishing.
14102 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014103 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014104 "Configuration doesn't matter in finishing " + r);
14105 r.stopFreezingScreenLocked(false);
14106 return true;
14107 }
14108
14109 // Okay we now are going to make this activity have the new config.
14110 // But then we need to figure out how it needs to deal with that.
14111 Configuration oldConfig = r.configuration;
14112 r.configuration = newConfig;
14113
14114 // If the activity isn't currently running, just leave the new
14115 // configuration and it will pick that up next time it starts.
14116 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014117 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014118 "Configuration doesn't matter not running " + r);
14119 r.stopFreezingScreenLocked(false);
14120 return true;
14121 }
14122
14123 // If the activity isn't persistent, there is a chance we will
14124 // need to restart it.
14125 if (!r.persistent) {
14126
14127 // Figure out what has changed between the two configurations.
14128 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014129 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014130 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014131 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014132 + Integer.toHexString(r.info.configChanges)
14133 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014134 }
14135 if ((changes&(~r.info.configChanges)) != 0) {
14136 // Aha, the activity isn't handling the change, so DIE DIE DIE.
14137 r.configChangeFlags |= changes;
14138 r.startFreezingScreenLocked(r.app, globalChanges);
14139 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014140 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014141 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014142 destroyActivityLocked(r, true);
14143 } else if (r.state == ActivityState.PAUSING) {
14144 // A little annoying: we are waiting for this activity to
14145 // finish pausing. Let's not do anything now, but just
14146 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014147 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014148 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014149 r.configDestroy = true;
14150 return true;
14151 } else if (r.state == ActivityState.RESUMED) {
14152 // Try to optimize this case: the configuration is changing
14153 // and we need to restart the top, resumed activity.
14154 // Instead of doing the normal handshaking, just say
14155 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080014156 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014157 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014158 relaunchActivityLocked(r, r.configChangeFlags, true);
14159 r.configChangeFlags = 0;
14160 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014161 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014162 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014163 relaunchActivityLocked(r, r.configChangeFlags, false);
14164 r.configChangeFlags = 0;
14165 }
14166
14167 // All done... tell the caller we weren't able to keep this
14168 // activity around.
14169 return false;
14170 }
14171 }
14172
14173 // Default case: the activity can handle this new configuration, so
14174 // hand it over. Note that we don't need to give it the new
14175 // configuration, since we always send configuration changes to all
14176 // process when they happen so it can just use whatever configuration
14177 // it last got.
14178 if (r.app != null && r.app.thread != null) {
14179 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014180 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014181 r.app.thread.scheduleActivityConfigurationChanged(r);
14182 } catch (RemoteException e) {
14183 // If process died, whatever.
14184 }
14185 }
14186 r.stopFreezingScreenLocked(false);
14187
14188 return true;
14189 }
14190
14191 /**
14192 * Save the locale. You must be inside a synchronized (this) block.
14193 */
14194 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
14195 if(isDiff) {
14196 SystemProperties.set("user.language", l.getLanguage());
14197 SystemProperties.set("user.region", l.getCountry());
14198 }
14199
14200 if(isPersist) {
14201 SystemProperties.set("persist.sys.language", l.getLanguage());
14202 SystemProperties.set("persist.sys.country", l.getCountry());
14203 SystemProperties.set("persist.sys.localevar", l.getVariant());
14204 }
14205 }
14206
14207 // =========================================================
14208 // LIFETIME MANAGEMENT
14209 // =========================================================
14210
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014211 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
14212 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014213 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014214 // This adjustment has already been computed. If we are calling
14215 // from the top, we may have already computed our adjustment with
14216 // an earlier hidden adjustment that isn't really for us... if
14217 // so, use the new hidden adjustment.
14218 if (!recursed && app.hidden) {
14219 app.curAdj = hiddenAdj;
14220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014221 return app.curAdj;
14222 }
14223
14224 if (app.thread == null) {
14225 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014226 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014227 return (app.curAdj=EMPTY_APP_ADJ);
14228 }
14229
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014230 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
14231 // The max adjustment doesn't allow this app to be anything
14232 // below foreground, so it is not worth doing work for it.
14233 app.adjType = "fixed";
14234 app.adjSeq = mAdjSeq;
14235 app.curRawAdj = app.maxAdj;
14236 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
14237 return (app.curAdj=app.maxAdj);
14238 }
14239
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014240 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014241 app.adjSource = null;
14242 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014243 app.empty = false;
14244 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014245
The Android Open Source Project4df24232009-03-05 14:34:35 -080014246 // Determine the importance of the process, starting with most
14247 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014248 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014249 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014250 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014251 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014252 // The last app on the list is the foreground app.
14253 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014254 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014255 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014256 } else if (app.instrumentationClass != null) {
14257 // Don't want to kill running instrumentation.
14258 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014259 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014260 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014261 } else if (app.persistentActivities > 0) {
14262 // Special persistent activities... shouldn't be used these days.
14263 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014264 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014265 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014266 } else if (app.curReceiver != null ||
14267 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
14268 // An app that is currently receiving a broadcast also
14269 // counts as being in the foreground.
14270 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014271 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014272 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014273 } else if (app.executingServices.size() > 0) {
14274 // An app that is currently executing a service callback also
14275 // counts as being in the foreground.
14276 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014277 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014278 app.adjType = "exec-service";
14279 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014280 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014281 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014282 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014283 app.adjType = "foreground-service";
14284 } else if (app.forcingToForeground != null) {
14285 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014286 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014287 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014288 app.adjType = "force-foreground";
14289 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014290 } else if (app == mHeavyWeightProcess) {
14291 // We don't want to kill the current heavy-weight process.
14292 adj = HEAVY_WEIGHT_APP_ADJ;
14293 schedGroup = Process.THREAD_GROUP_DEFAULT;
14294 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080014295 } else if (app == mHomeProcess) {
14296 // This process is hosting what we currently consider to be the
14297 // home app, so we don't want to let it go into the background.
14298 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014299 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014300 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014301 } else if ((N=app.activities.size()) != 0) {
14302 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014303 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014304 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014305 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014306 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014307 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014308 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014309 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014310 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014311 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014312 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014313 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014314 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014315 break;
14316 }
14317 }
14318 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014319 // A very not-needed process. If this is lower in the lru list,
14320 // we will push it in to the empty bucket.
14321 app.hidden = true;
14322 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014323 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014324 adj = hiddenAdj;
14325 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014326 }
14327
Joe Onorato8a9b2202010-02-26 18:56:32 -080014328 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014329
The Android Open Source Project4df24232009-03-05 14:34:35 -080014330 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014331 // there are applications dependent on our services or providers, but
14332 // this gives us a baseline and makes sure we don't get into an
14333 // infinite recursion.
14334 app.adjSeq = mAdjSeq;
14335 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014336
Christopher Tate6fa95972009-06-05 18:43:55 -070014337 if (mBackupTarget != null && app == mBackupTarget.app) {
14338 // If possible we want to avoid killing apps while they're being backed up
14339 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014340 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070014341 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014342 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014343 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070014344 }
14345 }
14346
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014347 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
14348 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014349 final long now = SystemClock.uptimeMillis();
14350 // This process is more important if the top activity is
14351 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070014352 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014353 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014354 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014355 if (s.startRequested) {
14356 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14357 // This service has seen some activity within
14358 // recent memory, so we will keep its process ahead
14359 // of the background processes.
14360 if (adj > SECONDARY_SERVER_ADJ) {
14361 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014362 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014363 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014364 }
14365 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014366 // If we have let the service slide into the background
14367 // state, still have some text describing what it is doing
14368 // even though the service no longer has an impact.
14369 if (adj > SECONDARY_SERVER_ADJ) {
14370 app.adjType = "started-bg-services";
14371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014372 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014373 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
14374 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014375 Iterator<ConnectionRecord> kt
14376 = s.connections.values().iterator();
14377 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14378 // XXX should compute this based on the max of
14379 // all connected clients.
14380 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014381 if (cr.binding.client == app) {
14382 // Binding to ourself is not interesting.
14383 continue;
14384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014385 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
14386 ProcessRecord client = cr.binding.client;
14387 int myHiddenAdj = hiddenAdj;
14388 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014389 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014390 myHiddenAdj = client.hiddenAdj;
14391 } else {
14392 myHiddenAdj = VISIBLE_APP_ADJ;
14393 }
14394 }
14395 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014396 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014397 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014398 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014399 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014400 if (!client.hidden) {
14401 app.hidden = false;
14402 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014403 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014404 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14405 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014406 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014407 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014408 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014409 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14410 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14411 schedGroup = Process.THREAD_GROUP_DEFAULT;
14412 }
14413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014414 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014415 ActivityRecord a = cr.activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014416 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014417 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014418 //}
14419 if (a != null && adj > FOREGROUND_APP_ADJ &&
14420 (a.state == ActivityState.RESUMED
14421 || a.state == ActivityState.PAUSING)) {
14422 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014423 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014424 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014425 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014426 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14427 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014428 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014429 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014430 }
14431 }
14432 }
14433 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014434
14435 // Finally, f this process has active services running in it, we
14436 // would like to avoid killing it unless it would prevent the current
14437 // application from running. By default we put the process in
14438 // with the rest of the background processes; as we scan through
14439 // its services we may bump it up from there.
14440 if (adj > hiddenAdj) {
14441 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014442 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014443 app.adjType = "bg-services";
14444 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014445 }
14446
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014447 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
14448 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014449 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014450 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
14451 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014452 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014453 if (cpr.clients.size() != 0) {
14454 Iterator<ProcessRecord> kt = cpr.clients.iterator();
14455 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14456 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014457 if (client == app) {
14458 // Being our own client is not interesting.
14459 continue;
14460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014461 int myHiddenAdj = hiddenAdj;
14462 if (myHiddenAdj > client.hiddenAdj) {
14463 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
14464 myHiddenAdj = client.hiddenAdj;
14465 } else {
14466 myHiddenAdj = FOREGROUND_APP_ADJ;
14467 }
14468 }
14469 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014470 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014471 if (adj > clientAdj) {
14472 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014473 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014474 if (!client.hidden) {
14475 app.hidden = false;
14476 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014477 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014478 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14479 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014480 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014481 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014482 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014483 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14484 schedGroup = Process.THREAD_GROUP_DEFAULT;
14485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014486 }
14487 }
14488 // If the provider has external (non-framework) process
14489 // dependencies, ensure that its adjustment is at least
14490 // FOREGROUND_APP_ADJ.
14491 if (cpr.externals != 0) {
14492 if (adj > FOREGROUND_APP_ADJ) {
14493 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014494 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014495 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014496 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014497 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014498 }
14499 }
14500 }
14501 }
14502
14503 app.curRawAdj = adj;
14504
Joe Onorato8a9b2202010-02-26 18:56:32 -080014505 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014506 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14507 if (adj > app.maxAdj) {
14508 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014509 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014510 schedGroup = Process.THREAD_GROUP_DEFAULT;
14511 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014512 }
14513
14514 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014515 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014517 return adj;
14518 }
14519
14520 /**
14521 * Ask a given process to GC right now.
14522 */
14523 final void performAppGcLocked(ProcessRecord app) {
14524 try {
14525 app.lastRequestedGc = SystemClock.uptimeMillis();
14526 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014527 if (app.reportLowMemory) {
14528 app.reportLowMemory = false;
14529 app.thread.scheduleLowMemory();
14530 } else {
14531 app.thread.processInBackground();
14532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014533 }
14534 } catch (Exception e) {
14535 // whatever.
14536 }
14537 }
14538
14539 /**
14540 * Returns true if things are idle enough to perform GCs.
14541 */
Josh Bartel7f208742010-02-25 11:01:44 -060014542 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014543 return mParallelBroadcasts.size() == 0
14544 && mOrderedBroadcasts.size() == 0
14545 && (mSleeping || (mResumedActivity != null &&
14546 mResumedActivity.idle));
14547 }
14548
14549 /**
14550 * Perform GCs on all processes that are waiting for it, but only
14551 * if things are idle.
14552 */
14553 final void performAppGcsLocked() {
14554 final int N = mProcessesToGc.size();
14555 if (N <= 0) {
14556 return;
14557 }
Josh Bartel7f208742010-02-25 11:01:44 -060014558 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014559 while (mProcessesToGc.size() > 0) {
14560 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014561 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014562 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14563 <= SystemClock.uptimeMillis()) {
14564 // To avoid spamming the system, we will GC processes one
14565 // at a time, waiting a few seconds between each.
14566 performAppGcLocked(proc);
14567 scheduleAppGcsLocked();
14568 return;
14569 } else {
14570 // It hasn't been long enough since we last GCed this
14571 // process... put it in the list to wait for its time.
14572 addProcessToGcListLocked(proc);
14573 break;
14574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014575 }
14576 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014577
14578 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014579 }
14580 }
14581
14582 /**
14583 * If all looks good, perform GCs on all processes waiting for them.
14584 */
14585 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014586 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014587 performAppGcsLocked();
14588 return;
14589 }
14590 // Still not idle, wait some more.
14591 scheduleAppGcsLocked();
14592 }
14593
14594 /**
14595 * Schedule the execution of all pending app GCs.
14596 */
14597 final void scheduleAppGcsLocked() {
14598 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014599
14600 if (mProcessesToGc.size() > 0) {
14601 // Schedule a GC for the time to the next process.
14602 ProcessRecord proc = mProcessesToGc.get(0);
14603 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14604
14605 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14606 long now = SystemClock.uptimeMillis();
14607 if (when < (now+GC_TIMEOUT)) {
14608 when = now + GC_TIMEOUT;
14609 }
14610 mHandler.sendMessageAtTime(msg, when);
14611 }
14612 }
14613
14614 /**
14615 * Add a process to the array of processes waiting to be GCed. Keeps the
14616 * list in sorted order by the last GC time. The process can't already be
14617 * on the list.
14618 */
14619 final void addProcessToGcListLocked(ProcessRecord proc) {
14620 boolean added = false;
14621 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14622 if (mProcessesToGc.get(i).lastRequestedGc <
14623 proc.lastRequestedGc) {
14624 added = true;
14625 mProcessesToGc.add(i+1, proc);
14626 break;
14627 }
14628 }
14629 if (!added) {
14630 mProcessesToGc.add(0, proc);
14631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014632 }
14633
14634 /**
14635 * Set up to ask a process to GC itself. This will either do it
14636 * immediately, or put it on the list of processes to gc the next
14637 * time things are idle.
14638 */
14639 final void scheduleAppGcLocked(ProcessRecord app) {
14640 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014641 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014642 return;
14643 }
14644 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014645 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014646 scheduleAppGcsLocked();
14647 }
14648 }
14649
14650 private final boolean updateOomAdjLocked(
14651 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14652 app.hiddenAdj = hiddenAdj;
14653
14654 if (app.thread == null) {
14655 return true;
14656 }
14657
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014658 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014659
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014660 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014661 if (app.curRawAdj != app.setRawAdj) {
14662 if (app.curRawAdj > FOREGROUND_APP_ADJ
14663 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14664 // If this app is transitioning from foreground to
14665 // non-foreground, have it do a gc.
14666 scheduleAppGcLocked(app);
14667 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14668 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14669 // Likewise do a gc when an app is moving in to the
14670 // background (such as a service stopping).
14671 scheduleAppGcLocked(app);
14672 }
14673 app.setRawAdj = app.curRawAdj;
14674 }
14675 if (adj != app.setAdj) {
14676 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014677 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014678 TAG, "Set app " + app.processName +
14679 " oom adj to " + adj);
14680 app.setAdj = adj;
14681 } else {
14682 return false;
14683 }
14684 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014685 if (app.setSchedGroup != app.curSchedGroup) {
14686 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014687 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014688 "Setting process group of " + app.processName
14689 + " to " + app.curSchedGroup);
14690 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014691 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014692 try {
14693 Process.setProcessGroup(app.pid, app.curSchedGroup);
14694 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014695 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014696 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014697 e.printStackTrace();
14698 } finally {
14699 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014700 }
14701 }
14702 if (false) {
14703 if (app.thread != null) {
14704 try {
14705 app.thread.setSchedulingGroup(app.curSchedGroup);
14706 } catch (RemoteException e) {
14707 }
14708 }
14709 }
14710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014711 }
14712
14713 return true;
14714 }
14715
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014716 private final ActivityRecord resumedAppLocked() {
14717 ActivityRecord resumedActivity = mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014718 if (resumedActivity == null || resumedActivity.app == null) {
14719 resumedActivity = mPausingActivity;
14720 if (resumedActivity == null || resumedActivity.app == null) {
14721 resumedActivity = topRunningActivityLocked(null);
14722 }
14723 }
14724 return resumedActivity;
14725 }
14726
14727 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014728 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014729 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14730 int curAdj = app.curAdj;
14731 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14732 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14733
14734 mAdjSeq++;
14735
14736 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14737 if (res) {
14738 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14739 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14740 if (nowHidden != wasHidden) {
14741 // Changed to/from hidden state, so apps after it in the LRU
14742 // list may also be changed.
14743 updateOomAdjLocked();
14744 }
14745 }
14746 return res;
14747 }
14748
14749 private final boolean updateOomAdjLocked() {
14750 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014751 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014752 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14753
14754 if (false) {
14755 RuntimeException e = new RuntimeException();
14756 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014757 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014758 }
14759
14760 mAdjSeq++;
14761
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014762 // Let's determine how many processes we have running vs.
14763 // how many slots we have for background processes; we may want
14764 // to put multiple processes in a slot of there are enough of
14765 // them.
14766 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14767 int factor = (mLruProcesses.size()-4)/numSlots;
14768 if (factor < 1) factor = 1;
14769 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014770 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014772 // First try updating the OOM adjustment for each of the
14773 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014774 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014775 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14776 while (i > 0) {
14777 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014778 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014779 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014780 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014781 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014782 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014783 step++;
14784 if (step >= factor) {
14785 step = 0;
14786 curHiddenAdj++;
14787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014788 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014789 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070014790 if (!app.killedBackground) {
14791 numHidden++;
14792 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070014793 Slog.i(TAG, "No longer want " + app.processName
14794 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014795 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14796 app.processName, app.setAdj, "too many background");
14797 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070014798 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014799 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014800 }
14801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014802 } else {
14803 didOomAdj = false;
14804 }
14805 }
14806
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014807 // If we return false, we will fall back on killing processes to
14808 // have a fixed limit. Do this if a limit has been requested; else
14809 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014810 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14811 }
14812
14813 private final void trimApplications() {
14814 synchronized (this) {
14815 int i;
14816
14817 // First remove any unused application processes whose package
14818 // has been removed.
14819 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14820 final ProcessRecord app = mRemovedProcesses.get(i);
14821 if (app.activities.size() == 0
14822 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014823 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014824 TAG, "Exiting empty application process "
14825 + app.processName + " ("
14826 + (app.thread != null ? app.thread.asBinder() : null)
14827 + ")\n");
14828 if (app.pid > 0 && app.pid != MY_PID) {
14829 Process.killProcess(app.pid);
14830 } else {
14831 try {
14832 app.thread.scheduleExit();
14833 } catch (Exception e) {
14834 // Ignore exceptions.
14835 }
14836 }
14837 cleanUpApplicationRecordLocked(app, false, -1);
14838 mRemovedProcesses.remove(i);
14839
14840 if (app.persistent) {
14841 if (app.persistent) {
14842 addAppLocked(app.info);
14843 }
14844 }
14845 }
14846 }
14847
14848 // Now try updating the OOM adjustment for each of the
14849 // application processes based on their current state.
14850 // If the setOomAdj() API is not supported, then go with our
14851 // back-up plan...
14852 if (!updateOomAdjLocked()) {
14853
14854 // Count how many processes are running services.
14855 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014856 for (i=mLruProcesses.size()-1; i>=0; i--) {
14857 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014858
14859 if (app.persistent || app.services.size() != 0
14860 || app.curReceiver != null
14861 || app.persistentActivities > 0) {
14862 // Don't count processes holding services against our
14863 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014864 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014865 TAG, "Not trimming app " + app + " with services: "
14866 + app.services);
14867 numServiceProcs++;
14868 }
14869 }
14870
14871 int curMaxProcs = mProcessLimit;
14872 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14873 if (mAlwaysFinishActivities) {
14874 curMaxProcs = 1;
14875 }
14876 curMaxProcs += numServiceProcs;
14877
14878 // Quit as many processes as we can to get down to the desired
14879 // process count. First remove any processes that no longer
14880 // have activites running in them.
14881 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014882 i<mLruProcesses.size()
14883 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014884 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014885 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014886 // Quit an application only if it is not currently
14887 // running any activities.
14888 if (!app.persistent && app.activities.size() == 0
14889 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014890 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014891 TAG, "Exiting empty application process "
14892 + app.processName + " ("
14893 + (app.thread != null ? app.thread.asBinder() : null)
14894 + ")\n");
14895 if (app.pid > 0 && app.pid != MY_PID) {
14896 Process.killProcess(app.pid);
14897 } else {
14898 try {
14899 app.thread.scheduleExit();
14900 } catch (Exception e) {
14901 // Ignore exceptions.
14902 }
14903 }
14904 // todo: For now we assume the application is not buggy
14905 // or evil, and will quit as a result of our request.
14906 // Eventually we need to drive this off of the death
14907 // notification, and kill the process if it takes too long.
14908 cleanUpApplicationRecordLocked(app, false, i);
14909 i--;
14910 }
14911 }
14912
14913 // If we still have too many processes, now from the least
14914 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014915 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014916 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014917 " of " + curMaxProcs + " processes");
14918 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014919 i<mLruProcesses.size()
14920 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014921 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014922 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014923 // Quit the application only if we have a state saved for
14924 // all of its activities.
14925 boolean canQuit = !app.persistent && app.curReceiver == null
14926 && app.services.size() == 0
14927 && app.persistentActivities == 0;
14928 int NUMA = app.activities.size();
14929 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014930 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014931 TAG, "Looking to quit " + app.processName);
14932 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014933 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014934 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014935 TAG, " " + r.intent.getComponent().flattenToShortString()
14936 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14937 canQuit = (r.haveState || !r.stateNotNeeded)
14938 && !r.visible && r.stopped;
14939 }
14940 if (canQuit) {
14941 // Finish all of the activities, and then the app itself.
14942 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014943 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014944 if (!r.finishing) {
14945 destroyActivityLocked(r, false);
14946 }
14947 r.resultTo = null;
14948 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014949 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014950 + app.processName + " ("
14951 + (app.thread != null ? app.thread.asBinder() : null)
14952 + ")\n");
14953 if (app.pid > 0 && app.pid != MY_PID) {
14954 Process.killProcess(app.pid);
14955 } else {
14956 try {
14957 app.thread.scheduleExit();
14958 } catch (Exception e) {
14959 // Ignore exceptions.
14960 }
14961 }
14962 // todo: For now we assume the application is not buggy
14963 // or evil, and will quit as a result of our request.
14964 // Eventually we need to drive this off of the death
14965 // notification, and kill the process if it takes too long.
14966 cleanUpApplicationRecordLocked(app, false, i);
14967 i--;
14968 //dump();
14969 }
14970 }
14971
14972 }
14973
14974 int curMaxActivities = MAX_ACTIVITIES;
14975 if (mAlwaysFinishActivities) {
14976 curMaxActivities = 1;
14977 }
14978
14979 // Finally, if there are too many activities now running, try to
14980 // finish as many as we can to get back down to the limit.
14981 for ( i=0;
14982 i<mLRUActivities.size()
14983 && mLRUActivities.size() > curMaxActivities;
14984 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014985 final ActivityRecord r
14986 = (ActivityRecord)mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014987
14988 // We can finish this one if we have its icicle saved and
14989 // it is not persistent.
14990 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14991 && r.stopped && !r.persistent && !r.finishing) {
14992 final int origSize = mLRUActivities.size();
14993 destroyActivityLocked(r, true);
14994
14995 // This will remove it from the LRU list, so keep
14996 // our index at the same value. Note that this check to
14997 // see if the size changes is just paranoia -- if
14998 // something unexpected happens, we don't want to end up
14999 // in an infinite loop.
15000 if (origSize > mLRUActivities.size()) {
15001 i--;
15002 }
15003 }
15004 }
15005 }
15006 }
15007
15008 /** This method sends the specified signal to each of the persistent apps */
15009 public void signalPersistentProcesses(int sig) throws RemoteException {
15010 if (sig != Process.SIGNAL_USR1) {
15011 throw new SecurityException("Only SIGNAL_USR1 is allowed");
15012 }
15013
15014 synchronized (this) {
15015 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
15016 != PackageManager.PERMISSION_GRANTED) {
15017 throw new SecurityException("Requires permission "
15018 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
15019 }
15020
Dianne Hackborndd71fc82009-12-16 19:24:32 -080015021 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
15022 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015023 if (r.thread != null && r.persistent) {
15024 Process.sendSignal(r.pid, sig);
15025 }
15026 }
15027 }
15028 }
15029
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015030 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015031 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015032
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015033 try {
15034 synchronized (this) {
15035 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
15036 // its own permission.
15037 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
15038 != PackageManager.PERMISSION_GRANTED) {
15039 throw new SecurityException("Requires permission "
15040 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015041 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015042
15043 if (start && fd == null) {
15044 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015045 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015046
15047 ProcessRecord proc = null;
15048 try {
15049 int pid = Integer.parseInt(process);
15050 synchronized (mPidsSelfLocked) {
15051 proc = mPidsSelfLocked.get(pid);
15052 }
15053 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015054 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015055
15056 if (proc == null) {
15057 HashMap<String, SparseArray<ProcessRecord>> all
15058 = mProcessNames.getMap();
15059 SparseArray<ProcessRecord> procs = all.get(process);
15060 if (procs != null && procs.size() > 0) {
15061 proc = procs.valueAt(0);
15062 }
15063 }
15064
15065 if (proc == null || proc.thread == null) {
15066 throw new IllegalArgumentException("Unknown process: " + process);
15067 }
15068
15069 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
15070 if (isSecure) {
15071 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
15072 throw new SecurityException("Process not debuggable: " + proc);
15073 }
15074 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015075
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015076 proc.thread.profilerControl(start, path, fd);
15077 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015078 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015079 }
15080 } catch (RemoteException e) {
15081 throw new IllegalStateException("Process disappeared");
15082 } finally {
15083 if (fd != null) {
15084 try {
15085 fd.close();
15086 } catch (IOException e) {
15087 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015088 }
15089 }
15090 }
15091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015092 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
15093 public void monitor() {
15094 synchronized (this) { }
15095 }
15096}