blob: 0e1eb6f0731624411a6f770f4bc7b654795b6daf [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 Hackborn01e4cfc2010-06-24 15:07:24 -07004565 void sendActivityResultLocked(int callingUid, ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004566 String resultWho, int requestCode, int resultCode, Intent data) {
4567
4568 if (callingUid > 0) {
4569 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4570 data, r);
4571 }
4572
Joe Onorato8a9b2202010-02-26 18:56:32 -08004573 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004574 + " : who=" + resultWho + " req=" + requestCode
4575 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4577 try {
4578 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4579 list.add(new ResultInfo(resultWho, requestCode,
4580 resultCode, data));
4581 r.app.thread.scheduleSendResult(r, list);
4582 return;
4583 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004584 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 }
4586 }
4587
4588 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4589 }
4590
4591 public final void finishSubActivity(IBinder token, String resultWho,
4592 int requestCode) {
4593 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004594 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004595 if (index < 0) {
4596 return;
4597 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004598 ActivityRecord self = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599
4600 final long origId = Binder.clearCallingIdentity();
4601
4602 int i;
4603 for (i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004604 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004605 if (r.resultTo == self && r.requestCode == requestCode) {
4606 if ((r.resultWho == null && resultWho == null) ||
4607 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4608 finishActivityLocked(r, i,
4609 Activity.RESULT_CANCELED, null, "request-sub");
4610 }
4611 }
4612 }
4613
4614 Binder.restoreCallingIdentity(origId);
4615 }
4616 }
4617
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004618 public boolean willActivityBeVisible(IBinder token) {
4619 synchronized(this) {
4620 int i;
4621 for (i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004622 ActivityRecord r = (ActivityRecord)mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004623 if (r == token) {
4624 return true;
4625 }
4626 if (r.fullscreen && !r.finishing) {
4627 return false;
4628 }
4629 }
4630 return true;
4631 }
4632 }
4633
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004634 public void overridePendingTransition(IBinder token, String packageName,
4635 int enterAnim, int exitAnim) {
4636 synchronized(this) {
4637 int index = indexOfTokenLocked(token);
4638 if (index < 0) {
4639 return;
4640 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004641 ActivityRecord self = (ActivityRecord)mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004642
4643 final long origId = Binder.clearCallingIdentity();
4644
4645 if (self.state == ActivityState.RESUMED
4646 || self.state == ActivityState.PAUSING) {
4647 mWindowManager.overridePendingAppTransition(packageName,
4648 enterAnim, exitAnim);
4649 }
4650
4651 Binder.restoreCallingIdentity(origId);
4652 }
4653 }
4654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 /**
4656 * Perform clean-up of service connections in an activity record.
4657 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004658 private final void cleanUpActivityServicesLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 // Throw away any services that have been bound by this activity.
4660 if (r.connections != null) {
4661 Iterator<ConnectionRecord> it = r.connections.iterator();
4662 while (it.hasNext()) {
4663 ConnectionRecord c = it.next();
4664 removeConnectionLocked(c, null, r);
4665 }
4666 r.connections = null;
4667 }
4668 }
4669
4670 /**
4671 * Perform the common clean-up of an activity record. This is called both
4672 * as part of destroyActivityLocked() (when destroying the client-side
4673 * representation) and cleaning things up as a result of its hosting
4674 * processing going away, in which case there is no remaining client-side
4675 * state to destroy so only the cleanup here is needed.
4676 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004677 private final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 if (mResumedActivity == r) {
4679 mResumedActivity = null;
4680 }
4681 if (mFocusedActivity == r) {
4682 mFocusedActivity = null;
4683 }
4684
4685 r.configDestroy = false;
4686 r.frozenBeforeDestroy = false;
4687
4688 // Make sure this record is no longer in the pending finishes list.
4689 // This could happen, for example, if we are trimming activities
4690 // down to the max limit while they are still waiting to finish.
4691 mFinishingActivities.remove(r);
4692 mWaitingVisibleActivities.remove(r);
4693
4694 // Remove any pending results.
4695 if (r.finishing && r.pendingResults != null) {
4696 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4697 PendingIntentRecord rec = apr.get();
4698 if (rec != null) {
4699 cancelIntentSenderLocked(rec, false);
4700 }
4701 }
4702 r.pendingResults = null;
4703 }
4704
4705 if (cleanServices) {
4706 cleanUpActivityServicesLocked(r);
4707 }
4708
4709 if (mPendingThumbnails.size() > 0) {
4710 // There are clients waiting to receive thumbnails so, in case
4711 // this is an activity that someone is waiting for, add it
4712 // to the pending list so we can correctly update the clients.
4713 mCancelledThumbnails.add(r);
4714 }
4715
4716 // Get rid of any pending idle timeouts.
4717 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4718 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4719 }
4720
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004721 private final void removeActivityFromHistoryLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 if (r.state != ActivityState.DESTROYED) {
4723 mHistory.remove(r);
4724 r.inHistory = false;
4725 r.state = ActivityState.DESTROYED;
4726 mWindowManager.removeAppToken(r);
4727 if (VALIDATE_TOKENS) {
4728 mWindowManager.validateAppTokens(mHistory);
4729 }
4730 cleanUpActivityServicesLocked(r);
4731 removeActivityUriPermissionsLocked(r);
4732 }
4733 }
4734
4735 /**
4736 * Destroy the current CLIENT SIDE instance of an activity. This may be
4737 * called both when actually finishing an activity, or when performing
4738 * a configuration switch where we destroy the current client-side object
4739 * but then create a new client-side object for this same HistoryRecord.
4740 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004741 private final boolean destroyActivityLocked(ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004743 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004744 TAG, "Removing activity: token=" + r
4745 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004746 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 System.identityHashCode(r),
4748 r.task.taskId, r.shortComponentName);
4749
4750 boolean removedFromHistory = false;
4751
4752 cleanUpActivityLocked(r, false);
4753
Dianne Hackborn03abb812010-01-04 18:43:19 -08004754 final boolean hadApp = r.app != null;
4755
4756 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 if (removeFromApp) {
4758 int idx = r.app.activities.indexOf(r);
4759 if (idx >= 0) {
4760 r.app.activities.remove(idx);
4761 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004762 if (mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4763 mHeavyWeightProcess = null;
4764 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004766 if (r.persistent) {
4767 decPersistentCountLocked(r.app);
4768 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004769 if (r.app.activities.size() == 0) {
4770 // No longer have activities, so update location in
4771 // LRU list.
4772 updateLruProcessLocked(r.app, true, false);
4773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004774 }
4775
4776 boolean skipDestroy = false;
4777
4778 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004779 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4781 r.configChangeFlags);
4782 } catch (Exception e) {
4783 // We can just ignore exceptions here... if the process
4784 // has crashed, our death notification will clean things
4785 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004786 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004787 if (r.finishing) {
4788 removeActivityFromHistoryLocked(r);
4789 removedFromHistory = true;
4790 skipDestroy = true;
4791 }
4792 }
4793
4794 r.app = null;
4795 r.nowVisible = false;
4796
4797 if (r.finishing && !skipDestroy) {
4798 r.state = ActivityState.DESTROYING;
4799 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4800 msg.obj = r;
4801 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4802 } else {
4803 r.state = ActivityState.DESTROYED;
4804 }
4805 } else {
4806 // remove this record from the history.
4807 if (r.finishing) {
4808 removeActivityFromHistoryLocked(r);
4809 removedFromHistory = true;
4810 } else {
4811 r.state = ActivityState.DESTROYED;
4812 }
4813 }
4814
4815 r.configChangeFlags = 0;
4816
Dianne Hackborn03abb812010-01-04 18:43:19 -08004817 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004818 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004819 }
4820
4821 return removedFromHistory;
4822 }
4823
Dianne Hackborn03abb812010-01-04 18:43:19 -08004824 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004825 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004826 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004827 TAG, "Removing app " + app + " from list " + list
4828 + " with " + i + " entries");
4829 while (i > 0) {
4830 i--;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004831 ActivityRecord r = (ActivityRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004832 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004833 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4834 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004835 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004836 list.remove(i);
4837 }
4838 }
4839 }
4840
4841 /**
4842 * Main function for removing an existing process from the activity manager
4843 * as a result of that process going away. Clears out all connections
4844 * to the process.
4845 */
4846 private final void handleAppDiedLocked(ProcessRecord app,
4847 boolean restarting) {
4848 cleanUpApplicationRecordLocked(app, restarting, -1);
4849 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004850 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004851 }
4852
4853 // Just in case...
4854 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004855 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004856 mPausingActivity = null;
4857 }
4858 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4859 mLastPausedActivity = null;
4860 }
4861
4862 // Remove this application's activities from active lists.
4863 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4864 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4865 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4866 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4867
4868 boolean atTop = true;
4869 boolean hasVisibleActivities = false;
4870
4871 // Clean out the history list.
4872 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004873 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 TAG, "Removing app " + app + " from history with " + i + " entries");
4875 while (i > 0) {
4876 i--;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004877 ActivityRecord r = (ActivityRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004878 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4880 if (r.app == app) {
4881 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004882 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004883 TAG, "Removing this entry! frozen=" + r.haveState
4884 + " finishing=" + r.finishing);
4885 mHistory.remove(i);
4886
4887 r.inHistory = false;
4888 mWindowManager.removeAppToken(r);
4889 if (VALIDATE_TOKENS) {
4890 mWindowManager.validateAppTokens(mHistory);
4891 }
4892 removeActivityUriPermissionsLocked(r);
4893
4894 } else {
4895 // We have the current state for this activity, so
4896 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004897 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004898 TAG, "Keeping entry, setting app to null");
4899 if (r.visible) {
4900 hasVisibleActivities = true;
4901 }
4902 r.app = null;
4903 r.nowVisible = false;
4904 if (!r.haveState) {
4905 r.icicle = null;
4906 }
4907 }
4908
4909 cleanUpActivityLocked(r, true);
4910 r.state = ActivityState.STOPPED;
4911 }
4912 atTop = false;
4913 }
4914
4915 app.activities.clear();
4916
4917 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004918 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004919 + " running instrumentation " + app.instrumentationClass);
4920 Bundle info = new Bundle();
4921 info.putString("shortMsg", "Process crashed.");
4922 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4923 }
4924
4925 if (!restarting) {
4926 if (!resumeTopActivityLocked(null)) {
4927 // If there was nothing to resume, and we are not already
4928 // restarting this process, but there is a visible activity that
4929 // is hosted by the process... then make sure all visible
4930 // activities are running, taking care of restarting this
4931 // process.
4932 if (hasVisibleActivities) {
4933 ensureActivitiesVisibleLocked(null, 0);
4934 }
4935 }
4936 }
4937 }
4938
4939 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4940 IBinder threadBinder = thread.asBinder();
4941
4942 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004943 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4944 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4946 return i;
4947 }
4948 }
4949 return -1;
4950 }
4951
4952 private final ProcessRecord getRecordForAppLocked(
4953 IApplicationThread thread) {
4954 if (thread == null) {
4955 return null;
4956 }
4957
4958 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004959 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 }
4961
4962 private final void appDiedLocked(ProcessRecord app, int pid,
4963 IApplicationThread thread) {
4964
4965 mProcDeaths[0]++;
4966
Magnus Edlund7bb25812010-02-24 15:45:06 +01004967 // Clean up already done if the process has been re-started.
4968 if (app.pid == pid && app.thread != null &&
4969 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07004970 if (!app.killedBackground) {
4971 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
4972 + ") has died.");
4973 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08004974 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004975 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004976 TAG, "Dying app: " + app + ", pid: " + pid
4977 + ", thread: " + thread.asBinder());
4978 boolean doLowMem = app.instrumentationClass == null;
4979 handleAppDiedLocked(app, false);
4980
4981 if (doLowMem) {
4982 // If there are no longer any background processes running,
4983 // and the app that died was not running instrumentation,
4984 // then tell everyone we are now low on memory.
4985 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004986 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4987 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4989 haveBg = true;
4990 break;
4991 }
4992 }
4993
4994 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004995 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004996 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004997 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004998 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4999 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07005000 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005001 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
5002 // The low memory report is overriding any current
5003 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005004 // heavy/important/visible/foreground processes first.
5005 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005006 rec.lastRequestedGc = 0;
5007 } else {
5008 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005009 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005010 rec.reportLowMemory = true;
5011 rec.lastLowMemory = now;
5012 mProcessesToGc.remove(rec);
5013 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 }
5015 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005016 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005017 }
5018 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01005019 } else if (app.pid != pid) {
5020 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005021 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01005022 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08005023 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005024 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005025 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 + thread.asBinder());
5027 }
5028 }
5029
Dan Egnor42471dd2010-01-07 17:25:22 -08005030 /**
5031 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07005032 * @param clearTraces causes the dump file to be erased prior to the new
5033 * traces being written, if true; when false, the new traces will be
5034 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08005035 * @param pids of dalvik VM processes to dump stack traces for
5036 * @return file containing stack traces, or null if no dump file is configured
5037 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07005038 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005039 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
5040 if (tracesPath == null || tracesPath.length() == 0) {
5041 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005042 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005043
5044 File tracesFile = new File(tracesPath);
5045 try {
5046 File tracesDir = tracesFile.getParentFile();
5047 if (!tracesDir.exists()) tracesFile.mkdirs();
5048 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
5049
Christopher Tate6ee412d2010-05-28 12:01:56 -07005050 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08005051 tracesFile.createNewFile();
5052 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
5053 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005054 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005055 return null;
5056 }
5057
5058 // Use a FileObserver to detect when traces finish writing.
5059 // The order of traces is considered important to maintain for legibility.
5060 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
5061 public synchronized void onEvent(int event, String path) { notify(); }
5062 };
5063
5064 try {
5065 observer.startWatching();
5066 int num = pids.size();
5067 for (int i = 0; i < num; i++) {
5068 synchronized (observer) {
5069 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
5070 observer.wait(200); // Wait for write-close, give up after 200msec
5071 }
5072 }
5073 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08005074 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005075 } finally {
5076 observer.stopWatching();
5077 }
5078
5079 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005080 }
5081
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005082 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
5083 ActivityRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005084 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005085
5086 synchronized (this) {
5087 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
5088 if (mShuttingDown) {
5089 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
5090 return;
5091 } else if (app.notResponding) {
5092 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
5093 return;
5094 } else if (app.crashing) {
5095 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
5096 return;
5097 }
5098
5099 // In case we come through here for the same app before completing
5100 // this one, mark as anring now so we will bail out.
5101 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08005102
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005103 // Log the ANR to the event log.
5104 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
5105 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08005106
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005107 // Dump thread traces as quickly as we can, starting with "interesting" processes.
5108 pids.add(app.pid);
5109
5110 int parentPid = app.pid;
5111 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
5112 if (parentPid != app.pid) pids.add(parentPid);
5113
5114 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08005115
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005116 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
5117 ProcessRecord r = mLruProcesses.get(i);
5118 if (r != null && r.thread != null) {
5119 int pid = r.pid;
5120 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
5121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005122 }
5123 }
5124
Christopher Tate6ee412d2010-05-28 12:01:56 -07005125 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08005126
5127 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005128 StringBuilder info = mStringBuilder;
5129 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08005130 info.append("ANR in ").append(app.processName);
5131 if (activity != null && activity.shortComponentName != null) {
5132 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07005133 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08005134 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005135 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005136 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005137 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005138 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005139 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005141
Dan Egnor42471dd2010-01-07 17:25:22 -08005142 String cpuInfo = null;
5143 if (MONITOR_CPU_USAGE) {
5144 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005145 synchronized (mProcessStatsThread) {
5146 cpuInfo = mProcessStats.printCurrentState();
5147 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005148 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 }
5150
Joe Onorato8a9b2202010-02-26 18:56:32 -08005151 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08005152 if (tracesFile == null) {
5153 // There is no trace file, so dump (only) the alleged culprit's threads to the log
5154 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
5155 }
5156
5157 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
5158
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005159 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08005161 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
5162 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005163 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005164 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
5165 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005166 }
5167 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005168 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005169 }
5170 }
5171
Dan Egnor42471dd2010-01-07 17:25:22 -08005172 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
5173 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
5174 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005175
5176 synchronized (this) {
5177 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
5178 Process.killProcess(app.pid);
5179 return;
5180 }
5181
5182 // Set the app's notResponding state, and look up the errorReportReceiver
5183 makeAppNotRespondingLocked(app,
5184 activity != null ? activity.shortComponentName : null,
5185 annotation != null ? "ANR " + annotation : "ANR",
5186 info.toString());
5187
5188 // Bring up the infamous App Not Responding dialog
5189 Message msg = Message.obtain();
5190 HashMap map = new HashMap();
5191 msg.what = SHOW_NOT_RESPONDING_MSG;
5192 msg.obj = map;
5193 map.put("app", app);
5194 if (activity != null) {
5195 map.put("activity", activity);
5196 }
5197
5198 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08005199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 }
5201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 private final void decPersistentCountLocked(ProcessRecord app)
5203 {
5204 app.persistentActivities--;
5205 if (app.persistentActivities > 0) {
5206 // Still more of 'em...
5207 return;
5208 }
5209 if (app.persistent) {
5210 // Ah, but the application itself is persistent. Whatever!
5211 return;
5212 }
5213
5214 // App is no longer persistent... make sure it and the ones
5215 // following it in the LRU list have the correc oom_adj.
5216 updateOomAdjLocked();
5217 }
5218
5219 public void setPersistent(IBinder token, boolean isPersistent) {
5220 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
5221 != PackageManager.PERMISSION_GRANTED) {
5222 String msg = "Permission Denial: setPersistent() from pid="
5223 + Binder.getCallingPid()
5224 + ", uid=" + Binder.getCallingUid()
5225 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005226 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005227 throw new SecurityException(msg);
5228 }
5229
5230 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005231 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 if (index < 0) {
5233 return;
5234 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005235 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 ProcessRecord app = r.app;
5237
Joe Onorato8a9b2202010-02-26 18:56:32 -08005238 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005239 TAG, "Setting persistence " + isPersistent + ": " + r);
5240
5241 if (isPersistent) {
5242 if (r.persistent) {
5243 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005244 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 return;
5246 }
5247 r.persistent = true;
5248 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005249 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005250 if (app.persistentActivities > 1) {
5251 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005252 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005253 return;
5254 }
5255 if (app.persistent) {
5256 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005257 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005258 return;
5259 }
5260
5261 // App is now persistent... make sure it and the ones
5262 // following it now have the correct oom_adj.
5263 final long origId = Binder.clearCallingIdentity();
5264 updateOomAdjLocked();
5265 Binder.restoreCallingIdentity(origId);
5266
5267 } else {
5268 if (!r.persistent) {
5269 // Okay okay, I heard you already!
5270 return;
5271 }
5272 r.persistent = false;
5273 final long origId = Binder.clearCallingIdentity();
5274 decPersistentCountLocked(app);
5275 Binder.restoreCallingIdentity(origId);
5276
5277 }
5278 }
5279 }
5280
5281 public boolean clearApplicationUserData(final String packageName,
5282 final IPackageDataObserver observer) {
5283 int uid = Binder.getCallingUid();
5284 int pid = Binder.getCallingPid();
5285 long callingId = Binder.clearCallingIdentity();
5286 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005287 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005288 int pkgUid = -1;
5289 synchronized(this) {
5290 try {
5291 pkgUid = pm.getPackageUid(packageName);
5292 } catch (RemoteException e) {
5293 }
5294 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005295 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 return false;
5297 }
5298 if (uid == pkgUid || checkComponentPermission(
5299 android.Manifest.permission.CLEAR_APP_USER_DATA,
5300 pid, uid, -1)
5301 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005302 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005303 } else {
5304 throw new SecurityException(pid+" does not have permission:"+
5305 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5306 "for process:"+packageName);
5307 }
5308 }
5309
5310 try {
5311 //clear application user data
5312 pm.clearApplicationUserData(packageName, observer);
5313 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5314 Uri.fromParts("package", packageName, null));
5315 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005316 synchronized (this) {
5317 broadcastIntentLocked(null, null, intent,
5318 null, null, 0, null, null, null,
5319 false, false, MY_PID, Process.SYSTEM_UID);
5320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 } catch (RemoteException e) {
5322 }
5323 } finally {
5324 Binder.restoreCallingIdentity(callingId);
5325 }
5326 return true;
5327 }
5328
Dianne Hackborn03abb812010-01-04 18:43:19 -08005329 public void killBackgroundProcesses(final String packageName) {
5330 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5331 != PackageManager.PERMISSION_GRANTED &&
5332 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5333 != PackageManager.PERMISSION_GRANTED) {
5334 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 + Binder.getCallingPid()
5336 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005337 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005338 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005339 throw new SecurityException(msg);
5340 }
5341
5342 long callingId = Binder.clearCallingIdentity();
5343 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005344 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 int pkgUid = -1;
5346 synchronized(this) {
5347 try {
5348 pkgUid = pm.getPackageUid(packageName);
5349 } catch (RemoteException e) {
5350 }
5351 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005352 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 return;
5354 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005355 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005356 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005357 }
5358 } finally {
5359 Binder.restoreCallingIdentity(callingId);
5360 }
5361 }
5362
5363 public void forceStopPackage(final String packageName) {
5364 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5365 != PackageManager.PERMISSION_GRANTED) {
5366 String msg = "Permission Denial: forceStopPackage() from pid="
5367 + Binder.getCallingPid()
5368 + ", uid=" + Binder.getCallingUid()
5369 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005370 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005371 throw new SecurityException(msg);
5372 }
5373
5374 long callingId = Binder.clearCallingIdentity();
5375 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005376 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08005377 int pkgUid = -1;
5378 synchronized(this) {
5379 try {
5380 pkgUid = pm.getPackageUid(packageName);
5381 } catch (RemoteException e) {
5382 }
5383 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005384 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005385 return;
5386 }
5387 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 }
5389 } finally {
5390 Binder.restoreCallingIdentity(callingId);
5391 }
5392 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005393
5394 /*
5395 * The pkg name and uid have to be specified.
5396 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5397 */
5398 public void killApplicationWithUid(String pkg, int uid) {
5399 if (pkg == null) {
5400 return;
5401 }
5402 // Make sure the uid is valid.
5403 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005404 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005405 return;
5406 }
5407 int callerUid = Binder.getCallingUid();
5408 // Only the system server can kill an application
5409 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005410 // Post an aysnc message to kill the application
5411 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5412 msg.arg1 = uid;
5413 msg.arg2 = 0;
5414 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005415 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005416 } else {
5417 throw new SecurityException(callerUid + " cannot kill pkg: " +
5418 pkg);
5419 }
5420 }
5421
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005422 public void closeSystemDialogs(String reason) {
5423 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5424 if (reason != null) {
5425 intent.putExtra("reason", reason);
5426 }
5427
5428 final int uid = Binder.getCallingUid();
5429 final long origId = Binder.clearCallingIdentity();
5430 synchronized (this) {
5431 int i = mWatchers.beginBroadcast();
5432 while (i > 0) {
5433 i--;
5434 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5435 if (w != null) {
5436 try {
5437 w.closingSystemDialogs(reason);
5438 } catch (RemoteException e) {
5439 }
5440 }
5441 }
5442 mWatchers.finishBroadcast();
5443
Dianne Hackbornffa42482009-09-23 22:20:11 -07005444 mWindowManager.closeSystemDialogs(reason);
5445
5446 for (i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005447 ActivityRecord r = (ActivityRecord)mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07005448 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5449 finishActivityLocked(r, i,
5450 Activity.RESULT_CANCELED, null, "close-sys");
5451 }
5452 }
5453
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005454 broadcastIntentLocked(null, null, intent, null,
5455 null, 0, null, null, null, false, false, -1, uid);
5456 }
5457 Binder.restoreCallingIdentity(origId);
5458 }
5459
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005460 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005461 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005462 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5463 for (int i=pids.length-1; i>=0; i--) {
5464 infos[i] = new Debug.MemoryInfo();
5465 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005466 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005467 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005468 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005469
5470 public void killApplicationProcess(String processName, int uid) {
5471 if (processName == null) {
5472 return;
5473 }
5474
5475 int callerUid = Binder.getCallingUid();
5476 // Only the system server can kill an application
5477 if (callerUid == Process.SYSTEM_UID) {
5478 synchronized (this) {
5479 ProcessRecord app = getProcessRecordLocked(processName, uid);
5480 if (app != null) {
5481 try {
5482 app.thread.scheduleSuicide();
5483 } catch (RemoteException e) {
5484 // If the other end already died, then our work here is done.
5485 }
5486 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005487 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005488 + processName + " / " + uid);
5489 }
5490 }
5491 } else {
5492 throw new SecurityException(callerUid + " cannot kill app process: " +
5493 processName);
5494 }
5495 }
5496
Dianne Hackborn03abb812010-01-04 18:43:19 -08005497 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005498 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5500 Uri.fromParts("package", packageName, null));
5501 intent.putExtra(Intent.EXTRA_UID, uid);
5502 broadcastIntentLocked(null, null, intent,
5503 null, null, 0, null, null, null,
5504 false, false, MY_PID, Process.SYSTEM_UID);
5505 }
5506
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005507 private final boolean killPackageProcessesLocked(String packageName, int uid,
5508 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005509 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510
Dianne Hackborn03abb812010-01-04 18:43:19 -08005511 // Remove all processes this package may have touched: all with the
5512 // same UID (except for the system or root user), and all whose name
5513 // matches the package name.
5514 final String procNamePrefix = packageName + ":";
5515 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5516 final int NA = apps.size();
5517 for (int ia=0; ia<NA; ia++) {
5518 ProcessRecord app = apps.valueAt(ia);
5519 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005520 if (doit) {
5521 procs.add(app);
5522 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005523 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5524 || app.processName.equals(packageName)
5525 || app.processName.startsWith(procNamePrefix)) {
5526 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005527 if (!doit) {
5528 return true;
5529 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005530 app.removed = true;
5531 procs.add(app);
5532 }
5533 }
5534 }
5535 }
5536
5537 int N = procs.size();
5538 for (int i=0; i<N; i++) {
5539 removeProcessLocked(procs.get(i), callerWillRestart);
5540 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005541 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005542 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005543
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005544 private final boolean forceStopPackageLocked(String name, int uid,
5545 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005546 int i, N;
5547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005548 if (uid < 0) {
5549 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005550 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551 } catch (RemoteException e) {
5552 }
5553 }
5554
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005555 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005556 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005557
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005558 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5559 while (badApps.hasNext()) {
5560 SparseArray<Long> ba = badApps.next();
5561 if (ba.get(uid) != null) {
5562 badApps.remove();
5563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005564 }
5565 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005566
5567 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5568 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005569
5570 for (i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005571 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005572 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005573 if (!doit) {
5574 return true;
5575 }
5576 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005577 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 if (r.app != null) {
5579 r.app.removed = true;
5580 }
5581 r.app = null;
5582 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5583 }
5584 }
5585
5586 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5587 for (ServiceRecord service : mServices.values()) {
5588 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005589 if (!doit) {
5590 return true;
5591 }
5592 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005593 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005594 if (service.app != null) {
5595 service.app.removed = true;
5596 }
5597 service.app = null;
5598 services.add(service);
5599 }
5600 }
5601
5602 N = services.size();
5603 for (i=0; i<N; i++) {
5604 bringDownServiceLocked(services.get(i), true);
5605 }
5606
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005607 if (doit) {
5608 if (purgeCache) {
5609 AttributeCache ac = AttributeCache.instance();
5610 if (ac != null) {
5611 ac.removePackage(name);
5612 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005613 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005614 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005615 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005616
5617 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005618 }
5619
5620 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5621 final String name = app.processName;
5622 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005623 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005624 TAG, "Force removing process " + app + " (" + name
5625 + "/" + uid + ")");
5626
5627 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005628 if (mHeavyWeightProcess == app) {
5629 mHeavyWeightProcess = null;
5630 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005632 boolean needRestart = false;
5633 if (app.pid > 0 && app.pid != MY_PID) {
5634 int pid = app.pid;
5635 synchronized (mPidsSelfLocked) {
5636 mPidsSelfLocked.remove(pid);
5637 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5638 }
5639 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005640 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005641 Process.killProcess(pid);
5642
5643 if (app.persistent) {
5644 if (!callerWillRestart) {
5645 addAppLocked(app.info);
5646 } else {
5647 needRestart = true;
5648 }
5649 }
5650 } else {
5651 mRemovedProcesses.add(app);
5652 }
5653
5654 return needRestart;
5655 }
5656
5657 private final void processStartTimedOutLocked(ProcessRecord app) {
5658 final int pid = app.pid;
5659 boolean gone = false;
5660 synchronized (mPidsSelfLocked) {
5661 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5662 if (knownApp != null && knownApp.thread == null) {
5663 mPidsSelfLocked.remove(pid);
5664 gone = true;
5665 }
5666 }
5667
5668 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005669 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005670 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005671 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005673 if (mHeavyWeightProcess == app) {
5674 mHeavyWeightProcess = null;
5675 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5676 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005677 // Take care of any launching providers waiting for this process.
5678 checkAppInLaunchingProvidersLocked(app, true);
5679 // Take care of any services that are waiting for the process.
5680 for (int i=0; i<mPendingServices.size(); i++) {
5681 ServiceRecord sr = mPendingServices.get(i);
5682 if (app.info.uid == sr.appInfo.uid
5683 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005684 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005685 mPendingServices.remove(i);
5686 i--;
5687 bringDownServiceLocked(sr, true);
5688 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005689 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005690 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005691 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005692 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005693 try {
5694 IBackupManager bm = IBackupManager.Stub.asInterface(
5695 ServiceManager.getService(Context.BACKUP_SERVICE));
5696 bm.agentDisconnected(app.info.packageName);
5697 } catch (RemoteException e) {
5698 // Can't happen; the backup manager is local
5699 }
5700 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005701 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005702 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005703 mPendingBroadcast = null;
5704 scheduleBroadcastsLocked();
5705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005706 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005707 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005708 }
5709 }
5710
5711 private final boolean attachApplicationLocked(IApplicationThread thread,
5712 int pid) {
5713
5714 // Find the application record that is being attached... either via
5715 // the pid if we are running in multiple processes, or just pull the
5716 // next app record if we are emulating process with anonymous threads.
5717 ProcessRecord app;
5718 if (pid != MY_PID && pid >= 0) {
5719 synchronized (mPidsSelfLocked) {
5720 app = mPidsSelfLocked.get(pid);
5721 }
5722 } else if (mStartingProcesses.size() > 0) {
5723 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005724 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005725 } else {
5726 app = null;
5727 }
5728
5729 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005730 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005731 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005732 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005733 if (pid > 0 && pid != MY_PID) {
5734 Process.killProcess(pid);
5735 } else {
5736 try {
5737 thread.scheduleExit();
5738 } catch (Exception e) {
5739 // Ignore exceptions.
5740 }
5741 }
5742 return false;
5743 }
5744
5745 // If this application record is still attached to a previous
5746 // process, clean it up now.
5747 if (app.thread != null) {
5748 handleAppDiedLocked(app, true);
5749 }
5750
5751 // Tell the process all about itself.
5752
Joe Onorato8a9b2202010-02-26 18:56:32 -08005753 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 TAG, "Binding process pid " + pid + " to record " + app);
5755
5756 String processName = app.processName;
5757 try {
5758 thread.asBinder().linkToDeath(new AppDeathRecipient(
5759 app, pid, thread), 0);
5760 } catch (RemoteException e) {
5761 app.resetPackageList();
5762 startProcessLocked(app, "link fail", processName);
5763 return false;
5764 }
5765
Doug Zongker2bec3d42009-12-04 12:52:44 -08005766 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005767
5768 app.thread = thread;
5769 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005770 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5771 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005772 app.forcingToForeground = null;
5773 app.foregroundServices = false;
5774 app.debugging = false;
5775
5776 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5777
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005778 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5779 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005780
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005781 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005782 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005783 }
5784
Joe Onorato8a9b2202010-02-26 18:56:32 -08005785 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 TAG, "New app record " + app
5787 + " thread=" + thread.asBinder() + " pid=" + pid);
5788 try {
5789 int testMode = IApplicationThread.DEBUG_OFF;
5790 if (mDebugApp != null && mDebugApp.equals(processName)) {
5791 testMode = mWaitForDebugger
5792 ? IApplicationThread.DEBUG_WAIT
5793 : IApplicationThread.DEBUG_ON;
5794 app.debugging = true;
5795 if (mDebugTransient) {
5796 mDebugApp = mOrigDebugApp;
5797 mWaitForDebugger = mOrigWaitForDebugger;
5798 }
5799 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005800
Christopher Tate181fafa2009-05-14 11:12:14 -07005801 // If the app is being launched for restore or full backup, set it up specially
5802 boolean isRestrictedBackupMode = false;
5803 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5804 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5805 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5806 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005807
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005808 ensurePackageDexOpt(app.instrumentationInfo != null
5809 ? app.instrumentationInfo.packageName
5810 : app.info.packageName);
5811 if (app.instrumentationClass != null) {
5812 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005813 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005814 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005815 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005816 thread.bindApplication(processName, app.instrumentationInfo != null
5817 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818 app.instrumentationClass, app.instrumentationProfileFile,
5819 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005820 isRestrictedBackupMode || !normalMode,
5821 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005822 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005823 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005824 } catch (Exception e) {
5825 // todo: Yikes! What should we do? For now we will try to
5826 // start another process, but that could easily get us in
5827 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005828 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005829
5830 app.resetPackageList();
5831 startProcessLocked(app, "bind fail", processName);
5832 return false;
5833 }
5834
5835 // Remove this record from the list of starting applications.
5836 mPersistentStartingProcesses.remove(app);
5837 mProcessesOnHold.remove(app);
5838
5839 boolean badApp = false;
5840 boolean didSomething = false;
5841
5842 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005843 ActivityRecord hr = topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07005844 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005845 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5846 && processName.equals(hr.processName)) {
5847 try {
5848 if (realStartActivityLocked(hr, app, true, true)) {
5849 didSomething = true;
5850 }
5851 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005852 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 + hr.intent.getComponent().flattenToShortString(), e);
5854 badApp = true;
5855 }
5856 } else {
5857 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5858 }
5859 }
5860
5861 // Find any services that should be running in this process...
5862 if (!badApp && mPendingServices.size() > 0) {
5863 ServiceRecord sr = null;
5864 try {
5865 for (int i=0; i<mPendingServices.size(); i++) {
5866 sr = mPendingServices.get(i);
5867 if (app.info.uid != sr.appInfo.uid
5868 || !processName.equals(sr.processName)) {
5869 continue;
5870 }
5871
5872 mPendingServices.remove(i);
5873 i--;
5874 realStartServiceLocked(sr, app);
5875 didSomething = true;
5876 }
5877 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005878 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 + sr.shortName, e);
5880 badApp = true;
5881 }
5882 }
5883
5884 // Check if the next broadcast receiver is in this process...
5885 BroadcastRecord br = mPendingBroadcast;
5886 if (!badApp && br != null && br.curApp == app) {
5887 try {
5888 mPendingBroadcast = null;
5889 processCurBroadcastLocked(br, app);
5890 didSomething = true;
5891 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005892 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005893 + br.curComponent.flattenToShortString(), e);
5894 badApp = true;
5895 logBroadcastReceiverDiscard(br);
5896 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5897 br.resultExtras, br.resultAbort, true);
5898 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005899 // We need to reset the state if we fails to start the receiver.
5900 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005901 }
5902 }
5903
Christopher Tate181fafa2009-05-14 11:12:14 -07005904 // Check whether the next backup agent is in this process...
5905 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005906 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005907 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005908 try {
5909 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5910 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005911 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005912 e.printStackTrace();
5913 }
5914 }
5915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005916 if (badApp) {
5917 // todo: Also need to kill application to deal with all
5918 // kinds of exceptions.
5919 handleAppDiedLocked(app, false);
5920 return false;
5921 }
5922
5923 if (!didSomething) {
5924 updateOomAdjLocked();
5925 }
5926
5927 return true;
5928 }
5929
5930 public final void attachApplication(IApplicationThread thread) {
5931 synchronized (this) {
5932 int callingPid = Binder.getCallingPid();
5933 final long origId = Binder.clearCallingIdentity();
5934 attachApplicationLocked(thread, callingPid);
5935 Binder.restoreCallingIdentity(origId);
5936 }
5937 }
5938
Dianne Hackborne88846e2009-09-30 21:34:25 -07005939 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005940 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005941 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005942 Binder.restoreCallingIdentity(origId);
5943 }
5944
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005945 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005946 boolean remove) {
5947 int N = mStoppingActivities.size();
5948 if (N <= 0) return null;
5949
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005950 ArrayList<ActivityRecord> stops = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005951
5952 final boolean nowVisible = mResumedActivity != null
5953 && mResumedActivity.nowVisible
5954 && !mResumedActivity.waitingVisible;
5955 for (int i=0; i<N; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005956 ActivityRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005957 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005958 + nowVisible + " waitingVisible=" + s.waitingVisible
5959 + " finishing=" + s.finishing);
5960 if (s.waitingVisible && nowVisible) {
5961 mWaitingVisibleActivities.remove(s);
5962 s.waitingVisible = false;
5963 if (s.finishing) {
5964 // If this activity is finishing, it is sitting on top of
5965 // everyone else but we now know it is no longer needed...
5966 // so get rid of it. Otherwise, we need to go through the
5967 // normal flow and hide it once we determine that it is
5968 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005969 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970 mWindowManager.setAppVisibility(s, false);
5971 }
5972 }
5973 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005974 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005975 if (stops == null) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005976 stops = new ArrayList<ActivityRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005977 }
5978 stops.add(s);
5979 mStoppingActivities.remove(i);
5980 N--;
5981 i--;
5982 }
5983 }
5984
5985 return stops;
5986 }
5987
5988 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005989 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005990 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005991 mWindowManager.enableScreenAfterBoot();
5992 }
5993
Dianne Hackborne88846e2009-09-30 21:34:25 -07005994 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5995 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005996 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005997
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005998 ArrayList<ActivityRecord> stops = null;
5999 ArrayList<ActivityRecord> finishes = null;
6000 ArrayList<ActivityRecord> thumbnails = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006001 int NS = 0;
6002 int NF = 0;
6003 int NT = 0;
6004 IApplicationThread sendThumbnail = null;
6005 boolean booting = false;
6006 boolean enableScreen = false;
6007
6008 synchronized (this) {
6009 if (token != null) {
6010 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
6011 }
6012
6013 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07006014 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006015 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006016 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006017
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006018 if (fromTimeout) {
6019 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
6020 }
6021
Dianne Hackborne88846e2009-09-30 21:34:25 -07006022 // This is a hack to semi-deal with a race condition
6023 // in the client where it can be constructed with a
6024 // newer configuration from when we asked it to launch.
6025 // We'll update with whatever configuration it now says
6026 // it used to launch.
6027 if (config != null) {
6028 r.configuration = config;
6029 }
6030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006031 // No longer need to keep the device awake.
6032 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
6033 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
6034 mLaunchingActivity.release();
6035 }
6036
6037 // We are now idle. If someone is waiting for a thumbnail from
6038 // us, we can now deliver.
6039 r.idle = true;
6040 scheduleAppGcsLocked();
6041 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
6042 sendThumbnail = r.app.thread;
6043 r.thumbnailNeeded = false;
6044 }
6045
6046 // If this activity is fullscreen, set up to hide those under it.
6047
Joe Onorato8a9b2202010-02-26 18:56:32 -08006048 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006049 ensureActivitiesVisibleLocked(null, 0);
6050
Joe Onorato8a9b2202010-02-26 18:56:32 -08006051 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006052 if (!mBooted && !fromTimeout) {
6053 mBooted = true;
6054 enableScreen = true;
6055 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006056
6057 } else if (fromTimeout) {
6058 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006059 }
6060
6061 // Atomically retrieve all of the other things to do.
6062 stops = processStoppingActivitiesLocked(true);
6063 NS = stops != null ? stops.size() : 0;
6064 if ((NF=mFinishingActivities.size()) > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006065 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006066 mFinishingActivities.clear();
6067 }
6068 if ((NT=mCancelledThumbnails.size()) > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006069 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006070 mCancelledThumbnails.clear();
6071 }
6072
6073 booting = mBooting;
6074 mBooting = false;
6075 }
6076
6077 int i;
6078
6079 // Send thumbnail if requested.
6080 if (sendThumbnail != null) {
6081 try {
6082 sendThumbnail.requestThumbnail(token);
6083 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006084 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006085 sendPendingThumbnail(null, token, null, null, true);
6086 }
6087 }
6088
6089 // Stop any activities that are scheduled to do so but have been
6090 // waiting for the next one to start.
6091 for (i=0; i<NS; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006092 ActivityRecord r = (ActivityRecord)stops.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006093 synchronized (this) {
6094 if (r.finishing) {
6095 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
6096 } else {
6097 stopActivityLocked(r);
6098 }
6099 }
6100 }
6101
6102 // Finish any activities that are scheduled to do so but have been
6103 // waiting for the next one to start.
6104 for (i=0; i<NF; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006105 ActivityRecord r = (ActivityRecord)finishes.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006106 synchronized (this) {
6107 destroyActivityLocked(r, true);
6108 }
6109 }
6110
6111 // Report back to any thumbnail receivers.
6112 for (i=0; i<NT; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006113 ActivityRecord r = (ActivityRecord)thumbnails.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006114 sendPendingThumbnail(r, null, null, null, true);
6115 }
6116
6117 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006118 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006119 }
6120
6121 trimApplications();
6122 //dump();
6123 //mWindowManager.dump();
6124
6125 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006126 enableScreenAfterBoot();
6127 }
6128 }
6129
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006130 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006131 IntentFilter pkgFilter = new IntentFilter();
6132 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
6133 pkgFilter.addDataScheme("package");
6134 mContext.registerReceiver(new BroadcastReceiver() {
6135 @Override
6136 public void onReceive(Context context, Intent intent) {
6137 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
6138 if (pkgs != null) {
6139 for (String pkg : pkgs) {
6140 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
6141 setResultCode(Activity.RESULT_OK);
6142 return;
6143 }
6144 }
6145 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006146 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006147 }, pkgFilter);
6148
6149 synchronized (this) {
6150 // Ensure that any processes we had put on hold are now started
6151 // up.
6152 final int NP = mProcessesOnHold.size();
6153 if (NP > 0) {
6154 ArrayList<ProcessRecord> procs =
6155 new ArrayList<ProcessRecord>(mProcessesOnHold);
6156 for (int ip=0; ip<NP; ip++) {
6157 this.startProcessLocked(procs.get(ip), "on-hold", null);
6158 }
6159 }
6160
6161 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6162 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006163 broadcastIntentLocked(null, null,
6164 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
6165 null, null, 0, null, null,
6166 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
6167 false, false, MY_PID, Process.SYSTEM_UID);
6168 }
6169 }
6170 }
6171
6172 final void ensureBootCompleted() {
6173 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006174 boolean enableScreen;
6175 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006176 booting = mBooting;
6177 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006178 enableScreen = !mBooted;
6179 mBooted = true;
6180 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006181
6182 if (booting) {
6183 finishBooting();
6184 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006185
6186 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006187 enableScreenAfterBoot();
6188 }
6189 }
6190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006191 public final void activityPaused(IBinder token, Bundle icicle) {
6192 // Refuse possible leaked file descriptors
6193 if (icicle != null && icicle.hasFileDescriptors()) {
6194 throw new IllegalArgumentException("File descriptors passed in Bundle");
6195 }
6196
6197 final long origId = Binder.clearCallingIdentity();
6198 activityPaused(token, icicle, false);
6199 Binder.restoreCallingIdentity(origId);
6200 }
6201
6202 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006203 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006204 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
6205 + ", timeout=" + timeout);
6206
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006207 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006208
6209 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006210 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006211 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006212 r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006213 if (!timeout) {
6214 r.icicle = icicle;
6215 r.haveState = true;
6216 }
6217 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
6218 if (mPausingActivity == r) {
6219 r.state = ActivityState.PAUSED;
6220 completePauseLocked();
6221 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08006222 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006223 System.identityHashCode(r), r.shortComponentName,
6224 mPausingActivity != null
6225 ? mPausingActivity.shortComponentName : "(none)");
6226 }
6227 }
6228 }
6229 }
6230
6231 public final void activityStopped(IBinder token, Bitmap thumbnail,
6232 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006233 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006234 TAG, "Activity stopped: token=" + token);
6235
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006236 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006237
6238 final long origId = Binder.clearCallingIdentity();
6239
6240 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006241 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006242 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006243 r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006244 r.thumbnail = thumbnail;
6245 r.description = description;
6246 r.stopped = true;
6247 r.state = ActivityState.STOPPED;
6248 if (!r.finishing) {
6249 if (r.configDestroy) {
6250 destroyActivityLocked(r, true);
6251 resumeTopActivityLocked(null);
6252 }
6253 }
6254 }
6255 }
6256
6257 if (r != null) {
6258 sendPendingThumbnail(r, null, null, null, false);
6259 }
6260
6261 trimApplications();
6262
6263 Binder.restoreCallingIdentity(origId);
6264 }
6265
6266 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006267 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006268 synchronized (this) {
6269 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
6270
Dianne Hackborn75b03852009-06-12 15:43:26 -07006271 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006272 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006273 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006274 if (r.state == ActivityState.DESTROYING) {
6275 final long origId = Binder.clearCallingIdentity();
6276 removeActivityFromHistoryLocked(r);
6277 Binder.restoreCallingIdentity(origId);
6278 }
6279 }
6280 }
6281 }
6282
6283 public String getCallingPackage(IBinder token) {
6284 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006285 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07006286 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006287 }
6288 }
6289
6290 public ComponentName getCallingActivity(IBinder token) {
6291 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006292 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006293 return r != null ? r.intent.getComponent() : null;
6294 }
6295 }
6296
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006297 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006298 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006299 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006300 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006301 if (r != null) {
6302 return r.resultTo;
6303 }
6304 }
6305 return null;
6306 }
6307
6308 public ComponentName getActivityClassForToken(IBinder token) {
6309 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006310 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006311 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006312 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006313 return r.intent.getComponent();
6314 }
6315 return null;
6316 }
6317 }
6318
6319 public String getPackageForToken(IBinder token) {
6320 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006321 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006323 ActivityRecord r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006324 return r.packageName;
6325 }
6326 return null;
6327 }
6328 }
6329
6330 public IIntentSender getIntentSender(int type,
6331 String packageName, IBinder token, String resultWho,
6332 int requestCode, Intent intent, String resolvedType, int flags) {
6333 // Refuse possible leaked file descriptors
6334 if (intent != null && intent.hasFileDescriptors() == true) {
6335 throw new IllegalArgumentException("File descriptors passed in Intent");
6336 }
6337
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006338 if (type == INTENT_SENDER_BROADCAST) {
6339 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6340 throw new IllegalArgumentException(
6341 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6342 }
6343 }
6344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006345 synchronized(this) {
6346 int callingUid = Binder.getCallingUid();
6347 try {
6348 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6349 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006350 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 .getPackageUid(packageName);
6352 if (uid != Binder.getCallingUid()) {
6353 String msg = "Permission Denial: getIntentSender() from pid="
6354 + Binder.getCallingPid()
6355 + ", uid=" + Binder.getCallingUid()
6356 + ", (need uid=" + uid + ")"
6357 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006358 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006359 throw new SecurityException(msg);
6360 }
6361 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006362
6363 return getIntentSenderLocked(type, packageName, callingUid,
6364 token, resultWho, requestCode, intent, resolvedType, flags);
6365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006366 } catch (RemoteException e) {
6367 throw new SecurityException(e);
6368 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006369 }
6370 }
6371
6372 IIntentSender getIntentSenderLocked(int type,
6373 String packageName, int callingUid, IBinder token, String resultWho,
6374 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006375 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006376 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6377 int index = indexOfTokenLocked(token);
6378 if (index < 0) {
6379 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006381 activity = (ActivityRecord)mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07006382 if (activity.finishing) {
6383 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006385 }
6386
6387 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6388 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6389 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6390 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6391 |PendingIntent.FLAG_UPDATE_CURRENT);
6392
6393 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6394 type, packageName, activity, resultWho,
6395 requestCode, intent, resolvedType, flags);
6396 WeakReference<PendingIntentRecord> ref;
6397 ref = mIntentSenderRecords.get(key);
6398 PendingIntentRecord rec = ref != null ? ref.get() : null;
6399 if (rec != null) {
6400 if (!cancelCurrent) {
6401 if (updateCurrent) {
6402 rec.key.requestIntent.replaceExtras(intent);
6403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006404 return rec;
6405 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006406 rec.canceled = true;
6407 mIntentSenderRecords.remove(key);
6408 }
6409 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006410 return rec;
6411 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006412 rec = new PendingIntentRecord(this, key, callingUid);
6413 mIntentSenderRecords.put(key, rec.ref);
6414 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6415 if (activity.pendingResults == null) {
6416 activity.pendingResults
6417 = new HashSet<WeakReference<PendingIntentRecord>>();
6418 }
6419 activity.pendingResults.add(rec.ref);
6420 }
6421 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006422 }
6423
6424 public void cancelIntentSender(IIntentSender sender) {
6425 if (!(sender instanceof PendingIntentRecord)) {
6426 return;
6427 }
6428 synchronized(this) {
6429 PendingIntentRecord rec = (PendingIntentRecord)sender;
6430 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006431 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006432 .getPackageUid(rec.key.packageName);
6433 if (uid != Binder.getCallingUid()) {
6434 String msg = "Permission Denial: cancelIntentSender() from pid="
6435 + Binder.getCallingPid()
6436 + ", uid=" + Binder.getCallingUid()
6437 + " is not allowed to cancel packges "
6438 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006439 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006440 throw new SecurityException(msg);
6441 }
6442 } catch (RemoteException e) {
6443 throw new SecurityException(e);
6444 }
6445 cancelIntentSenderLocked(rec, true);
6446 }
6447 }
6448
6449 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6450 rec.canceled = true;
6451 mIntentSenderRecords.remove(rec.key);
6452 if (cleanActivity && rec.key.activity != null) {
6453 rec.key.activity.pendingResults.remove(rec.ref);
6454 }
6455 }
6456
6457 public String getPackageForIntentSender(IIntentSender pendingResult) {
6458 if (!(pendingResult instanceof PendingIntentRecord)) {
6459 return null;
6460 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006461 try {
6462 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6463 return res.key.packageName;
6464 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006465 }
6466 return null;
6467 }
6468
6469 public void setProcessLimit(int max) {
6470 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6471 "setProcessLimit()");
6472 mProcessLimit = max;
6473 }
6474
6475 public int getProcessLimit() {
6476 return mProcessLimit;
6477 }
6478
6479 void foregroundTokenDied(ForegroundToken token) {
6480 synchronized (ActivityManagerService.this) {
6481 synchronized (mPidsSelfLocked) {
6482 ForegroundToken cur
6483 = mForegroundProcesses.get(token.pid);
6484 if (cur != token) {
6485 return;
6486 }
6487 mForegroundProcesses.remove(token.pid);
6488 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6489 if (pr == null) {
6490 return;
6491 }
6492 pr.forcingToForeground = null;
6493 pr.foregroundServices = false;
6494 }
6495 updateOomAdjLocked();
6496 }
6497 }
6498
6499 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6500 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6501 "setProcessForeground()");
6502 synchronized(this) {
6503 boolean changed = false;
6504
6505 synchronized (mPidsSelfLocked) {
6506 ProcessRecord pr = mPidsSelfLocked.get(pid);
6507 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006508 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006509 return;
6510 }
6511 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6512 if (oldToken != null) {
6513 oldToken.token.unlinkToDeath(oldToken, 0);
6514 mForegroundProcesses.remove(pid);
6515 pr.forcingToForeground = null;
6516 changed = true;
6517 }
6518 if (isForeground && token != null) {
6519 ForegroundToken newToken = new ForegroundToken() {
6520 public void binderDied() {
6521 foregroundTokenDied(this);
6522 }
6523 };
6524 newToken.pid = pid;
6525 newToken.token = token;
6526 try {
6527 token.linkToDeath(newToken, 0);
6528 mForegroundProcesses.put(pid, newToken);
6529 pr.forcingToForeground = token;
6530 changed = true;
6531 } catch (RemoteException e) {
6532 // If the process died while doing this, we will later
6533 // do the cleanup with the process death link.
6534 }
6535 }
6536 }
6537
6538 if (changed) {
6539 updateOomAdjLocked();
6540 }
6541 }
6542 }
6543
6544 // =========================================================
6545 // PERMISSIONS
6546 // =========================================================
6547
6548 static class PermissionController extends IPermissionController.Stub {
6549 ActivityManagerService mActivityManagerService;
6550 PermissionController(ActivityManagerService activityManagerService) {
6551 mActivityManagerService = activityManagerService;
6552 }
6553
6554 public boolean checkPermission(String permission, int pid, int uid) {
6555 return mActivityManagerService.checkPermission(permission, pid,
6556 uid) == PackageManager.PERMISSION_GRANTED;
6557 }
6558 }
6559
6560 /**
6561 * This can be called with or without the global lock held.
6562 */
6563 int checkComponentPermission(String permission, int pid, int uid,
6564 int reqUid) {
6565 // We might be performing an operation on behalf of an indirect binder
6566 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6567 // client identity accordingly before proceeding.
6568 Identity tlsIdentity = sCallerIdentity.get();
6569 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006570 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006571 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6572 uid = tlsIdentity.uid;
6573 pid = tlsIdentity.pid;
6574 }
6575
6576 // Root, system server and our own process get to do everything.
6577 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6578 !Process.supportsProcesses()) {
6579 return PackageManager.PERMISSION_GRANTED;
6580 }
6581 // If the target requires a specific UID, always fail for others.
6582 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006583 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 return PackageManager.PERMISSION_DENIED;
6585 }
6586 if (permission == null) {
6587 return PackageManager.PERMISSION_GRANTED;
6588 }
6589 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006590 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006591 .checkUidPermission(permission, uid);
6592 } catch (RemoteException e) {
6593 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006594 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006595 }
6596 return PackageManager.PERMISSION_DENIED;
6597 }
6598
6599 /**
6600 * As the only public entry point for permissions checking, this method
6601 * can enforce the semantic that requesting a check on a null global
6602 * permission is automatically denied. (Internally a null permission
6603 * string is used when calling {@link #checkComponentPermission} in cases
6604 * when only uid-based security is needed.)
6605 *
6606 * This can be called with or without the global lock held.
6607 */
6608 public int checkPermission(String permission, int pid, int uid) {
6609 if (permission == null) {
6610 return PackageManager.PERMISSION_DENIED;
6611 }
6612 return checkComponentPermission(permission, pid, uid, -1);
6613 }
6614
6615 /**
6616 * Binder IPC calls go through the public entry point.
6617 * This can be called with or without the global lock held.
6618 */
6619 int checkCallingPermission(String permission) {
6620 return checkPermission(permission,
6621 Binder.getCallingPid(),
6622 Binder.getCallingUid());
6623 }
6624
6625 /**
6626 * This can be called with or without the global lock held.
6627 */
6628 void enforceCallingPermission(String permission, String func) {
6629 if (checkCallingPermission(permission)
6630 == PackageManager.PERMISSION_GRANTED) {
6631 return;
6632 }
6633
6634 String msg = "Permission Denial: " + func + " from pid="
6635 + Binder.getCallingPid()
6636 + ", uid=" + Binder.getCallingUid()
6637 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006638 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006639 throw new SecurityException(msg);
6640 }
6641
6642 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6643 ProviderInfo pi, int uid, int modeFlags) {
6644 try {
6645 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6646 if ((pi.readPermission != null) &&
6647 (pm.checkUidPermission(pi.readPermission, uid)
6648 != PackageManager.PERMISSION_GRANTED)) {
6649 return false;
6650 }
6651 }
6652 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6653 if ((pi.writePermission != null) &&
6654 (pm.checkUidPermission(pi.writePermission, uid)
6655 != PackageManager.PERMISSION_GRANTED)) {
6656 return false;
6657 }
6658 }
6659 return true;
6660 } catch (RemoteException e) {
6661 return false;
6662 }
6663 }
6664
6665 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6666 int modeFlags) {
6667 // Root gets to do everything.
6668 if (uid == 0 || !Process.supportsProcesses()) {
6669 return true;
6670 }
6671 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6672 if (perms == null) return false;
6673 UriPermission perm = perms.get(uri);
6674 if (perm == null) return false;
6675 return (modeFlags&perm.modeFlags) == modeFlags;
6676 }
6677
6678 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6679 // Another redirected-binder-call permissions check as in
6680 // {@link checkComponentPermission}.
6681 Identity tlsIdentity = sCallerIdentity.get();
6682 if (tlsIdentity != null) {
6683 uid = tlsIdentity.uid;
6684 pid = tlsIdentity.pid;
6685 }
6686
6687 // Our own process gets to do everything.
6688 if (pid == MY_PID) {
6689 return PackageManager.PERMISSION_GRANTED;
6690 }
6691 synchronized(this) {
6692 return checkUriPermissionLocked(uri, uid, modeFlags)
6693 ? PackageManager.PERMISSION_GRANTED
6694 : PackageManager.PERMISSION_DENIED;
6695 }
6696 }
6697
6698 private void grantUriPermissionLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006699 String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006700 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6701 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6702 if (modeFlags == 0) {
6703 return;
6704 }
6705
Joe Onorato8a9b2202010-02-26 18:56:32 -08006706 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006707 "Requested grant " + targetPkg + " permission to " + uri);
6708
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006709 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006710
6711 // If this is not a content: uri, we can't do anything with it.
6712 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006713 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006714 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 return;
6716 }
6717
6718 String name = uri.getAuthority();
6719 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006720 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006721 if (cpr != null) {
6722 pi = cpr.info;
6723 } else {
6724 try {
6725 pi = pm.resolveContentProvider(name,
6726 PackageManager.GET_URI_PERMISSION_PATTERNS);
6727 } catch (RemoteException ex) {
6728 }
6729 }
6730 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006731 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 return;
6733 }
6734
6735 int targetUid;
6736 try {
6737 targetUid = pm.getPackageUid(targetPkg);
6738 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006739 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006740 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006741 return;
6742 }
6743 } catch (RemoteException ex) {
6744 return;
6745 }
6746
6747 // First... does the target actually need this permission?
6748 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6749 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006750 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006751 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006752 return;
6753 }
6754
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006755 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006756 if (!pi.grantUriPermissions) {
6757 throw new SecurityException("Provider " + pi.packageName
6758 + "/" + pi.name
6759 + " does not allow granting of Uri permissions (uri "
6760 + uri + ")");
6761 }
6762 if (pi.uriPermissionPatterns != null) {
6763 final int N = pi.uriPermissionPatterns.length;
6764 boolean allowed = false;
6765 for (int i=0; i<N; i++) {
6766 if (pi.uriPermissionPatterns[i] != null
6767 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6768 allowed = true;
6769 break;
6770 }
6771 }
6772 if (!allowed) {
6773 throw new SecurityException("Provider " + pi.packageName
6774 + "/" + pi.name
6775 + " does not allow granting of permission to path of Uri "
6776 + uri);
6777 }
6778 }
6779
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006780 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006781 // this uri?
6782 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6783 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6784 throw new SecurityException("Uid " + callingUid
6785 + " does not have permission to uri " + uri);
6786 }
6787 }
6788
6789 // Okay! So here we are: the caller has the assumed permission
6790 // to the uri, and the target doesn't. Let's now give this to
6791 // the target.
6792
Joe Onorato8a9b2202010-02-26 18:56:32 -08006793 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006794 "Granting " + targetPkg + " permission to " + uri);
6795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006796 HashMap<Uri, UriPermission> targetUris
6797 = mGrantedUriPermissions.get(targetUid);
6798 if (targetUris == null) {
6799 targetUris = new HashMap<Uri, UriPermission>();
6800 mGrantedUriPermissions.put(targetUid, targetUris);
6801 }
6802
6803 UriPermission perm = targetUris.get(uri);
6804 if (perm == null) {
6805 perm = new UriPermission(targetUid, uri);
6806 targetUris.put(uri, perm);
6807
6808 }
6809 perm.modeFlags |= modeFlags;
6810 if (activity == null) {
6811 perm.globalModeFlags |= modeFlags;
6812 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6813 perm.readActivities.add(activity);
6814 if (activity.readUriPermissions == null) {
6815 activity.readUriPermissions = new HashSet<UriPermission>();
6816 }
6817 activity.readUriPermissions.add(perm);
6818 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6819 perm.writeActivities.add(activity);
6820 if (activity.writeUriPermissions == null) {
6821 activity.writeUriPermissions = new HashSet<UriPermission>();
6822 }
6823 activity.writeUriPermissions.add(perm);
6824 }
6825 }
6826
6827 private void grantUriPermissionFromIntentLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006828 String targetPkg, Intent intent, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006829 if (intent == null) {
6830 return;
6831 }
6832 Uri data = intent.getData();
6833 if (data == null) {
6834 return;
6835 }
6836 grantUriPermissionLocked(callingUid, targetPkg, data,
6837 intent.getFlags(), activity);
6838 }
6839
6840 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6841 Uri uri, int modeFlags) {
6842 synchronized(this) {
6843 final ProcessRecord r = getRecordForAppLocked(caller);
6844 if (r == null) {
6845 throw new SecurityException("Unable to find app for caller "
6846 + caller
6847 + " when granting permission to uri " + uri);
6848 }
6849 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006850 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006851 return;
6852 }
6853 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006854 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006855 return;
6856 }
6857
6858 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6859 null);
6860 }
6861 }
6862
6863 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6864 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6865 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6866 HashMap<Uri, UriPermission> perms
6867 = mGrantedUriPermissions.get(perm.uid);
6868 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006869 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006870 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006871 perms.remove(perm.uri);
6872 if (perms.size() == 0) {
6873 mGrantedUriPermissions.remove(perm.uid);
6874 }
6875 }
6876 }
6877 }
6878
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006879 private void removeActivityUriPermissionsLocked(ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006880 if (activity.readUriPermissions != null) {
6881 for (UriPermission perm : activity.readUriPermissions) {
6882 perm.readActivities.remove(activity);
6883 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6884 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6885 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6886 removeUriPermissionIfNeededLocked(perm);
6887 }
6888 }
6889 }
6890 if (activity.writeUriPermissions != null) {
6891 for (UriPermission perm : activity.writeUriPermissions) {
6892 perm.writeActivities.remove(activity);
6893 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6894 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6895 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6896 removeUriPermissionIfNeededLocked(perm);
6897 }
6898 }
6899 }
6900 }
6901
6902 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6903 int modeFlags) {
6904 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6905 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6906 if (modeFlags == 0) {
6907 return;
6908 }
6909
Joe Onorato8a9b2202010-02-26 18:56:32 -08006910 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006911 "Revoking all granted permissions to " + uri);
6912
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006913 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006914
6915 final String authority = uri.getAuthority();
6916 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006917 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006918 if (cpr != null) {
6919 pi = cpr.info;
6920 } else {
6921 try {
6922 pi = pm.resolveContentProvider(authority,
6923 PackageManager.GET_URI_PERMISSION_PATTERNS);
6924 } catch (RemoteException ex) {
6925 }
6926 }
6927 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006928 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006929 return;
6930 }
6931
6932 // Does the caller have this permission on the URI?
6933 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6934 // Right now, if you are not the original owner of the permission,
6935 // you are not allowed to revoke it.
6936 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6937 throw new SecurityException("Uid " + callingUid
6938 + " does not have permission to uri " + uri);
6939 //}
6940 }
6941
6942 // Go through all of the permissions and remove any that match.
6943 final List<String> SEGMENTS = uri.getPathSegments();
6944 if (SEGMENTS != null) {
6945 final int NS = SEGMENTS.size();
6946 int N = mGrantedUriPermissions.size();
6947 for (int i=0; i<N; i++) {
6948 HashMap<Uri, UriPermission> perms
6949 = mGrantedUriPermissions.valueAt(i);
6950 Iterator<UriPermission> it = perms.values().iterator();
6951 toploop:
6952 while (it.hasNext()) {
6953 UriPermission perm = it.next();
6954 Uri targetUri = perm.uri;
6955 if (!authority.equals(targetUri.getAuthority())) {
6956 continue;
6957 }
6958 List<String> targetSegments = targetUri.getPathSegments();
6959 if (targetSegments == null) {
6960 continue;
6961 }
6962 if (targetSegments.size() < NS) {
6963 continue;
6964 }
6965 for (int j=0; j<NS; j++) {
6966 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6967 continue toploop;
6968 }
6969 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006970 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006971 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006972 perm.clearModes(modeFlags);
6973 if (perm.modeFlags == 0) {
6974 it.remove();
6975 }
6976 }
6977 if (perms.size() == 0) {
6978 mGrantedUriPermissions.remove(
6979 mGrantedUriPermissions.keyAt(i));
6980 N--;
6981 i--;
6982 }
6983 }
6984 }
6985 }
6986
6987 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6988 int modeFlags) {
6989 synchronized(this) {
6990 final ProcessRecord r = getRecordForAppLocked(caller);
6991 if (r == null) {
6992 throw new SecurityException("Unable to find app for caller "
6993 + caller
6994 + " when revoking permission to uri " + uri);
6995 }
6996 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006997 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006998 return;
6999 }
7000
7001 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
7002 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
7003 if (modeFlags == 0) {
7004 return;
7005 }
7006
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007007 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007008
7009 final String authority = uri.getAuthority();
7010 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07007011 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007012 if (cpr != null) {
7013 pi = cpr.info;
7014 } else {
7015 try {
7016 pi = pm.resolveContentProvider(authority,
7017 PackageManager.GET_URI_PERMISSION_PATTERNS);
7018 } catch (RemoteException ex) {
7019 }
7020 }
7021 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007022 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007023 return;
7024 }
7025
7026 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
7027 }
7028 }
7029
7030 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
7031 synchronized (this) {
7032 ProcessRecord app =
7033 who != null ? getRecordForAppLocked(who) : null;
7034 if (app == null) return;
7035
7036 Message msg = Message.obtain();
7037 msg.what = WAIT_FOR_DEBUGGER_MSG;
7038 msg.obj = app;
7039 msg.arg1 = waiting ? 1 : 0;
7040 mHandler.sendMessage(msg);
7041 }
7042 }
7043
7044 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
7045 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08007046 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007047 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08007048 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007049 }
7050
7051 // =========================================================
7052 // TASK MANAGEMENT
7053 // =========================================================
7054
7055 public List getTasks(int maxNum, int flags,
7056 IThumbnailReceiver receiver) {
7057 ArrayList list = new ArrayList();
7058
7059 PendingThumbnailsRecord pending = null;
7060 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007061 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007062
7063 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007064 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007065 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
7066 + ", receiver=" + receiver);
7067
7068 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
7069 != PackageManager.PERMISSION_GRANTED) {
7070 if (receiver != null) {
7071 // If the caller wants to wait for pending thumbnails,
7072 // it ain't gonna get them.
7073 try {
7074 receiver.finished();
7075 } catch (RemoteException ex) {
7076 }
7077 }
7078 String msg = "Permission Denial: getTasks() from pid="
7079 + Binder.getCallingPid()
7080 + ", uid=" + Binder.getCallingUid()
7081 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007082 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007083 throw new SecurityException(msg);
7084 }
7085
7086 int pos = mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007087 ActivityRecord next =
7088 pos >= 0 ? (ActivityRecord)mHistory.get(pos) : null;
7089 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007090 CharSequence topDescription = null;
7091 TaskRecord curTask = null;
7092 int numActivities = 0;
7093 int numRunning = 0;
7094 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007095 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007096 pos--;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007097 next = pos >= 0 ? (ActivityRecord)mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007098
7099 // Initialize state for next task if needed.
7100 if (top == null ||
7101 (top.state == ActivityState.INITIALIZING
7102 && top.task == r.task)) {
7103 top = r;
7104 topDescription = r.description;
7105 curTask = r.task;
7106 numActivities = numRunning = 0;
7107 }
7108
7109 // Add 'r' into the current task.
7110 numActivities++;
7111 if (r.app != null && r.app.thread != null) {
7112 numRunning++;
7113 }
7114 if (topDescription == null) {
7115 topDescription = r.description;
7116 }
7117
Joe Onorato8a9b2202010-02-26 18:56:32 -08007118 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007119 TAG, r.intent.getComponent().flattenToShortString()
7120 + ": task=" + r.task);
7121
7122 // If the next one is a different task, generate a new
7123 // TaskInfo entry for what we have.
7124 if (next == null || next.task != curTask) {
7125 ActivityManager.RunningTaskInfo ci
7126 = new ActivityManager.RunningTaskInfo();
7127 ci.id = curTask.taskId;
7128 ci.baseActivity = r.intent.getComponent();
7129 ci.topActivity = top.intent.getComponent();
7130 ci.thumbnail = top.thumbnail;
7131 ci.description = topDescription;
7132 ci.numActivities = numActivities;
7133 ci.numRunning = numRunning;
7134 //System.out.println(
7135 // "#" + maxNum + ": " + " descr=" + ci.description);
7136 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007137 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007138 TAG, "State=" + top.state + "Idle=" + top.idle
7139 + " app=" + top.app
7140 + " thr=" + (top.app != null ? top.app.thread : null));
7141 if (top.state == ActivityState.RESUMED
7142 || top.state == ActivityState.PAUSING) {
7143 if (top.idle && top.app != null
7144 && top.app.thread != null) {
7145 topRecord = top;
7146 topThumbnail = top.app.thread;
7147 } else {
7148 top.thumbnailNeeded = true;
7149 }
7150 }
7151 if (pending == null) {
7152 pending = new PendingThumbnailsRecord(receiver);
7153 }
7154 pending.pendingRecords.add(top);
7155 }
7156 list.add(ci);
7157 maxNum--;
7158 top = null;
7159 }
7160 }
7161
7162 if (pending != null) {
7163 mPendingThumbnails.add(pending);
7164 }
7165 }
7166
Joe Onorato8a9b2202010-02-26 18:56:32 -08007167 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007168
7169 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007170 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007171 try {
7172 topThumbnail.requestThumbnail(topRecord);
7173 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007174 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007175 sendPendingThumbnail(null, topRecord, null, null, true);
7176 }
7177 }
7178
7179 if (pending == null && receiver != null) {
7180 // In this case all thumbnails were available and the client
7181 // is being asked to be told when the remaining ones come in...
7182 // which is unusually, since the top-most currently running
7183 // activity should never have a canned thumbnail! Oh well.
7184 try {
7185 receiver.finished();
7186 } catch (RemoteException ex) {
7187 }
7188 }
7189
7190 return list;
7191 }
7192
7193 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
7194 int flags) {
7195 synchronized (this) {
7196 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
7197 "getRecentTasks()");
7198
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007199 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007201 final int N = mRecentTasks.size();
7202 ArrayList<ActivityManager.RecentTaskInfo> res
7203 = new ArrayList<ActivityManager.RecentTaskInfo>(
7204 maxNum < N ? maxNum : N);
7205 for (int i=0; i<N && maxNum > 0; i++) {
7206 TaskRecord tr = mRecentTasks.get(i);
7207 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
7208 || (tr.intent == null)
7209 || ((tr.intent.getFlags()
7210 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
7211 ActivityManager.RecentTaskInfo rti
7212 = new ActivityManager.RecentTaskInfo();
7213 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
7214 rti.baseIntent = new Intent(
7215 tr.intent != null ? tr.intent : tr.affinityIntent);
7216 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007217
7218 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
7219 // Check whether this activity is currently available.
7220 try {
7221 if (rti.origActivity != null) {
7222 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
7223 continue;
7224 }
7225 } else if (rti.baseIntent != null) {
7226 if (pm.queryIntentActivities(rti.baseIntent,
7227 null, 0) == null) {
7228 continue;
7229 }
7230 }
7231 } catch (RemoteException e) {
7232 // Will never happen.
7233 }
7234 }
7235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007236 res.add(rti);
7237 maxNum--;
7238 }
7239 }
7240 return res;
7241 }
7242 }
7243
7244 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
7245 int j;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007246 TaskRecord startTask = ((ActivityRecord)mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007247 TaskRecord jt = startTask;
7248
7249 // First look backwards
7250 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007251 ActivityRecord r = (ActivityRecord)mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252 if (r.task != jt) {
7253 jt = r.task;
7254 if (affinity.equals(jt.affinity)) {
7255 return j;
7256 }
7257 }
7258 }
7259
7260 // Now look forwards
7261 final int N = mHistory.size();
7262 jt = startTask;
7263 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007264 ActivityRecord r = (ActivityRecord)mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007265 if (r.task != jt) {
7266 if (affinity.equals(jt.affinity)) {
7267 return j;
7268 }
7269 jt = r.task;
7270 }
7271 }
7272
7273 // Might it be at the top?
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007274 if (affinity.equals(((ActivityRecord)mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007275 return N-1;
7276 }
7277
7278 return -1;
7279 }
7280
7281 /**
7282 * Perform a reset of the given task, if needed as part of launching it.
7283 * Returns the new HistoryRecord at the top of the task.
7284 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007285 private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
7286 ActivityRecord newActivity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007287 boolean forceReset = (newActivity.info.flags
7288 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
7289 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
7290 if ((newActivity.info.flags
7291 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
7292 forceReset = true;
7293 }
7294 }
7295
7296 final TaskRecord task = taskTop.task;
7297
7298 // We are going to move through the history list so that we can look
7299 // at each activity 'target' with 'below' either the interesting
7300 // activity immediately below it in the stack or null.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007301 ActivityRecord target = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007302 int targetI = 0;
7303 int taskTopI = -1;
7304 int replyChainEnd = -1;
7305 int lastReparentPos = -1;
7306 for (int i=mHistory.size()-1; i>=-1; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007307 ActivityRecord below = i >= 0 ? (ActivityRecord)mHistory.get(i) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308
7309 if (below != null && below.finishing) {
7310 continue;
7311 }
7312 if (target == null) {
7313 target = below;
7314 targetI = i;
7315 // If we were in the middle of a reply chain before this
7316 // task, it doesn't appear like the root of the chain wants
7317 // anything interesting, so drop it.
7318 replyChainEnd = -1;
7319 continue;
7320 }
7321
7322 final int flags = target.info.flags;
7323
7324 final boolean finishOnTaskLaunch =
7325 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7326 final boolean allowTaskReparenting =
7327 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7328
7329 if (target.task == task) {
7330 // We are inside of the task being reset... we'll either
7331 // finish this activity, push it out for another task,
7332 // or leave it as-is. We only do this
7333 // for activities that are not the root of the task (since
7334 // if we finish the root, we may no longer have the task!).
7335 if (taskTopI < 0) {
7336 taskTopI = targetI;
7337 }
7338 if (below != null && below.task == task) {
7339 final boolean clearWhenTaskReset =
7340 (target.intent.getFlags()
7341 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007342 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007343 // If this activity is sending a reply to a previous
7344 // activity, we can't do anything with it now until
7345 // we reach the start of the reply chain.
7346 // XXX note that we are assuming the result is always
7347 // to the previous activity, which is almost always
7348 // the case but we really shouldn't count on.
7349 if (replyChainEnd < 0) {
7350 replyChainEnd = targetI;
7351 }
Ed Heyl73798232009-03-24 21:32:21 -07007352 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007353 && target.taskAffinity != null
7354 && !target.taskAffinity.equals(task.affinity)) {
7355 // If this activity has an affinity for another
7356 // task, then we need to move it out of here. We will
7357 // move it as far out of the way as possible, to the
7358 // bottom of the activity stack. This also keeps it
7359 // correctly ordered with any activities we previously
7360 // moved.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007361 ActivityRecord p = (ActivityRecord)mHistory.get(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007362 if (target.taskAffinity != null
7363 && target.taskAffinity.equals(p.task.affinity)) {
7364 // If the activity currently at the bottom has the
7365 // same task affinity as the one we are moving,
7366 // then merge it into the same task.
7367 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007368 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007369 + " out to bottom task " + p.task);
7370 } else {
7371 mCurTask++;
7372 if (mCurTask <= 0) {
7373 mCurTask = 1;
7374 }
7375 target.task = new TaskRecord(mCurTask, target.info, null,
7376 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7377 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007378 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007379 + " out to new task " + target.task);
7380 }
7381 mWindowManager.setAppGroupId(target, task.taskId);
7382 if (replyChainEnd < 0) {
7383 replyChainEnd = targetI;
7384 }
7385 int dstPos = 0;
7386 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007387 p = (ActivityRecord)mHistory.get(srcPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007388 if (p.finishing) {
7389 continue;
7390 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007391 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007392 + " out to target's task " + target.task);
7393 task.numActivities--;
7394 p.task = target.task;
7395 target.task.numActivities++;
7396 mHistory.remove(srcPos);
7397 mHistory.add(dstPos, p);
7398 mWindowManager.moveAppToken(dstPos, p);
7399 mWindowManager.setAppGroupId(p, p.task.taskId);
7400 dstPos++;
7401 if (VALIDATE_TOKENS) {
7402 mWindowManager.validateAppTokens(mHistory);
7403 }
7404 i++;
7405 }
7406 if (taskTop == p) {
7407 taskTop = below;
7408 }
7409 if (taskTopI == replyChainEnd) {
7410 taskTopI = -1;
7411 }
7412 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007413 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 } else if (forceReset || finishOnTaskLaunch
7415 || clearWhenTaskReset) {
7416 // If the activity should just be removed -- either
7417 // because it asks for it, or the task should be
7418 // cleared -- then finish it and anything that is
7419 // part of its reply chain.
7420 if (clearWhenTaskReset) {
7421 // In this case, we want to finish this activity
7422 // and everything above it, so be sneaky and pretend
7423 // like these are all in the reply chain.
7424 replyChainEnd = targetI+1;
7425 while (replyChainEnd < mHistory.size() &&
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007426 ((ActivityRecord)mHistory.get(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 replyChainEnd)).task == task) {
7428 replyChainEnd++;
7429 }
7430 replyChainEnd--;
7431 } else if (replyChainEnd < 0) {
7432 replyChainEnd = targetI;
7433 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007434 ActivityRecord p = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007435 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007436 p = (ActivityRecord)mHistory.get(srcPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007437 if (p.finishing) {
7438 continue;
7439 }
7440 if (finishActivityLocked(p, srcPos,
7441 Activity.RESULT_CANCELED, null, "reset")) {
7442 replyChainEnd--;
7443 srcPos--;
7444 }
7445 }
7446 if (taskTop == p) {
7447 taskTop = below;
7448 }
7449 if (taskTopI == replyChainEnd) {
7450 taskTopI = -1;
7451 }
7452 replyChainEnd = -1;
7453 } else {
7454 // If we were in the middle of a chain, well the
7455 // activity that started it all doesn't want anything
7456 // special, so leave it all as-is.
7457 replyChainEnd = -1;
7458 }
7459 } else {
7460 // Reached the bottom of the task -- any reply chain
7461 // should be left as-is.
7462 replyChainEnd = -1;
7463 }
7464
7465 } else if (target.resultTo != null) {
7466 // If this activity is sending a reply to a previous
7467 // activity, we can't do anything with it now until
7468 // we reach the start of the reply chain.
7469 // XXX note that we are assuming the result is always
7470 // to the previous activity, which is almost always
7471 // the case but we really shouldn't count on.
7472 if (replyChainEnd < 0) {
7473 replyChainEnd = targetI;
7474 }
7475
7476 } else if (taskTopI >= 0 && allowTaskReparenting
7477 && task.affinity != null
7478 && task.affinity.equals(target.taskAffinity)) {
7479 // We are inside of another task... if this activity has
7480 // an affinity for our task, then either remove it if we are
7481 // clearing or move it over to our task. Note that
7482 // we currently punt on the case where we are resetting a
7483 // task that is not at the top but who has activities above
7484 // with an affinity to it... this is really not a normal
7485 // case, and we will need to later pull that task to the front
7486 // and usually at that point we will do the reset and pick
7487 // up those remaining activities. (This only happens if
7488 // someone starts an activity in a new task from an activity
7489 // in a task that is not currently on top.)
7490 if (forceReset || finishOnTaskLaunch) {
7491 if (replyChainEnd < 0) {
7492 replyChainEnd = targetI;
7493 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007494 ActivityRecord p = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007496 p = (ActivityRecord)mHistory.get(srcPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007497 if (p.finishing) {
7498 continue;
7499 }
7500 if (finishActivityLocked(p, srcPos,
7501 Activity.RESULT_CANCELED, null, "reset")) {
7502 taskTopI--;
7503 lastReparentPos--;
7504 replyChainEnd--;
7505 srcPos--;
7506 }
7507 }
7508 replyChainEnd = -1;
7509 } else {
7510 if (replyChainEnd < 0) {
7511 replyChainEnd = targetI;
7512 }
7513 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007514 ActivityRecord p = (ActivityRecord)mHistory.get(srcPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 if (p.finishing) {
7516 continue;
7517 }
7518 if (lastReparentPos < 0) {
7519 lastReparentPos = taskTopI;
7520 taskTop = p;
7521 } else {
7522 lastReparentPos--;
7523 }
7524 mHistory.remove(srcPos);
7525 p.task.numActivities--;
7526 p.task = task;
7527 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007528 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007529 + " in to resetting task " + task);
7530 task.numActivities++;
7531 mWindowManager.moveAppToken(lastReparentPos, p);
7532 mWindowManager.setAppGroupId(p, p.task.taskId);
7533 if (VALIDATE_TOKENS) {
7534 mWindowManager.validateAppTokens(mHistory);
7535 }
7536 }
7537 replyChainEnd = -1;
7538
7539 // Now we've moved it in to place... but what if this is
7540 // a singleTop activity and we have put it on top of another
7541 // instance of the same activity? Then we drop the instance
7542 // below so it remains singleTop.
7543 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7544 for (int j=lastReparentPos-1; j>=0; j--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007545 ActivityRecord p = (ActivityRecord)mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007546 if (p.finishing) {
7547 continue;
7548 }
7549 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7550 if (finishActivityLocked(p, j,
7551 Activity.RESULT_CANCELED, null, "replace")) {
7552 taskTopI--;
7553 lastReparentPos--;
7554 }
7555 }
7556 }
7557 }
7558 }
7559 }
7560
7561 target = below;
7562 targetI = i;
7563 }
7564
7565 return taskTop;
7566 }
7567
7568 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007569 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 */
7571 public void moveTaskToFront(int task) {
7572 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7573 "moveTaskToFront()");
7574
7575 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007576 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7577 Binder.getCallingUid(), "Task to front")) {
7578 return;
7579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 final long origId = Binder.clearCallingIdentity();
7581 try {
7582 int N = mRecentTasks.size();
7583 for (int i=0; i<N; i++) {
7584 TaskRecord tr = mRecentTasks.get(i);
7585 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007586 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007587 return;
7588 }
7589 }
7590 for (int i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007591 ActivityRecord hr = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007592 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007593 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007594 return;
7595 }
7596 }
7597 } finally {
7598 Binder.restoreCallingIdentity(origId);
7599 }
7600 }
7601 }
7602
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007603 private final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007604 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007605
7606 final int task = tr.taskId;
7607 int top = mHistory.size()-1;
7608
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007609 if (top < 0 || ((ActivityRecord)mHistory.get(top)).task.taskId == task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007610 // nothing to do!
7611 return;
7612 }
7613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007614 ArrayList moved = new ArrayList();
7615
7616 // Applying the affinities may have removed entries from the history,
7617 // so get the size again.
7618 top = mHistory.size()-1;
7619 int pos = top;
7620
7621 // Shift all activities with this task up to the top
7622 // of the stack, keeping them in the same internal order.
7623 while (pos >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007624 ActivityRecord r = (ActivityRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007625 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007626 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7627 boolean first = true;
7628 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007629 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007630 mHistory.remove(pos);
7631 mHistory.add(top, r);
7632 moved.add(0, r);
7633 top--;
7634 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007635 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007636 first = false;
7637 }
7638 }
7639 pos--;
7640 }
7641
Joe Onorato8a9b2202010-02-26 18:56:32 -08007642 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007643 "Prepare to front transition: task=" + tr);
7644 if (reason != null &&
7645 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7646 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007647 ActivityRecord r = topRunningActivityLocked(null);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007648 if (r != null) {
7649 mNoAnimActivities.add(r);
7650 }
7651 } else {
7652 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7653 }
7654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007655 mWindowManager.moveAppTokensToTop(moved);
7656 if (VALIDATE_TOKENS) {
7657 mWindowManager.validateAppTokens(mHistory);
7658 }
7659
Josh Bartel7f208742010-02-25 11:01:44 -06007660 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007661 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007662 }
7663
Josh Bartel7f208742010-02-25 11:01:44 -06007664 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007665 resumeTopActivityLocked(null);
7666 }
7667
7668 public void moveTaskToBack(int task) {
7669 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7670 "moveTaskToBack()");
7671
7672 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007673 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7674 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7675 Binder.getCallingUid(), "Task to back")) {
7676 return;
7677 }
7678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007679 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007680 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007681 Binder.restoreCallingIdentity(origId);
7682 }
7683 }
7684
7685 /**
7686 * Moves an activity, and all of the other activities within the same task, to the bottom
7687 * of the history stack. The activity's order within the task is unchanged.
7688 *
7689 * @param token A reference to the activity we wish to move
7690 * @param nonRoot If false then this only works if the activity is the root
7691 * of a task; if true it will work for any activity in a task.
7692 * @return Returns true if the move completed, false if not.
7693 */
7694 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7695 synchronized(this) {
7696 final long origId = Binder.clearCallingIdentity();
7697 int taskId = getTaskForActivityLocked(token, !nonRoot);
7698 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007699 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007700 }
7701 Binder.restoreCallingIdentity(origId);
7702 }
7703 return false;
7704 }
7705
7706 /**
7707 * Worker method for rearranging history stack. Implements the function of moving all
7708 * activities for a specific task (gathering them if disjoint) into a single group at the
7709 * bottom of the stack.
7710 *
7711 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7712 * to premeptively cancel the move.
7713 *
7714 * @param task The taskId to collect and move to the bottom.
7715 * @return Returns true if the move completed, false if not.
7716 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007717 private final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007718 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007719
7720 // If we have a watcher, preflight the move before committing to it. First check
7721 // for *other* available tasks, but if none are available, then try again allowing the
7722 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007723 if (mController != null) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007724 ActivityRecord next = topRunningActivityLocked(null, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007725 if (next == null) {
7726 next = topRunningActivityLocked(null, 0);
7727 }
7728 if (next != null) {
7729 // ask watcher if this is allowed
7730 boolean moveOK = true;
7731 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007732 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007733 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007734 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007735 }
7736 if (!moveOK) {
7737 return false;
7738 }
7739 }
7740 }
7741
7742 ArrayList moved = new ArrayList();
7743
Joe Onorato8a9b2202010-02-26 18:56:32 -08007744 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007745 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007746
7747 final int N = mHistory.size();
7748 int bottom = 0;
7749 int pos = 0;
7750
7751 // Shift all activities with this task down to the bottom
7752 // of the stack, keeping them in the same internal order.
7753 while (pos < N) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007754 ActivityRecord r = (ActivityRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007755 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007756 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7757 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007758 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007759 mHistory.remove(pos);
7760 mHistory.add(bottom, r);
7761 moved.add(r);
7762 bottom++;
7763 }
7764 pos++;
7765 }
7766
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007767 if (reason != null &&
7768 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7769 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007770 ActivityRecord r = topRunningActivityLocked(null);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007771 if (r != null) {
7772 mNoAnimActivities.add(r);
7773 }
7774 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007775 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007777 mWindowManager.moveAppTokensToBottom(moved);
7778 if (VALIDATE_TOKENS) {
7779 mWindowManager.validateAppTokens(mHistory);
7780 }
7781
Josh Bartel7f208742010-02-25 11:01:44 -06007782 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007783 return true;
7784 }
7785
7786 public void moveTaskBackwards(int task) {
7787 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7788 "moveTaskBackwards()");
7789
7790 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007791 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7792 Binder.getCallingUid(), "Task backwards")) {
7793 return;
7794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007795 final long origId = Binder.clearCallingIdentity();
7796 moveTaskBackwardsLocked(task);
7797 Binder.restoreCallingIdentity(origId);
7798 }
7799 }
7800
7801 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007802 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007803 }
7804
7805 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7806 synchronized(this) {
7807 return getTaskForActivityLocked(token, onlyRoot);
7808 }
7809 }
7810
7811 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7812 final int N = mHistory.size();
7813 TaskRecord lastTask = null;
7814 for (int i=0; i<N; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007815 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007816 if (r == token) {
7817 if (!onlyRoot || lastTask != r.task) {
7818 return r.task.taskId;
7819 }
7820 return -1;
7821 }
7822 lastTask = r.task;
7823 }
7824
7825 return -1;
7826 }
7827
7828 /**
7829 * Returns the top activity in any existing task matching the given
7830 * Intent. Returns null if no such task is found.
7831 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007832 private ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007833 ComponentName cls = intent.getComponent();
7834 if (info.targetActivity != null) {
7835 cls = new ComponentName(info.packageName, info.targetActivity);
7836 }
7837
7838 TaskRecord cp = null;
7839
7840 final int N = mHistory.size();
7841 for (int i=(N-1); i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007842 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007843 if (!r.finishing && r.task != cp
7844 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7845 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007846 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007847 // + "/aff=" + r.task.affinity + " to new cls="
7848 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7849 if (r.task.affinity != null) {
7850 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007851 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007852 return r;
7853 }
7854 } else if (r.task.intent != null
7855 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007856 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007857 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007858 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007859 return r;
7860 } else if (r.task.affinityIntent != null
7861 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007862 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007864 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007865 return r;
7866 }
7867 }
7868 }
7869
7870 return null;
7871 }
7872
7873 /**
7874 * Returns the first activity (starting from the top of the stack) that
7875 * is the same as the given activity. Returns null if no such activity
7876 * is found.
7877 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007878 private ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007879 ComponentName cls = intent.getComponent();
7880 if (info.targetActivity != null) {
7881 cls = new ComponentName(info.packageName, info.targetActivity);
7882 }
7883
7884 final int N = mHistory.size();
7885 for (int i=(N-1); i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007886 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007887 if (!r.finishing) {
7888 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007889 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007891 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 return r;
7893 }
7894 }
7895 }
7896
7897 return null;
7898 }
7899
7900 public void finishOtherInstances(IBinder token, ComponentName className) {
7901 synchronized(this) {
7902 final long origId = Binder.clearCallingIdentity();
7903
7904 int N = mHistory.size();
7905 TaskRecord lastTask = null;
7906 for (int i=0; i<N; i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007907 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 if (r.realActivity.equals(className)
7909 && r != token && lastTask != r.task) {
7910 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7911 null, "others")) {
7912 i--;
7913 N--;
7914 }
7915 }
7916 lastTask = r.task;
7917 }
7918
7919 Binder.restoreCallingIdentity(origId);
7920 }
7921 }
7922
7923 // =========================================================
7924 // THUMBNAILS
7925 // =========================================================
7926
7927 public void reportThumbnail(IBinder token,
7928 Bitmap thumbnail, CharSequence description) {
7929 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7930 final long origId = Binder.clearCallingIdentity();
7931 sendPendingThumbnail(null, token, thumbnail, description, true);
7932 Binder.restoreCallingIdentity(origId);
7933 }
7934
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007935 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936 Bitmap thumbnail, CharSequence description, boolean always) {
7937 TaskRecord task = null;
7938 ArrayList receivers = null;
7939
7940 //System.out.println("Send pending thumbnail: " + r);
7941
7942 synchronized(this) {
7943 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007944 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945 if (index < 0) {
7946 return;
7947 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007948 r = (ActivityRecord)mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007949 }
7950 if (thumbnail == null) {
7951 thumbnail = r.thumbnail;
7952 description = r.description;
7953 }
7954 if (thumbnail == null && !always) {
7955 // If there is no thumbnail, and this entry is not actually
7956 // going away, then abort for now and pick up the next
7957 // thumbnail we get.
7958 return;
7959 }
7960 task = r.task;
7961
7962 int N = mPendingThumbnails.size();
7963 int i=0;
7964 while (i<N) {
7965 PendingThumbnailsRecord pr =
7966 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7967 //System.out.println("Looking in " + pr.pendingRecords);
7968 if (pr.pendingRecords.remove(r)) {
7969 if (receivers == null) {
7970 receivers = new ArrayList();
7971 }
7972 receivers.add(pr);
7973 if (pr.pendingRecords.size() == 0) {
7974 pr.finished = true;
7975 mPendingThumbnails.remove(i);
7976 N--;
7977 continue;
7978 }
7979 }
7980 i++;
7981 }
7982 }
7983
7984 if (receivers != null) {
7985 final int N = receivers.size();
7986 for (int i=0; i<N; i++) {
7987 try {
7988 PendingThumbnailsRecord pr =
7989 (PendingThumbnailsRecord)receivers.get(i);
7990 pr.receiver.newThumbnail(
7991 task != null ? task.taskId : -1, thumbnail, description);
7992 if (pr.finished) {
7993 pr.receiver.finished();
7994 }
7995 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007996 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007997 }
7998 }
7999 }
8000 }
8001
8002 // =========================================================
8003 // CONTENT PROVIDERS
8004 // =========================================================
8005
8006 private final List generateApplicationProvidersLocked(ProcessRecord app) {
8007 List providers = null;
8008 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008009 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008010 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008011 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008012 } catch (RemoteException ex) {
8013 }
8014 if (providers != null) {
8015 final int N = providers.size();
8016 for (int i=0; i<N; i++) {
8017 ProviderInfo cpi =
8018 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008019 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008020 if (cpr == null) {
8021 cpr = new ContentProviderRecord(cpi, app.info);
8022 mProvidersByClass.put(cpi.name, cpr);
8023 }
8024 app.pubProviders.put(cpi.name, cpr);
8025 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008026 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008027 }
8028 }
8029 return providers;
8030 }
8031
8032 private final String checkContentProviderPermissionLocked(
8033 ProviderInfo cpi, ProcessRecord r, int mode) {
8034 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
8035 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
8036 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
8037 cpi.exported ? -1 : cpi.applicationInfo.uid)
8038 == PackageManager.PERMISSION_GRANTED
8039 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8040 return null;
8041 }
8042 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
8043 cpi.exported ? -1 : cpi.applicationInfo.uid)
8044 == PackageManager.PERMISSION_GRANTED) {
8045 return null;
8046 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07008047
8048 PathPermission[] pps = cpi.pathPermissions;
8049 if (pps != null) {
8050 int i = pps.length;
8051 while (i > 0) {
8052 i--;
8053 PathPermission pp = pps[i];
8054 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
8055 cpi.exported ? -1 : cpi.applicationInfo.uid)
8056 == PackageManager.PERMISSION_GRANTED
8057 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8058 return null;
8059 }
8060 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
8061 cpi.exported ? -1 : cpi.applicationInfo.uid)
8062 == PackageManager.PERMISSION_GRANTED) {
8063 return null;
8064 }
8065 }
8066 }
8067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008068 String msg = "Permission Denial: opening provider " + cpi.name
8069 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
8070 + ", uid=" + callingUid + ") requires "
8071 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008072 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008073 return msg;
8074 }
8075
8076 private final ContentProviderHolder getContentProviderImpl(
8077 IApplicationThread caller, String name) {
8078 ContentProviderRecord cpr;
8079 ProviderInfo cpi = null;
8080
8081 synchronized(this) {
8082 ProcessRecord r = null;
8083 if (caller != null) {
8084 r = getRecordForAppLocked(caller);
8085 if (r == null) {
8086 throw new SecurityException(
8087 "Unable to find app for caller " + caller
8088 + " (pid=" + Binder.getCallingPid()
8089 + ") when getting content provider " + name);
8090 }
8091 }
8092
8093 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07008094 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008095 if (cpr != null) {
8096 cpi = cpr.info;
8097 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8098 return new ContentProviderHolder(cpi,
8099 cpi.readPermission != null
8100 ? cpi.readPermission : cpi.writePermission);
8101 }
8102
8103 if (r != null && cpr.canRunHere(r)) {
8104 // This provider has been published or is in the process
8105 // of being published... but it is also allowed to run
8106 // in the caller's process, so don't make a connection
8107 // and just let the caller instantiate its own instance.
8108 if (cpr.provider != null) {
8109 // don't give caller the provider object, it needs
8110 // to make its own.
8111 cpr = new ContentProviderRecord(cpr);
8112 }
8113 return cpr;
8114 }
8115
8116 final long origId = Binder.clearCallingIdentity();
8117
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008118 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008119 // return it right away.
8120 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008121 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008122 "Adding provider requested by "
8123 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008124 + cpr.info.processName);
8125 Integer cnt = r.conProviders.get(cpr);
8126 if (cnt == null) {
8127 r.conProviders.put(cpr, new Integer(1));
8128 } else {
8129 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008131 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008132 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
8133 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07008134 // make sure to count it as being accessed and thus
8135 // back up on the LRU list. This is good because
8136 // content providers are often expensive to start.
8137 updateLruProcessLocked(cpr.app, false, true);
8138 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07008139 } else {
8140 cpr.externals++;
8141 }
8142
8143 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008144 updateOomAdjLocked(cpr.app);
8145 }
8146
8147 Binder.restoreCallingIdentity(origId);
8148
8149 } else {
8150 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008151 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008152 resolveContentProvider(name,
8153 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008154 } catch (RemoteException ex) {
8155 }
8156 if (cpi == null) {
8157 return null;
8158 }
8159
8160 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8161 return new ContentProviderHolder(cpi,
8162 cpi.readPermission != null
8163 ? cpi.readPermission : cpi.writePermission);
8164 }
8165
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008166 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
8167 && !cpi.processName.equals("system")) {
8168 // If this content provider does not run in the system
8169 // process, and the system is not yet ready to run other
8170 // processes, then fail fast instead of hanging.
8171 throw new IllegalArgumentException(
8172 "Attempt to launch content provider before system ready");
8173 }
8174
Dianne Hackborn860755f2010-06-03 18:47:52 -07008175 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008176 final boolean firstClass = cpr == null;
8177 if (firstClass) {
8178 try {
8179 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008180 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008181 getApplicationInfo(
8182 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008183 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008184 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008185 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008186 + cpi.name);
8187 return null;
8188 }
8189 cpr = new ContentProviderRecord(cpi, ai);
8190 } catch (RemoteException ex) {
8191 // pm is in same process, this will never happen.
8192 }
8193 }
8194
8195 if (r != null && cpr.canRunHere(r)) {
8196 // If this is a multiprocess provider, then just return its
8197 // info and allow the caller to instantiate it. Only do
8198 // this if the provider is the same user as the caller's
8199 // process, or can run as root (so can be in any process).
8200 return cpr;
8201 }
8202
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008203 if (DEBUG_PROVIDER) {
8204 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08008205 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008206 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008207 }
8208
8209 // This is single process, and our app is now connecting to it.
8210 // See if we are already in the process of launching this
8211 // provider.
8212 final int N = mLaunchingProviders.size();
8213 int i;
8214 for (i=0; i<N; i++) {
8215 if (mLaunchingProviders.get(i) == cpr) {
8216 break;
8217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008218 }
8219
8220 // If the provider is not already being launched, then get it
8221 // started.
8222 if (i >= N) {
8223 final long origId = Binder.clearCallingIdentity();
8224 ProcessRecord proc = startProcessLocked(cpi.processName,
8225 cpr.appInfo, false, 0, "content provider",
8226 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008227 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008228 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008229 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008230 + cpi.applicationInfo.packageName + "/"
8231 + cpi.applicationInfo.uid + " for provider "
8232 + name + ": process is bad");
8233 return null;
8234 }
8235 cpr.launchingApp = proc;
8236 mLaunchingProviders.add(cpr);
8237 Binder.restoreCallingIdentity(origId);
8238 }
8239
8240 // Make sure the provider is published (the same provider class
8241 // may be published under multiple names).
8242 if (firstClass) {
8243 mProvidersByClass.put(cpi.name, cpr);
8244 }
8245 mProvidersByName.put(name, cpr);
8246
8247 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008248 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008249 "Adding provider requested by "
8250 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008251 + cpr.info.processName);
8252 Integer cnt = r.conProviders.get(cpr);
8253 if (cnt == null) {
8254 r.conProviders.put(cpr, new Integer(1));
8255 } else {
8256 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008258 cpr.clients.add(r);
8259 } else {
8260 cpr.externals++;
8261 }
8262 }
8263 }
8264
8265 // Wait for the provider to be published...
8266 synchronized (cpr) {
8267 while (cpr.provider == null) {
8268 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008269 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008270 + cpi.applicationInfo.packageName + "/"
8271 + cpi.applicationInfo.uid + " for provider "
8272 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008273 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008274 cpi.applicationInfo.packageName,
8275 cpi.applicationInfo.uid, name);
8276 return null;
8277 }
8278 try {
8279 cpr.wait();
8280 } catch (InterruptedException ex) {
8281 }
8282 }
8283 }
8284 return cpr;
8285 }
8286
8287 public final ContentProviderHolder getContentProvider(
8288 IApplicationThread caller, String name) {
8289 if (caller == null) {
8290 String msg = "null IApplicationThread when getting content provider "
8291 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008292 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008293 throw new SecurityException(msg);
8294 }
8295
8296 return getContentProviderImpl(caller, name);
8297 }
8298
8299 private ContentProviderHolder getContentProviderExternal(String name) {
8300 return getContentProviderImpl(null, name);
8301 }
8302
8303 /**
8304 * Drop a content provider from a ProcessRecord's bookkeeping
8305 * @param cpr
8306 */
8307 public void removeContentProvider(IApplicationThread caller, String name) {
8308 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008309 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008310 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008311 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008312 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008313 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008314 return;
8315 }
8316 final ProcessRecord r = getRecordForAppLocked(caller);
8317 if (r == null) {
8318 throw new SecurityException(
8319 "Unable to find app for caller " + caller +
8320 " when removing content provider " + name);
8321 }
8322 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008323 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008324 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008325 + r.info.processName + " from process "
8326 + localCpr.appInfo.processName);
8327 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008329 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008330 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008331 return;
8332 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008333 Integer cnt = r.conProviders.get(localCpr);
8334 if (cnt == null || cnt.intValue() <= 1) {
8335 localCpr.clients.remove(r);
8336 r.conProviders.remove(localCpr);
8337 } else {
8338 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008340 }
8341 updateOomAdjLocked();
8342 }
8343 }
8344
8345 private void removeContentProviderExternal(String name) {
8346 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008347 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008348 if(cpr == null) {
8349 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008350 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008351 return;
8352 }
8353
8354 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008355 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008356 localCpr.externals--;
8357 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008358 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008359 }
8360 updateOomAdjLocked();
8361 }
8362 }
8363
8364 public final void publishContentProviders(IApplicationThread caller,
8365 List<ContentProviderHolder> providers) {
8366 if (providers == null) {
8367 return;
8368 }
8369
8370 synchronized(this) {
8371 final ProcessRecord r = getRecordForAppLocked(caller);
8372 if (r == null) {
8373 throw new SecurityException(
8374 "Unable to find app for caller " + caller
8375 + " (pid=" + Binder.getCallingPid()
8376 + ") when publishing content providers");
8377 }
8378
8379 final long origId = Binder.clearCallingIdentity();
8380
8381 final int N = providers.size();
8382 for (int i=0; i<N; i++) {
8383 ContentProviderHolder src = providers.get(i);
8384 if (src == null || src.info == null || src.provider == null) {
8385 continue;
8386 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07008387 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008388 if (dst != null) {
8389 mProvidersByClass.put(dst.info.name, dst);
8390 String names[] = dst.info.authority.split(";");
8391 for (int j = 0; j < names.length; j++) {
8392 mProvidersByName.put(names[j], dst);
8393 }
8394
8395 int NL = mLaunchingProviders.size();
8396 int j;
8397 for (j=0; j<NL; j++) {
8398 if (mLaunchingProviders.get(j) == dst) {
8399 mLaunchingProviders.remove(j);
8400 j--;
8401 NL--;
8402 }
8403 }
8404 synchronized (dst) {
8405 dst.provider = src.provider;
8406 dst.app = r;
8407 dst.notifyAll();
8408 }
8409 updateOomAdjLocked(r);
8410 }
8411 }
8412
8413 Binder.restoreCallingIdentity(origId);
8414 }
8415 }
8416
8417 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008418 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008419 synchronized (mSelf) {
8420 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8421 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008422 if (providers != null) {
8423 for (int i=providers.size()-1; i>=0; i--) {
8424 ProviderInfo pi = (ProviderInfo)providers.get(i);
8425 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8426 Slog.w(TAG, "Not installing system proc provider " + pi.name
8427 + ": not system .apk");
8428 providers.remove(i);
8429 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008430 }
8431 }
8432 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008433 if (providers != null) {
8434 mSystemThread.installSystemProviders(providers);
8435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 }
8437
8438 // =========================================================
8439 // GLOBAL MANAGEMENT
8440 // =========================================================
8441
8442 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8443 ApplicationInfo info, String customProcess) {
8444 String proc = customProcess != null ? customProcess : info.processName;
8445 BatteryStatsImpl.Uid.Proc ps = null;
8446 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8447 synchronized (stats) {
8448 ps = stats.getProcessStatsLocked(info.uid, proc);
8449 }
8450 return new ProcessRecord(ps, thread, info, proc);
8451 }
8452
8453 final ProcessRecord addAppLocked(ApplicationInfo info) {
8454 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8455
8456 if (app == null) {
8457 app = newProcessRecordLocked(null, info, null);
8458 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008459 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008460 }
8461
8462 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8463 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8464 app.persistent = true;
8465 app.maxAdj = CORE_SERVER_ADJ;
8466 }
8467 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8468 mPersistentStartingProcesses.add(app);
8469 startProcessLocked(app, "added application", app.processName);
8470 }
8471
8472 return app;
8473 }
8474
8475 public void unhandledBack() {
8476 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8477 "unhandledBack()");
8478
8479 synchronized(this) {
8480 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008481 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008482 TAG, "Performing unhandledBack(): stack size = " + count);
8483 if (count > 1) {
8484 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008485 finishActivityLocked((ActivityRecord)mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8487 Binder.restoreCallingIdentity(origId);
8488 }
8489 }
8490 }
8491
8492 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8493 String name = uri.getAuthority();
8494 ContentProviderHolder cph = getContentProviderExternal(name);
8495 ParcelFileDescriptor pfd = null;
8496 if (cph != null) {
8497 // We record the binder invoker's uid in thread-local storage before
8498 // going to the content provider to open the file. Later, in the code
8499 // that handles all permissions checks, we look for this uid and use
8500 // that rather than the Activity Manager's own uid. The effect is that
8501 // we do the check against the caller's permissions even though it looks
8502 // to the content provider like the Activity Manager itself is making
8503 // the request.
8504 sCallerIdentity.set(new Identity(
8505 Binder.getCallingPid(), Binder.getCallingUid()));
8506 try {
8507 pfd = cph.provider.openFile(uri, "r");
8508 } catch (FileNotFoundException e) {
8509 // do nothing; pfd will be returned null
8510 } finally {
8511 // Ensure that whatever happens, we clean up the identity state
8512 sCallerIdentity.remove();
8513 }
8514
8515 // We've got the fd now, so we're done with the provider.
8516 removeContentProviderExternal(name);
8517 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008518 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008519 }
8520 return pfd;
8521 }
8522
8523 public void goingToSleep() {
8524 synchronized(this) {
8525 mSleeping = true;
8526 mWindowManager.setEventDispatching(false);
8527
8528 if (mResumedActivity != null) {
8529 pauseIfSleepingLocked();
8530 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008531 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008532 }
8533 }
8534 }
8535
Dianne Hackborn55280a92009-05-07 15:53:46 -07008536 public boolean shutdown(int timeout) {
8537 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8538 != PackageManager.PERMISSION_GRANTED) {
8539 throw new SecurityException("Requires permission "
8540 + android.Manifest.permission.SHUTDOWN);
8541 }
8542
8543 boolean timedout = false;
8544
8545 synchronized(this) {
8546 mShuttingDown = true;
8547 mWindowManager.setEventDispatching(false);
8548
8549 if (mResumedActivity != null) {
8550 pauseIfSleepingLocked();
8551 final long endTime = System.currentTimeMillis() + timeout;
8552 while (mResumedActivity != null || mPausingActivity != null) {
8553 long delay = endTime - System.currentTimeMillis();
8554 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008555 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008556 timedout = true;
8557 break;
8558 }
8559 try {
8560 this.wait();
8561 } catch (InterruptedException e) {
8562 }
8563 }
8564 }
8565 }
8566
8567 mUsageStatsService.shutdown();
8568 mBatteryStatsService.shutdown();
8569
8570 return timedout;
8571 }
8572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008573 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008574 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008575 if (!mGoingToSleep.isHeld()) {
8576 mGoingToSleep.acquire();
8577 if (mLaunchingActivity.isHeld()) {
8578 mLaunchingActivity.release();
8579 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8580 }
8581 }
8582
8583 // If we are not currently pausing an activity, get the current
8584 // one to pause. If we are pausing one, we will just let that stuff
8585 // run and release the wake lock when all done.
8586 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008587 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8588 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008589 startPausingLocked(false, true);
8590 }
8591 }
8592 }
8593
8594 public void wakingUp() {
8595 synchronized(this) {
8596 if (mGoingToSleep.isHeld()) {
8597 mGoingToSleep.release();
8598 }
8599 mWindowManager.setEventDispatching(true);
8600 mSleeping = false;
8601 resumeTopActivityLocked(null);
8602 }
8603 }
8604
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008605 public void stopAppSwitches() {
8606 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8607 != PackageManager.PERMISSION_GRANTED) {
8608 throw new SecurityException("Requires permission "
8609 + android.Manifest.permission.STOP_APP_SWITCHES);
8610 }
8611
8612 synchronized(this) {
8613 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8614 + APP_SWITCH_DELAY_TIME;
8615 mDidAppSwitch = false;
8616 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8617 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8618 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8619 }
8620 }
8621
8622 public void resumeAppSwitches() {
8623 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8624 != PackageManager.PERMISSION_GRANTED) {
8625 throw new SecurityException("Requires permission "
8626 + android.Manifest.permission.STOP_APP_SWITCHES);
8627 }
8628
8629 synchronized(this) {
8630 // Note that we don't execute any pending app switches... we will
8631 // let those wait until either the timeout, or the next start
8632 // activity request.
8633 mAppSwitchesAllowedTime = 0;
8634 }
8635 }
8636
8637 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8638 String name) {
8639 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8640 return true;
8641 }
8642
8643 final int perm = checkComponentPermission(
8644 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8645 callingUid, -1);
8646 if (perm == PackageManager.PERMISSION_GRANTED) {
8647 return true;
8648 }
8649
Joe Onorato8a9b2202010-02-26 18:56:32 -08008650 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008651 return false;
8652 }
8653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008654 public void setDebugApp(String packageName, boolean waitForDebugger,
8655 boolean persistent) {
8656 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8657 "setDebugApp()");
8658
8659 // Note that this is not really thread safe if there are multiple
8660 // callers into it at the same time, but that's not a situation we
8661 // care about.
8662 if (persistent) {
8663 final ContentResolver resolver = mContext.getContentResolver();
8664 Settings.System.putString(
8665 resolver, Settings.System.DEBUG_APP,
8666 packageName);
8667 Settings.System.putInt(
8668 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8669 waitForDebugger ? 1 : 0);
8670 }
8671
8672 synchronized (this) {
8673 if (!persistent) {
8674 mOrigDebugApp = mDebugApp;
8675 mOrigWaitForDebugger = mWaitForDebugger;
8676 }
8677 mDebugApp = packageName;
8678 mWaitForDebugger = waitForDebugger;
8679 mDebugTransient = !persistent;
8680 if (packageName != null) {
8681 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008682 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008683 Binder.restoreCallingIdentity(origId);
8684 }
8685 }
8686 }
8687
8688 public void setAlwaysFinish(boolean enabled) {
8689 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8690 "setAlwaysFinish()");
8691
8692 Settings.System.putInt(
8693 mContext.getContentResolver(),
8694 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8695
8696 synchronized (this) {
8697 mAlwaysFinishActivities = enabled;
8698 }
8699 }
8700
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008701 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008702 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008703 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008704 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008705 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008706 }
8707 }
8708
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008709 public boolean isUserAMonkey() {
8710 // For now the fact that there is a controller implies
8711 // we have a monkey.
8712 synchronized (this) {
8713 return mController != null;
8714 }
8715 }
8716
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008717 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008718 synchronized (this) {
8719 mWatchers.register(watcher);
8720 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008721 }
8722
8723 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008724 synchronized (this) {
8725 mWatchers.unregister(watcher);
8726 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008727 }
8728
Daniel Sandler69a48172010-06-23 16:29:36 -04008729 public void setImmersive(IBinder token, boolean immersive) {
8730 synchronized(this) {
8731 int index = (token != null) ? indexOfTokenLocked(token) : -1;
8732 if (index < 0) {
8733 throw new IllegalArgumentException();
8734 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008735 ActivityRecord r = (ActivityRecord)mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04008736 r.immersive = immersive;
8737 }
8738 }
8739
8740 public boolean isImmersive(IBinder token) {
8741 synchronized (this) {
8742 int index = (token != null) ? indexOfTokenLocked(token) : -1;
8743 if (index < 0) {
8744 throw new IllegalArgumentException();
8745 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008746 ActivityRecord r = (ActivityRecord)mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04008747 return r.immersive;
8748 }
8749 }
8750
8751 public boolean isTopActivityImmersive() {
8752 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008753 ActivityRecord r = topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04008754 return (r != null) ? r.immersive : false;
8755 }
8756 }
8757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008758 public final void enterSafeMode() {
8759 synchronized(this) {
8760 // It only makes sense to do this before the system is ready
8761 // and started launching other packages.
8762 if (!mSystemReady) {
8763 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008764 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008765 } catch (RemoteException e) {
8766 }
8767
8768 View v = LayoutInflater.from(mContext).inflate(
8769 com.android.internal.R.layout.safe_mode, null);
8770 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8771 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8772 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8773 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8774 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8775 lp.format = v.getBackground().getOpacity();
8776 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8777 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8778 ((WindowManager)mContext.getSystemService(
8779 Context.WINDOW_SERVICE)).addView(v, lp);
8780 }
8781 }
8782 }
8783
8784 public void noteWakeupAlarm(IIntentSender sender) {
8785 if (!(sender instanceof PendingIntentRecord)) {
8786 return;
8787 }
8788 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8789 synchronized (stats) {
8790 if (mBatteryStatsService.isOnBattery()) {
8791 mBatteryStatsService.enforceCallingPermission();
8792 PendingIntentRecord rec = (PendingIntentRecord)sender;
8793 int MY_UID = Binder.getCallingUid();
8794 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8795 BatteryStatsImpl.Uid.Pkg pkg =
8796 stats.getPackageStatsLocked(uid, rec.key.packageName);
8797 pkg.incWakeupsLocked();
8798 }
8799 }
8800 }
8801
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008802 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008803 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008804 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008805 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008806 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807 // XXX Note: don't acquire main activity lock here, because the window
8808 // manager calls in with its locks held.
8809
8810 boolean killed = false;
8811 synchronized (mPidsSelfLocked) {
8812 int[] types = new int[pids.length];
8813 int worstType = 0;
8814 for (int i=0; i<pids.length; i++) {
8815 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8816 if (proc != null) {
8817 int type = proc.setAdj;
8818 types[i] = type;
8819 if (type > worstType) {
8820 worstType = type;
8821 }
8822 }
8823 }
8824
8825 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8826 // then constrain it so we will kill all hidden procs.
8827 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8828 worstType = HIDDEN_APP_MIN_ADJ;
8829 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008830 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008831 for (int i=0; i<pids.length; i++) {
8832 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8833 if (proc == null) {
8834 continue;
8835 }
8836 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008837 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008838 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008839 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8840 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008841 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008842 proc.killedBackground = true;
8843 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008844 }
8845 }
8846 }
8847 return killed;
8848 }
8849
8850 public void reportPss(IApplicationThread caller, int pss) {
8851 Watchdog.PssRequestor req;
8852 String name;
8853 ProcessRecord callerApp;
8854 synchronized (this) {
8855 if (caller == null) {
8856 return;
8857 }
8858 callerApp = getRecordForAppLocked(caller);
8859 if (callerApp == null) {
8860 return;
8861 }
8862 callerApp.lastPss = pss;
8863 req = callerApp;
8864 name = callerApp.processName;
8865 }
8866 Watchdog.getInstance().reportPss(req, name, pss);
8867 if (!callerApp.persistent) {
8868 removeRequestedPss(callerApp);
8869 }
8870 }
8871
8872 public void requestPss(Runnable completeCallback) {
8873 ArrayList<ProcessRecord> procs;
8874 synchronized (this) {
8875 mRequestPssCallback = completeCallback;
8876 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008877 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8878 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008879 if (!proc.persistent) {
8880 mRequestPssList.add(proc);
8881 }
8882 }
8883 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8884 }
8885
8886 int oldPri = Process.getThreadPriority(Process.myTid());
8887 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8888 for (int i=procs.size()-1; i>=0; i--) {
8889 ProcessRecord proc = procs.get(i);
8890 proc.lastPss = 0;
8891 proc.requestPss();
8892 }
8893 Process.setThreadPriority(oldPri);
8894 }
8895
8896 void removeRequestedPss(ProcessRecord proc) {
8897 Runnable callback = null;
8898 synchronized (this) {
8899 if (mRequestPssList.remove(proc)) {
8900 if (mRequestPssList.size() == 0) {
8901 callback = mRequestPssCallback;
8902 mRequestPssCallback = null;
8903 }
8904 }
8905 }
8906
8907 if (callback != null) {
8908 callback.run();
8909 }
8910 }
8911
8912 public void collectPss(Watchdog.PssStats stats) {
8913 stats.mEmptyPss = 0;
8914 stats.mEmptyCount = 0;
8915 stats.mBackgroundPss = 0;
8916 stats.mBackgroundCount = 0;
8917 stats.mServicePss = 0;
8918 stats.mServiceCount = 0;
8919 stats.mVisiblePss = 0;
8920 stats.mVisibleCount = 0;
8921 stats.mForegroundPss = 0;
8922 stats.mForegroundCount = 0;
8923 stats.mNoPssCount = 0;
8924 synchronized (this) {
8925 int i;
8926 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8927 ? mProcDeaths.length : stats.mProcDeaths.length;
8928 int aggr = 0;
8929 for (i=0; i<NPD; i++) {
8930 aggr += mProcDeaths[i];
8931 stats.mProcDeaths[i] = aggr;
8932 }
8933 while (i<stats.mProcDeaths.length) {
8934 stats.mProcDeaths[i] = 0;
8935 i++;
8936 }
8937
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008938 for (i=mLruProcesses.size()-1; i>=0; i--) {
8939 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008940 if (proc.persistent) {
8941 continue;
8942 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008943 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008944 if (proc.lastPss == 0) {
8945 stats.mNoPssCount++;
8946 continue;
8947 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008948 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8949 if (proc.empty) {
8950 stats.mEmptyPss += proc.lastPss;
8951 stats.mEmptyCount++;
8952 } else {
8953 stats.mBackgroundPss += proc.lastPss;
8954 stats.mBackgroundCount++;
8955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008956 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8957 stats.mVisiblePss += proc.lastPss;
8958 stats.mVisibleCount++;
8959 } else {
8960 stats.mForegroundPss += proc.lastPss;
8961 stats.mForegroundCount++;
8962 }
8963 }
8964 }
8965 }
8966
8967 public final void startRunning(String pkg, String cls, String action,
8968 String data) {
8969 synchronized(this) {
8970 if (mStartRunning) {
8971 return;
8972 }
8973 mStartRunning = true;
8974 mTopComponent = pkg != null && cls != null
8975 ? new ComponentName(pkg, cls) : null;
8976 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8977 mTopData = data;
8978 if (!mSystemReady) {
8979 return;
8980 }
8981 }
8982
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008983 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984 }
8985
8986 private void retrieveSettings() {
8987 final ContentResolver resolver = mContext.getContentResolver();
8988 String debugApp = Settings.System.getString(
8989 resolver, Settings.System.DEBUG_APP);
8990 boolean waitForDebugger = Settings.System.getInt(
8991 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8992 boolean alwaysFinishActivities = Settings.System.getInt(
8993 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8994
8995 Configuration configuration = new Configuration();
8996 Settings.System.getConfiguration(resolver, configuration);
8997
8998 synchronized (this) {
8999 mDebugApp = mOrigDebugApp = debugApp;
9000 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
9001 mAlwaysFinishActivities = alwaysFinishActivities;
9002 // This happens before any activities are started, so we can
9003 // change mConfiguration in-place.
9004 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009005 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009006 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009007 }
9008 }
9009
9010 public boolean testIsSystemReady() {
9011 // no need to synchronize(this) just to read & return the value
9012 return mSystemReady;
9013 }
9014
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009015 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009016 // In the simulator, startRunning will never have been called, which
9017 // normally sets a few crucial variables. Do it here instead.
9018 if (!Process.supportsProcesses()) {
9019 mStartRunning = true;
9020 mTopAction = Intent.ACTION_MAIN;
9021 }
9022
9023 synchronized(this) {
9024 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009025 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009026 return;
9027 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009028
9029 // Check to see if there are any update receivers to run.
9030 if (!mDidUpdate) {
9031 if (mWaitingUpdate) {
9032 return;
9033 }
9034 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
9035 List<ResolveInfo> ris = null;
9036 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009037 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009038 intent, null, 0);
9039 } catch (RemoteException e) {
9040 }
9041 if (ris != null) {
9042 for (int i=ris.size()-1; i>=0; i--) {
9043 if ((ris.get(i).activityInfo.applicationInfo.flags
9044 &ApplicationInfo.FLAG_SYSTEM) == 0) {
9045 ris.remove(i);
9046 }
9047 }
9048 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
9049 for (int i=0; i<ris.size(); i++) {
9050 ActivityInfo ai = ris.get(i).activityInfo;
9051 intent.setComponent(new ComponentName(ai.packageName, ai.name));
9052 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08009053 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009054 finisher = new IIntentReceiver.Stub() {
9055 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07009056 String data, Bundle extras, boolean ordered,
9057 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009058 throws RemoteException {
9059 synchronized (ActivityManagerService.this) {
9060 mDidUpdate = true;
9061 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009062 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009063 }
9064 };
9065 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009066 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009067 broadcastIntentLocked(null, null, intent, null, finisher,
9068 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08009069 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009070 mWaitingUpdate = true;
9071 }
9072 }
9073 }
9074 if (mWaitingUpdate) {
9075 return;
9076 }
9077 mDidUpdate = true;
9078 }
9079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009080 mSystemReady = true;
9081 if (!mStartRunning) {
9082 return;
9083 }
9084 }
9085
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009086 ArrayList<ProcessRecord> procsToKill = null;
9087 synchronized(mPidsSelfLocked) {
9088 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
9089 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
9090 if (!isAllowedWhileBooting(proc.info)){
9091 if (procsToKill == null) {
9092 procsToKill = new ArrayList<ProcessRecord>();
9093 }
9094 procsToKill.add(proc);
9095 }
9096 }
9097 }
9098
9099 if (procsToKill != null) {
9100 synchronized(this) {
9101 for (int i=procsToKill.size()-1; i>=0; i--) {
9102 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009103 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009104 removeProcessLocked(proc, true);
9105 }
9106 }
9107 }
9108
Joe Onorato8a9b2202010-02-26 18:56:32 -08009109 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009110 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009111 SystemClock.uptimeMillis());
9112
9113 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009114 // Make sure we have no pre-ready processes sitting around.
9115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009116 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
9117 ResolveInfo ri = mContext.getPackageManager()
9118 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07009119 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 CharSequence errorMsg = null;
9121 if (ri != null) {
9122 ActivityInfo ai = ri.activityInfo;
9123 ApplicationInfo app = ai.applicationInfo;
9124 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
9125 mTopAction = Intent.ACTION_FACTORY_TEST;
9126 mTopData = null;
9127 mTopComponent = new ComponentName(app.packageName,
9128 ai.name);
9129 } else {
9130 errorMsg = mContext.getResources().getText(
9131 com.android.internal.R.string.factorytest_not_system);
9132 }
9133 } else {
9134 errorMsg = mContext.getResources().getText(
9135 com.android.internal.R.string.factorytest_no_action);
9136 }
9137 if (errorMsg != null) {
9138 mTopAction = null;
9139 mTopData = null;
9140 mTopComponent = null;
9141 Message msg = Message.obtain();
9142 msg.what = SHOW_FACTORY_ERROR_MSG;
9143 msg.getData().putCharSequence("msg", errorMsg);
9144 mHandler.sendMessage(msg);
9145 }
9146 }
9147 }
9148
9149 retrieveSettings();
9150
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009151 if (goingCallback != null) goingCallback.run();
9152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009153 synchronized (this) {
9154 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
9155 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009156 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009157 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009158 if (apps != null) {
9159 int N = apps.size();
9160 int i;
9161 for (i=0; i<N; i++) {
9162 ApplicationInfo info
9163 = (ApplicationInfo)apps.get(i);
9164 if (info != null &&
9165 !info.packageName.equals("android")) {
9166 addAppLocked(info);
9167 }
9168 }
9169 }
9170 } catch (RemoteException ex) {
9171 // pm is in same process, this will never happen.
9172 }
9173 }
9174
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009175 // Start up initial activity.
9176 mBooting = true;
9177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009178 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009179 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009180 Message msg = Message.obtain();
9181 msg.what = SHOW_UID_ERROR_MSG;
9182 mHandler.sendMessage(msg);
9183 }
9184 } catch (RemoteException e) {
9185 }
9186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009187 resumeTopActivityLocked(null);
9188 }
9189 }
9190
Dan Egnorb7f03672009-12-09 16:22:32 -08009191 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009192 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009193 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009194 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009195 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009196 startAppProblemLocked(app);
9197 app.stopFreezingAllLocked();
9198 return handleAppCrashLocked(app);
9199 }
9200
Dan Egnorb7f03672009-12-09 16:22:32 -08009201 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009202 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009203 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009204 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009205 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
9206 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009207 startAppProblemLocked(app);
9208 app.stopFreezingAllLocked();
9209 }
9210
9211 /**
9212 * Generate a process error record, suitable for attachment to a ProcessRecord.
9213 *
9214 * @param app The ProcessRecord in which the error occurred.
9215 * @param condition Crashing, Application Not Responding, etc. Values are defined in
9216 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08009217 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009218 * @param shortMsg Short message describing the crash.
9219 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08009220 * @param stackTrace Full crash stack trace, may be null.
9221 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009222 * @return Returns a fully-formed AppErrorStateInfo record.
9223 */
9224 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009225 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08009227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009228 report.condition = condition;
9229 report.processName = app.processName;
9230 report.pid = app.pid;
9231 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08009232 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009233 report.shortMsg = shortMsg;
9234 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08009235 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009236
9237 return report;
9238 }
9239
Dan Egnor42471dd2010-01-07 17:25:22 -08009240 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009241 synchronized (this) {
9242 app.crashing = false;
9243 app.crashingReport = null;
9244 app.notResponding = false;
9245 app.notRespondingReport = null;
9246 if (app.anrDialog == fromDialog) {
9247 app.anrDialog = null;
9248 }
9249 if (app.waitDialog == fromDialog) {
9250 app.waitDialog = null;
9251 }
9252 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009253 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07009254 Slog.i(ActivityManagerService.TAG, "Killing "
9255 + app.processName + " (pid=" + app.pid + "): user's request");
9256 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
9257 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009258 Process.killProcess(app.pid);
9259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009260 }
9261 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009262
Dan Egnorb7f03672009-12-09 16:22:32 -08009263 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009264 long now = SystemClock.uptimeMillis();
9265
9266 Long crashTime = mProcessCrashTimes.get(app.info.processName,
9267 app.info.uid);
9268 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
9269 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08009270 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009272 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009273 app.info.processName, app.info.uid);
9274 killServicesLocked(app, false);
9275 for (int i=mHistory.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009276 ActivityRecord r = (ActivityRecord)mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009277 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009278 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009279 + r.intent.getComponent().flattenToShortString());
9280 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
9281 }
9282 }
9283 if (!app.persistent) {
9284 // We don't want to start this process again until the user
9285 // explicitly does so... but for persistent process, we really
9286 // need to keep it running. If a persistent process is actually
9287 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08009288 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009289 app.info.processName);
9290 mBadProcesses.put(app.info.processName, app.info.uid, now);
9291 app.bad = true;
9292 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
9293 app.removed = true;
9294 removeProcessLocked(app, false);
9295 return false;
9296 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009297 } else {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009298 ActivityRecord r = topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009299 if (r.app == app) {
9300 // If the top running activity is from this crashing
9301 // process, then terminate it to avoid getting in a loop.
9302 Slog.w(TAG, " Force finishing activity "
9303 + r.intent.getComponent().flattenToShortString());
9304 int index = indexOfTokenLocked(r);
9305 finishActivityLocked(r, index,
9306 Activity.RESULT_CANCELED, null, "crashed");
9307 // Also terminate an activities below it that aren't yet
9308 // stopped, to avoid a situation where one will get
9309 // re-start our crashing activity once it gets resumed again.
9310 index--;
9311 if (index >= 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009312 r = (ActivityRecord)mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009313 if (r.state == ActivityState.RESUMED
9314 || r.state == ActivityState.PAUSING
9315 || r.state == ActivityState.PAUSED) {
9316 if (!r.isHomeActivity) {
9317 Slog.w(TAG, " Force finishing activity "
9318 + r.intent.getComponent().flattenToShortString());
9319 finishActivityLocked(r, index,
9320 Activity.RESULT_CANCELED, null, "crashed");
9321 }
9322 }
9323 }
9324 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009325 }
9326
9327 // Bump up the crash count of any services currently running in the proc.
9328 if (app.services.size() != 0) {
9329 // Any services running in the application need to be placed
9330 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009331 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009332 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009333 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009334 sr.crashCount++;
9335 }
9336 }
9337
9338 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
9339 return true;
9340 }
9341
9342 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009343 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9344 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009345 skipCurrentReceiverLocked(app);
9346 }
9347
9348 void skipCurrentReceiverLocked(ProcessRecord app) {
9349 boolean reschedule = false;
9350 BroadcastRecord r = app.curReceiver;
9351 if (r != null) {
9352 // The current broadcast is waiting for this app's receiver
9353 // to be finished. Looks like that's not going to happen, so
9354 // let the broadcast continue.
9355 logBroadcastReceiverDiscard(r);
9356 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9357 r.resultExtras, r.resultAbort, true);
9358 reschedule = true;
9359 }
9360 r = mPendingBroadcast;
9361 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009362 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009363 "skip & discard pending app " + r);
9364 logBroadcastReceiverDiscard(r);
9365 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9366 r.resultExtras, r.resultAbort, true);
9367 reschedule = true;
9368 }
9369 if (reschedule) {
9370 scheduleBroadcastsLocked();
9371 }
9372 }
9373
Dan Egnor60d87622009-12-16 16:32:58 -08009374 /**
9375 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9376 * The application process will exit immediately after this call returns.
9377 * @param app object of the crashing app, null for the system server
9378 * @param crashInfo describing the exception
9379 */
9380 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9381 ProcessRecord r = findAppProcess(app);
9382
9383 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9384 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009385 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009386 crashInfo.exceptionClassName,
9387 crashInfo.exceptionMessage,
9388 crashInfo.throwFileName,
9389 crashInfo.throwLineNumber);
9390
Dan Egnor42471dd2010-01-07 17:25:22 -08009391 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009392
9393 crashApplication(r, crashInfo);
9394 }
9395
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009396 public void handleApplicationStrictModeViolation(
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009397 IBinder app, int violationMask, ApplicationErrorReport.CrashInfo crashInfo) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009398 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009399
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009400 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009401 Integer stackFingerprint = crashInfo.stackTrace.hashCode();
9402 boolean logIt = true;
9403 synchronized (mAlreadyLoggedViolatedStacks) {
9404 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
9405 logIt = false;
9406 // TODO: sub-sample into EventLog for these, with
9407 // the crashInfo.durationMillis? Then we'd get
9408 // the relative pain numbers, without logging all
9409 // the stack traces repeatedly. We'd want to do
9410 // likewise in the client code, which also does
9411 // dup suppression, before the Binder call.
9412 } else {
9413 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
9414 mAlreadyLoggedViolatedStacks.clear();
9415 }
9416 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
9417 }
9418 }
9419 if (logIt) {
9420 addErrorToDropBox("strictmode", r, null, null, null, null, null, crashInfo);
9421 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009422 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009423
9424 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
9425 AppErrorResult result = new AppErrorResult();
9426 synchronized (this) {
9427 final long origId = Binder.clearCallingIdentity();
9428
9429 Message msg = Message.obtain();
9430 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
9431 HashMap<String, Object> data = new HashMap<String, Object>();
9432 data.put("result", result);
9433 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009434 data.put("violationMask", violationMask);
9435 data.put("crashInfo", crashInfo);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07009436 msg.obj = data;
9437 mHandler.sendMessage(msg);
9438
9439 Binder.restoreCallingIdentity(origId);
9440 }
9441 int res = result.get();
9442 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
9443 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009444 }
9445
Dan Egnor60d87622009-12-16 16:32:58 -08009446 /**
9447 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9448 * @param app object of the crashing app, null for the system server
9449 * @param tag reported by the caller
9450 * @param crashInfo describing the context of the error
9451 * @return true if the process should exit immediately (WTF is fatal)
9452 */
9453 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009454 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009455 ProcessRecord r = findAppProcess(app);
9456
9457 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9458 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009459 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009460 tag, crashInfo.exceptionMessage);
9461
Dan Egnor42471dd2010-01-07 17:25:22 -08009462 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009463
Doug Zongker43866e02010-01-07 12:09:54 -08009464 if (Settings.Secure.getInt(mContext.getContentResolver(),
9465 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009466 crashApplication(r, crashInfo);
9467 return true;
9468 } else {
9469 return false;
9470 }
9471 }
9472
9473 /**
9474 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9475 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9476 */
9477 private ProcessRecord findAppProcess(IBinder app) {
9478 if (app == null) {
9479 return null;
9480 }
9481
9482 synchronized (this) {
9483 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9484 final int NA = apps.size();
9485 for (int ia=0; ia<NA; ia++) {
9486 ProcessRecord p = apps.valueAt(ia);
9487 if (p.thread != null && p.thread.asBinder() == app) {
9488 return p;
9489 }
9490 }
9491 }
9492
Joe Onorato8a9b2202010-02-26 18:56:32 -08009493 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009494 return null;
9495 }
9496 }
9497
9498 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009499 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009500 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009501 * @param process which caused the error, null means the system server
9502 * @param activity which triggered the error, null if unknown
9503 * @param parent activity related to the error, null if unknown
9504 * @param subject line related to the error, null if absent
9505 * @param report in long form describing the error, null if absent
9506 * @param logFile to include in the report, null if none
9507 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009508 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009509 public void addErrorToDropBox(String eventType,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009510 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
Dan Egnora455d192010-03-12 08:52:28 -08009511 final String report, final File logFile,
9512 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009513 // NOTE -- this must never acquire the ActivityManagerService lock,
9514 // otherwise the watchdog may be prevented from resetting the system.
9515
Dan Egnora455d192010-03-12 08:52:28 -08009516 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009517 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009518 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009519 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009520 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009521 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009522 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009523 }
9524
Dan Egnora455d192010-03-12 08:52:28 -08009525 final String dropboxTag = prefix + eventType;
9526 final DropBoxManager dbox = (DropBoxManager)
9527 mContext.getSystemService(Context.DROPBOX_SERVICE);
9528
9529 // Exit early if the dropbox isn't configured to accept this report type.
9530 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9531
9532 final StringBuilder sb = new StringBuilder(1024);
9533 if (process == null || process.pid == MY_PID) {
9534 sb.append("Process: system_server\n");
9535 } else {
9536 sb.append("Process: ").append(process.processName).append("\n");
9537 }
9538 if (process != null) {
9539 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009540 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08009541 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9542 for (String pkg : process.pkgList) {
9543 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009544 try {
Dan Egnora455d192010-03-12 08:52:28 -08009545 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9546 if (pi != null) {
9547 sb.append(" v").append(pi.versionCode);
9548 if (pi.versionName != null) {
9549 sb.append(" (").append(pi.versionName).append(")");
9550 }
9551 }
9552 } catch (RemoteException e) {
9553 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009554 }
Dan Egnora455d192010-03-12 08:52:28 -08009555 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009556 }
Dan Egnora455d192010-03-12 08:52:28 -08009557 }
9558 if (activity != null) {
9559 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9560 }
9561 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9562 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9563 }
9564 if (parent != null && parent != activity) {
9565 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9566 }
9567 if (subject != null) {
9568 sb.append("Subject: ").append(subject).append("\n");
9569 }
9570 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Brad Fitzpatrick04b243d2010-06-21 08:01:13 -07009571 if (crashInfo != null && crashInfo.durationMillis != -1) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07009572 sb.append("Duration-Millis: ").append(crashInfo.durationMillis).append("\n");
9573 }
Dan Egnora455d192010-03-12 08:52:28 -08009574 sb.append("\n");
9575
9576 // Do the rest in a worker thread to avoid blocking the caller on I/O
9577 // (After this point, we shouldn't access AMS internal data structures.)
9578 Thread worker = new Thread("Error dump: " + dropboxTag) {
9579 @Override
9580 public void run() {
9581 if (report != null) {
9582 sb.append(report);
9583 }
9584 if (logFile != null) {
9585 try {
9586 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9587 } catch (IOException e) {
9588 Slog.e(TAG, "Error reading " + logFile, e);
9589 }
9590 }
9591 if (crashInfo != null && crashInfo.stackTrace != null) {
9592 sb.append(crashInfo.stackTrace);
9593 }
9594
9595 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9596 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9597 if (lines > 0) {
9598 sb.append("\n");
9599
9600 // Merge several logcat streams, and take the last N lines
9601 InputStreamReader input = null;
9602 try {
9603 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9604 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9605 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9606
9607 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9608 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9609 input = new InputStreamReader(logcat.getInputStream());
9610
9611 int num;
9612 char[] buf = new char[8192];
9613 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9614 } catch (IOException e) {
9615 Slog.e(TAG, "Error running logcat", e);
9616 } finally {
9617 if (input != null) try { input.close(); } catch (IOException e) {}
9618 }
9619 }
9620
9621 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009622 }
Dan Egnora455d192010-03-12 08:52:28 -08009623 };
9624
9625 if (process == null || process.pid == MY_PID) {
9626 worker.run(); // We may be about to die -- need to run this synchronously
9627 } else {
9628 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009629 }
9630 }
9631
9632 /**
9633 * Bring up the "unexpected error" dialog box for a crashing app.
9634 * Deal with edge cases (intercepts from instrumented applications,
9635 * ActivityController, error intent receivers, that sort of thing).
9636 * @param r the application crashing
9637 * @param crashInfo describing the failure
9638 */
9639 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009640 long timeMillis = System.currentTimeMillis();
9641 String shortMsg = crashInfo.exceptionClassName;
9642 String longMsg = crashInfo.exceptionMessage;
9643 String stackTrace = crashInfo.stackTrace;
9644 if (shortMsg != null && longMsg != null) {
9645 longMsg = shortMsg + ": " + longMsg;
9646 } else if (shortMsg != null) {
9647 longMsg = shortMsg;
9648 }
9649
Dan Egnor60d87622009-12-16 16:32:58 -08009650 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009651 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009652 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009653 try {
9654 String name = r != null ? r.processName : null;
9655 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009656 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009657 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009658 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009659 + " at watcher's request");
9660 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009661 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009662 }
9663 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009664 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009665 }
9666 }
9667
9668 final long origId = Binder.clearCallingIdentity();
9669
9670 // If this process is running instrumentation, finish it.
9671 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009672 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009673 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009674 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9675 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676 Bundle info = new Bundle();
9677 info.putString("shortMsg", shortMsg);
9678 info.putString("longMsg", longMsg);
9679 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9680 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009681 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009682 }
9683
Dan Egnor60d87622009-12-16 16:32:58 -08009684 // If we can't identify the process or it's already exceeded its crash quota,
9685 // quit right away without showing a crash dialog.
9686 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009687 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009688 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689 }
9690
9691 Message msg = Message.obtain();
9692 msg.what = SHOW_ERROR_MSG;
9693 HashMap data = new HashMap();
9694 data.put("result", result);
9695 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009696 msg.obj = data;
9697 mHandler.sendMessage(msg);
9698
9699 Binder.restoreCallingIdentity(origId);
9700 }
9701
9702 int res = result.get();
9703
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009704 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009705 synchronized (this) {
9706 if (r != null) {
9707 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9708 SystemClock.uptimeMillis());
9709 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009710 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009711 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009712 }
9713 }
9714
9715 if (appErrorIntent != null) {
9716 try {
9717 mContext.startActivity(appErrorIntent);
9718 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009719 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009722 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009723
9724 Intent createAppErrorIntentLocked(ProcessRecord r,
9725 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9726 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009727 if (report == null) {
9728 return null;
9729 }
9730 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9731 result.setComponent(r.errorReportReceiver);
9732 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9733 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9734 return result;
9735 }
9736
Dan Egnorb7f03672009-12-09 16:22:32 -08009737 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9738 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009739 if (r.errorReportReceiver == null) {
9740 return null;
9741 }
9742
9743 if (!r.crashing && !r.notResponding) {
9744 return null;
9745 }
9746
Dan Egnorb7f03672009-12-09 16:22:32 -08009747 ApplicationErrorReport report = new ApplicationErrorReport();
9748 report.packageName = r.info.packageName;
9749 report.installerPackageName = r.errorReportReceiver.getPackageName();
9750 report.processName = r.processName;
9751 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009752 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009753
Dan Egnorb7f03672009-12-09 16:22:32 -08009754 if (r.crashing) {
9755 report.type = ApplicationErrorReport.TYPE_CRASH;
9756 report.crashInfo = crashInfo;
9757 } else if (r.notResponding) {
9758 report.type = ApplicationErrorReport.TYPE_ANR;
9759 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009760
Dan Egnorb7f03672009-12-09 16:22:32 -08009761 report.anrInfo.activity = r.notRespondingReport.tag;
9762 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9763 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009764 }
9765
Dan Egnorb7f03672009-12-09 16:22:32 -08009766 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009767 }
9768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009769 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9770 // assume our apps are happy - lazy create the list
9771 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9772
9773 synchronized (this) {
9774
9775 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009776 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9777 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009778 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9779 // This one's in trouble, so we'll generate a report for it
9780 // crashes are higher priority (in case there's a crash *and* an anr)
9781 ActivityManager.ProcessErrorStateInfo report = null;
9782 if (app.crashing) {
9783 report = app.crashingReport;
9784 } else if (app.notResponding) {
9785 report = app.notRespondingReport;
9786 }
9787
9788 if (report != null) {
9789 if (errList == null) {
9790 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9791 }
9792 errList.add(report);
9793 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009794 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009795 " crashing = " + app.crashing +
9796 " notResponding = " + app.notResponding);
9797 }
9798 }
9799 }
9800 }
9801
9802 return errList;
9803 }
9804
9805 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9806 // Lazy instantiation of list
9807 List<ActivityManager.RunningAppProcessInfo> runList = null;
9808 synchronized (this) {
9809 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009810 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9811 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009812 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9813 // Generate process state info for running application
9814 ActivityManager.RunningAppProcessInfo currApp =
9815 new ActivityManager.RunningAppProcessInfo(app.processName,
9816 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009817 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07009818 if (mHeavyWeightProcess == app) {
9819 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
9820 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009822 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009823 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9824 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9825 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009826 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9827 } else if (adj >= HOME_APP_ADJ) {
9828 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9829 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 } else if (adj >= SECONDARY_SERVER_ADJ) {
9831 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07009832 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
9833 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
9834 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
9835 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009836 } else if (adj >= VISIBLE_APP_ADJ) {
9837 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9838 } else {
9839 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9840 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009841 currApp.importanceReasonCode = app.adjTypeCode;
9842 if (app.adjSource instanceof ProcessRecord) {
9843 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009844 } else if (app.adjSource instanceof ActivityRecord) {
9845 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009846 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9847 }
9848 if (app.adjTarget instanceof ComponentName) {
9849 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9850 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009851 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009852 // + " lru=" + currApp.lru);
9853 if (runList == null) {
9854 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9855 }
9856 runList.add(currApp);
9857 }
9858 }
9859 }
9860 return runList;
9861 }
9862
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009863 public List<ApplicationInfo> getRunningExternalApplications() {
9864 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9865 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9866 if (runningApps != null && runningApps.size() > 0) {
9867 Set<String> extList = new HashSet<String>();
9868 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9869 if (app.pkgList != null) {
9870 for (String pkg : app.pkgList) {
9871 extList.add(pkg);
9872 }
9873 }
9874 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009875 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009876 for (String pkg : extList) {
9877 try {
9878 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9879 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9880 retList.add(info);
9881 }
9882 } catch (RemoteException e) {
9883 }
9884 }
9885 }
9886 return retList;
9887 }
9888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009889 @Override
9890 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009891 if (checkCallingPermission(android.Manifest.permission.DUMP)
9892 != PackageManager.PERMISSION_GRANTED) {
9893 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9894 + Binder.getCallingPid()
9895 + ", uid=" + Binder.getCallingUid()
9896 + " without permission "
9897 + android.Manifest.permission.DUMP);
9898 return;
9899 }
9900
9901 boolean dumpAll = false;
9902
9903 int opti = 0;
9904 while (opti < args.length) {
9905 String opt = args[opti];
9906 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9907 break;
9908 }
9909 opti++;
9910 if ("-a".equals(opt)) {
9911 dumpAll = true;
9912 } else if ("-h".equals(opt)) {
9913 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009914 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009915 pw.println(" cmd may be one of:");
9916 pw.println(" activities: activity stack state");
9917 pw.println(" broadcasts: broadcast state");
9918 pw.println(" intents: pending intent state");
9919 pw.println(" processes: process state");
9920 pw.println(" providers: content provider state");
9921 pw.println(" services: service state");
9922 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009923 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009924 } else {
9925 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009926 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009927 }
9928
9929 // Is the caller requesting to dump a particular piece of data?
9930 if (opti < args.length) {
9931 String cmd = args[opti];
9932 opti++;
9933 if ("activities".equals(cmd) || "a".equals(cmd)) {
9934 synchronized (this) {
9935 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009936 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009937 return;
9938 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9939 synchronized (this) {
9940 dumpBroadcastsLocked(fd, pw, args, opti, true);
9941 }
9942 return;
9943 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9944 synchronized (this) {
9945 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9946 }
9947 return;
9948 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9949 synchronized (this) {
9950 dumpProcessesLocked(fd, pw, args, opti, true);
9951 }
9952 return;
9953 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9954 synchronized (this) {
9955 dumpProvidersLocked(fd, pw, args, opti, true);
9956 }
9957 return;
9958 } else if ("service".equals(cmd)) {
9959 dumpService(fd, pw, args, opti, true);
9960 return;
9961 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9962 synchronized (this) {
9963 dumpServicesLocked(fd, pw, args, opti, true);
9964 }
9965 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009966 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009967 }
9968
9969 // No piece of data specified, dump everything.
9970 synchronized (this) {
9971 boolean needSep;
9972 if (dumpAll) {
9973 pw.println("Providers in Current Activity Manager State:");
9974 }
9975 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9976 if (needSep) {
9977 pw.println(" ");
9978 }
9979 if (dumpAll) {
9980 pw.println("-------------------------------------------------------------------------------");
9981 pw.println("Broadcasts in Current Activity Manager State:");
9982 }
9983 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9984 if (needSep) {
9985 pw.println(" ");
9986 }
9987 if (dumpAll) {
9988 pw.println("-------------------------------------------------------------------------------");
9989 pw.println("Services in Current Activity Manager State:");
9990 }
9991 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9992 if (needSep) {
9993 pw.println(" ");
9994 }
9995 if (dumpAll) {
9996 pw.println("-------------------------------------------------------------------------------");
9997 pw.println("PendingIntents in Current Activity Manager State:");
9998 }
9999 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
10000 if (needSep) {
10001 pw.println(" ");
10002 }
10003 if (dumpAll) {
10004 pw.println("-------------------------------------------------------------------------------");
10005 pw.println("Activities in Current Activity Manager State:");
10006 }
10007 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
10008 if (needSep) {
10009 pw.println(" ");
10010 }
10011 if (dumpAll) {
10012 pw.println("-------------------------------------------------------------------------------");
10013 pw.println("Processes in Current Activity Manager State:");
10014 }
10015 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
10016 }
10017 }
10018
10019 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10020 int opti, boolean dumpAll, boolean needHeader) {
10021 if (needHeader) {
10022 pw.println(" Activity stack:");
10023 }
10024 dumpHistoryList(pw, mHistory, " ", "Hist", true);
10025 pw.println(" ");
10026 pw.println(" Running activities (most recent first):");
10027 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
10028 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010029 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010030 pw.println(" Activities waiting for another to become visible:");
10031 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
10032 }
10033 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010034 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010035 pw.println(" Activities waiting to stop:");
10036 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
10037 }
10038 if (mFinishingActivities.size() > 0) {
10039 pw.println(" ");
10040 pw.println(" Activities waiting to finish:");
10041 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
10042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010043
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010044 pw.println(" ");
10045 pw.println(" mPausingActivity: " + mPausingActivity);
10046 pw.println(" mResumedActivity: " + mResumedActivity);
10047 pw.println(" mFocusedActivity: " + mFocusedActivity);
10048 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010049
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010050 if (dumpAll && mRecentTasks.size() > 0) {
10051 pw.println(" ");
10052 pw.println("Recent tasks in Current Activity Manager State:");
10053
10054 final int N = mRecentTasks.size();
10055 for (int i=0; i<N; i++) {
10056 TaskRecord tr = mRecentTasks.get(i);
10057 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
10058 pw.println(tr);
10059 mRecentTasks.get(i).dump(pw, " ");
10060 }
10061 }
10062
10063 pw.println(" ");
10064 pw.println(" mCurTask: " + mCurTask);
10065
10066 return true;
10067 }
10068
10069 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10070 int opti, boolean dumpAll) {
10071 boolean needSep = false;
10072 int numPers = 0;
10073
10074 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
10076 final int NA = procs.size();
10077 for (int ia=0; ia<NA; ia++) {
10078 if (!needSep) {
10079 pw.println(" All known processes:");
10080 needSep = true;
10081 }
10082 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010083 pw.print(r.persistent ? " *PERS*" : " *APP*");
10084 pw.print(" UID "); pw.print(procs.keyAt(ia));
10085 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010086 r.dump(pw, " ");
10087 if (r.persistent) {
10088 numPers++;
10089 }
10090 }
10091 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010092 }
10093
10094 if (mLruProcesses.size() > 0) {
10095 if (needSep) pw.println(" ");
10096 needSep = true;
10097 pw.println(" Running processes (most recent first):");
10098 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010099 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010100 needSep = true;
10101 }
10102
10103 synchronized (mPidsSelfLocked) {
10104 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010105 if (needSep) pw.println(" ");
10106 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010107 pw.println(" PID mappings:");
10108 for (int i=0; i<mPidsSelfLocked.size(); i++) {
10109 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
10110 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010111 }
10112 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010113 }
10114
10115 if (mForegroundProcesses.size() > 0) {
10116 if (needSep) pw.println(" ");
10117 needSep = true;
10118 pw.println(" Foreground Processes:");
10119 for (int i=0; i<mForegroundProcesses.size(); i++) {
10120 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
10121 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010122 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010123 }
10124
10125 if (mPersistentStartingProcesses.size() > 0) {
10126 if (needSep) pw.println(" ");
10127 needSep = true;
10128 pw.println(" Persisent processes that are starting:");
10129 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
10130 "Starting Norm", "Restarting PERS", false);
10131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010132
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010133 if (mStartingProcesses.size() > 0) {
10134 if (needSep) pw.println(" ");
10135 needSep = true;
10136 pw.println(" Processes that are starting:");
10137 dumpProcessList(pw, this, mStartingProcesses, " ",
10138 "Starting Norm", "Starting PERS", false);
10139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010141 if (mRemovedProcesses.size() > 0) {
10142 if (needSep) pw.println(" ");
10143 needSep = true;
10144 pw.println(" Processes that are being removed:");
10145 dumpProcessList(pw, this, mRemovedProcesses, " ",
10146 "Removed Norm", "Removed PERS", false);
10147 }
10148
10149 if (mProcessesOnHold.size() > 0) {
10150 if (needSep) pw.println(" ");
10151 needSep = true;
10152 pw.println(" Processes that are on old until the system is ready:");
10153 dumpProcessList(pw, this, mProcessesOnHold, " ",
10154 "OnHold Norm", "OnHold PERS", false);
10155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010156
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010157 if (mProcessesToGc.size() > 0) {
10158 if (needSep) pw.println(" ");
10159 needSep = true;
10160 pw.println(" Processes that are waiting to GC:");
10161 long now = SystemClock.uptimeMillis();
10162 for (int i=0; i<mProcessesToGc.size(); i++) {
10163 ProcessRecord proc = mProcessesToGc.get(i);
10164 pw.print(" Process "); pw.println(proc);
10165 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
10166 pw.print(", last gced=");
10167 pw.print(now-proc.lastRequestedGc);
10168 pw.print(" ms ago, last lowMem=");
10169 pw.print(now-proc.lastLowMemory);
10170 pw.println(" ms ago");
10171
10172 }
10173 }
10174
10175 if (mProcessCrashTimes.getMap().size() > 0) {
10176 if (needSep) pw.println(" ");
10177 needSep = true;
10178 pw.println(" Time since processes crashed:");
10179 long now = SystemClock.uptimeMillis();
10180 for (Map.Entry<String, SparseArray<Long>> procs
10181 : mProcessCrashTimes.getMap().entrySet()) {
10182 SparseArray<Long> uids = procs.getValue();
10183 final int N = uids.size();
10184 for (int i=0; i<N; i++) {
10185 pw.print(" Process "); pw.print(procs.getKey());
10186 pw.print(" uid "); pw.print(uids.keyAt(i));
10187 pw.print(": last crashed ");
10188 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010189 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010190 }
10191 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010192 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010193
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010194 if (mBadProcesses.getMap().size() > 0) {
10195 if (needSep) pw.println(" ");
10196 needSep = true;
10197 pw.println(" Bad processes:");
10198 for (Map.Entry<String, SparseArray<Long>> procs
10199 : mBadProcesses.getMap().entrySet()) {
10200 SparseArray<Long> uids = procs.getValue();
10201 final int N = uids.size();
10202 for (int i=0; i<N; i++) {
10203 pw.print(" Bad process "); pw.print(procs.getKey());
10204 pw.print(" uid "); pw.print(uids.keyAt(i));
10205 pw.print(": crashed at time ");
10206 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010207 }
10208 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010209 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010210
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010211 pw.println(" ");
10212 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010213 if (mHeavyWeightProcess != null) {
10214 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
10215 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010216 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -070010217 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010218 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
10219 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
10220 || mOrigWaitForDebugger) {
10221 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
10222 + " mDebugTransient=" + mDebugTransient
10223 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
10224 }
10225 if (mAlwaysFinishActivities || mController != null) {
10226 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
10227 + " mController=" + mController);
10228 }
10229 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010231 pw.println(" mStartRunning=" + mStartRunning
10232 + " mSystemReady=" + mSystemReady
10233 + " mBooting=" + mBooting
10234 + " mBooted=" + mBooted
10235 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236 pw.println(" mGoingToSleep=" + mGoingToSleep);
10237 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -070010238 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010239 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010240
10241 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 }
10243
10244 /**
10245 * There are three ways to call this:
10246 * - no service specified: dump all the services
10247 * - a flattened component name that matched an existing service was specified as the
10248 * first arg: dump that one service
10249 * - the first arg isn't the flattened component name of an existing service:
10250 * dump all services whose component contains the first arg as a substring
10251 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010252 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
10253 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010254 String[] newArgs;
10255 String componentNameString;
10256 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -080010257 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010258 componentNameString = null;
10259 newArgs = EMPTY_STRING_ARRAY;
10260 r = null;
10261 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010262 componentNameString = args[opti];
10263 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010264 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
10265 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010266 newArgs = new String[args.length - opti];
10267 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010268 }
10269
10270 if (r != null) {
10271 dumpService(fd, pw, r, newArgs);
10272 } else {
10273 for (ServiceRecord r1 : mServices.values()) {
10274 if (componentNameString == null
10275 || r1.name.flattenToString().contains(componentNameString)) {
10276 dumpService(fd, pw, r1, newArgs);
10277 }
10278 }
10279 }
10280 }
10281
10282 /**
10283 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
10284 * there is a thread associated with the service.
10285 */
10286 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
10287 pw.println(" Service " + r.name.flattenToString());
10288 if (r.app != null && r.app.thread != null) {
10289 try {
10290 // flush anything that is already in the PrintWriter since the thread is going
10291 // to write to the file descriptor directly
10292 pw.flush();
10293 r.app.thread.dumpService(fd, r, args);
10294 pw.print("\n");
10295 } catch (RemoteException e) {
10296 pw.println("got a RemoteException while dumping the service");
10297 }
10298 }
10299 }
10300
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010301 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10302 int opti, boolean dumpAll) {
10303 boolean needSep = false;
10304
10305 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010306 if (mRegisteredReceivers.size() > 0) {
10307 pw.println(" ");
10308 pw.println(" Registered Receivers:");
10309 Iterator it = mRegisteredReceivers.values().iterator();
10310 while (it.hasNext()) {
10311 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010312 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010313 r.dump(pw, " ");
10314 }
10315 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010317 pw.println(" ");
10318 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010319 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010320 needSep = true;
10321 }
10322
10323 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
10324 || mPendingBroadcast != null) {
10325 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010326 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010327 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010328 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010329 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10330 pw.println(" Broadcast #" + i + ":");
10331 mParallelBroadcasts.get(i).dump(pw, " ");
10332 }
10333 if (mOrderedBroadcasts.size() > 0) {
10334 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010335 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010336 }
10337 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10338 pw.println(" Serialized Broadcast #" + i + ":");
10339 mOrderedBroadcasts.get(i).dump(pw, " ");
10340 }
10341 pw.println(" ");
10342 pw.println(" Pending broadcast:");
10343 if (mPendingBroadcast != null) {
10344 mPendingBroadcast.dump(pw, " ");
10345 } else {
10346 pw.println(" (null)");
10347 }
10348 needSep = true;
10349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010350
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010351 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010352 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -080010353 pw.println(" Historical broadcasts:");
10354 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
10355 BroadcastRecord r = mBroadcastHistory[i];
10356 if (r == null) {
10357 break;
10358 }
10359 pw.println(" Historical Broadcast #" + i + ":");
10360 r.dump(pw, " ");
10361 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010362 needSep = true;
10363 }
10364
10365 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010366 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010367 pw.println(" Sticky broadcasts:");
10368 StringBuilder sb = new StringBuilder(128);
10369 for (Map.Entry<String, ArrayList<Intent>> ent
10370 : mStickyBroadcasts.entrySet()) {
10371 pw.print(" * Sticky action "); pw.print(ent.getKey());
10372 pw.println(":");
10373 ArrayList<Intent> intents = ent.getValue();
10374 final int N = intents.size();
10375 for (int i=0; i<N; i++) {
10376 sb.setLength(0);
10377 sb.append(" Intent: ");
10378 intents.get(i).toShortString(sb, true, false);
10379 pw.println(sb.toString());
10380 Bundle bundle = intents.get(i).getExtras();
10381 if (bundle != null) {
10382 pw.print(" ");
10383 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010384 }
10385 }
10386 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010387 needSep = true;
10388 }
10389
10390 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010391 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010392 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010393 pw.println(" mHandler:");
10394 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010395 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010396 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010397
10398 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010399 }
10400
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010401 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10402 int opti, boolean dumpAll) {
10403 boolean needSep = false;
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 if (mServices.size() > 0) {
10407 pw.println(" Active services:");
10408 Iterator<ServiceRecord> it = mServices.values().iterator();
10409 while (it.hasNext()) {
10410 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010411 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010412 r.dump(pw, " ");
10413 }
10414 needSep = true;
10415 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010417
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010418 if (mPendingServices.size() > 0) {
10419 if (needSep) pw.println(" ");
10420 pw.println(" Pending services:");
10421 for (int i=0; i<mPendingServices.size(); i++) {
10422 ServiceRecord r = mPendingServices.get(i);
10423 pw.print(" * Pending "); pw.println(r);
10424 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010425 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010426 needSep = true;
10427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010428
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010429 if (mRestartingServices.size() > 0) {
10430 if (needSep) pw.println(" ");
10431 pw.println(" Restarting services:");
10432 for (int i=0; i<mRestartingServices.size(); i++) {
10433 ServiceRecord r = mRestartingServices.get(i);
10434 pw.print(" * Restarting "); pw.println(r);
10435 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010436 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010437 needSep = true;
10438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010439
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010440 if (mStoppingServices.size() > 0) {
10441 if (needSep) pw.println(" ");
10442 pw.println(" Stopping services:");
10443 for (int i=0; i<mStoppingServices.size(); i++) {
10444 ServiceRecord r = mStoppingServices.get(i);
10445 pw.print(" * Stopping "); pw.println(r);
10446 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010447 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010448 needSep = true;
10449 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010450
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010451 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010452 if (mServiceConnections.size() > 0) {
10453 if (needSep) pw.println(" ");
10454 pw.println(" Connection bindings to services:");
10455 Iterator<ConnectionRecord> it
10456 = mServiceConnections.values().iterator();
10457 while (it.hasNext()) {
10458 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010459 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010460 r.dump(pw, " ");
10461 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010462 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010463 }
10464 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010465
10466 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010467 }
10468
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010469 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10470 int opti, boolean dumpAll) {
10471 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010472
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010473 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010474 if (mProvidersByClass.size() > 0) {
10475 if (needSep) pw.println(" ");
10476 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010477 Iterator<Map.Entry<String, ContentProviderRecord>> it
10478 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010480 Map.Entry<String, ContentProviderRecord> e = it.next();
10481 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010482 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010483 r.dump(pw, " ");
10484 }
10485 needSep = true;
10486 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010487
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010488 if (mProvidersByName.size() > 0) {
10489 pw.println(" ");
10490 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010491 Iterator<Map.Entry<String, ContentProviderRecord>> it
10492 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010493 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010494 Map.Entry<String, ContentProviderRecord> e = it.next();
10495 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010496 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10497 pw.println(r);
10498 }
10499 needSep = true;
10500 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010501 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010502
10503 if (mLaunchingProviders.size() > 0) {
10504 if (needSep) pw.println(" ");
10505 pw.println(" Launching content providers:");
10506 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10507 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10508 pw.println(mLaunchingProviders.get(i));
10509 }
10510 needSep = true;
10511 }
10512
10513 if (mGrantedUriPermissions.size() > 0) {
10514 pw.println();
10515 pw.println("Granted Uri Permissions:");
10516 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10517 int uid = mGrantedUriPermissions.keyAt(i);
10518 HashMap<Uri, UriPermission> perms
10519 = mGrantedUriPermissions.valueAt(i);
10520 pw.print(" * UID "); pw.print(uid);
10521 pw.println(" holds:");
10522 for (UriPermission perm : perms.values()) {
10523 pw.print(" "); pw.println(perm);
10524 perm.dump(pw, " ");
10525 }
10526 }
10527 needSep = true;
10528 }
10529
10530 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010531 }
10532
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010533 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10534 int opti, boolean dumpAll) {
10535 boolean needSep = false;
10536
10537 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010538 if (this.mIntentSenderRecords.size() > 0) {
10539 Iterator<WeakReference<PendingIntentRecord>> it
10540 = mIntentSenderRecords.values().iterator();
10541 while (it.hasNext()) {
10542 WeakReference<PendingIntentRecord> ref = it.next();
10543 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010544 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010545 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010546 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010547 rec.dump(pw, " ");
10548 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010549 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010550 }
10551 }
10552 }
10553 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010554
10555 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010556 }
10557
10558 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010559 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010560 TaskRecord lastTask = null;
10561 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010562 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010563 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010564 if (lastTask != r.task) {
10565 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010566 pw.print(prefix);
10567 pw.print(full ? "* " : " ");
10568 pw.println(lastTask);
10569 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010570 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010572 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010573 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10574 pw.print(" #"); pw.print(i); pw.print(": ");
10575 pw.println(r);
10576 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010577 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010579 }
10580 }
10581
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010582 private static String buildOomTag(String prefix, String space, int val, int base) {
10583 if (val == base) {
10584 if (space == null) return prefix;
10585 return prefix + " ";
10586 }
10587 return prefix + "+" + Integer.toString(val-base);
10588 }
10589
10590 private static final int dumpProcessList(PrintWriter pw,
10591 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010592 String prefix, String normalLabel, String persistentLabel,
10593 boolean inclOomAdj) {
10594 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010595 final int N = list.size()-1;
10596 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010597 ProcessRecord r = (ProcessRecord)list.get(i);
10598 if (false) {
10599 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10600 + " #" + i + ":");
10601 r.dump(pw, prefix + " ");
10602 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010603 String oomAdj;
10604 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010605 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010606 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010607 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10608 } else if (r.setAdj >= HOME_APP_ADJ) {
10609 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10610 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10611 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10612 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10613 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010614 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
10615 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
10616 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
10617 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010618 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10619 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10620 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10621 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010622 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010623 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010624 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010625 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010626 } else {
10627 oomAdj = Integer.toString(r.setAdj);
10628 }
10629 String schedGroup;
10630 switch (r.setSchedGroup) {
10631 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10632 schedGroup = "B";
10633 break;
10634 case Process.THREAD_GROUP_DEFAULT:
10635 schedGroup = "F";
10636 break;
10637 default:
10638 schedGroup = Integer.toString(r.setSchedGroup);
10639 break;
10640 }
10641 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010642 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010643 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010644 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010645 pw.print(prefix);
10646 pw.print(" ");
10647 if (r.adjTarget instanceof ComponentName) {
10648 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
10649 } else if (r.adjTarget != null) {
10650 pw.print(r.adjTarget.toString());
10651 } else {
10652 pw.print("{null}");
10653 }
10654 pw.print("<=");
10655 if (r.adjSource instanceof ProcessRecord) {
10656 pw.print("Proc{");
10657 pw.print(((ProcessRecord)r.adjSource).toShortString());
10658 pw.println("}");
10659 } else if (r.adjSource != null) {
10660 pw.println(r.adjSource.toString());
10661 } else {
10662 pw.println("{null}");
10663 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010665 } else {
10666 pw.println(String.format("%s%s #%2d: %s",
10667 prefix, (r.persistent ? persistentLabel : normalLabel),
10668 i, r.toString()));
10669 }
10670 if (r.persistent) {
10671 numPers++;
10672 }
10673 }
10674 return numPers;
10675 }
10676
Dianne Hackborn472ad872010-04-07 17:31:48 -070010677 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010678 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010679 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010680 long uptime = SystemClock.uptimeMillis();
10681 long realtime = SystemClock.elapsedRealtime();
10682
10683 if (isCheckinRequest) {
10684 // short checkin version
10685 pw.println(uptime + "," + realtime);
10686 pw.flush();
10687 } else {
10688 pw.println("Applications Memory Usage (kB):");
10689 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10690 }
10691 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10692 ProcessRecord r = (ProcessRecord)list.get(i);
10693 if (r.thread != null) {
10694 if (!isCheckinRequest) {
10695 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10696 pw.flush();
10697 }
10698 try {
10699 r.thread.asBinder().dump(fd, args);
10700 } catch (RemoteException e) {
10701 if (!isCheckinRequest) {
10702 pw.println("Got RemoteException!");
10703 pw.flush();
10704 }
10705 }
10706 }
10707 }
10708 }
10709
10710 /**
10711 * Searches array of arguments for the specified string
10712 * @param args array of argument strings
10713 * @param value value to search for
10714 * @return true if the value is contained in the array
10715 */
10716 private static boolean scanArgs(String[] args, String value) {
10717 if (args != null) {
10718 for (String arg : args) {
10719 if (value.equals(arg)) {
10720 return true;
10721 }
10722 }
10723 }
10724 return false;
10725 }
10726
Dianne Hackborn75b03852009-06-12 15:43:26 -070010727 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010728 int count = mHistory.size();
10729
10730 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010731 int index = -1;
10732 for (int i=count-1; i>=0; i--) {
10733 Object o = mHistory.get(i);
10734 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010735 index = i;
10736 break;
10737 }
10738 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010739
10740 return index;
10741 }
10742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010743 private final void killServicesLocked(ProcessRecord app,
10744 boolean allowRestart) {
10745 // Report disconnected services.
10746 if (false) {
10747 // XXX we are letting the client link to the service for
10748 // death notifications.
10749 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010750 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010751 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010752 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753 if (r.connections.size() > 0) {
10754 Iterator<ConnectionRecord> jt
10755 = r.connections.values().iterator();
10756 while (jt.hasNext()) {
10757 ConnectionRecord c = jt.next();
10758 if (c.binding.client != app) {
10759 try {
10760 //c.conn.connected(r.className, null);
10761 } catch (Exception e) {
10762 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010763 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010764 + r.shortName
10765 + " from app " + app.processName, e);
10766 }
10767 }
10768 }
10769 }
10770 }
10771 }
10772 }
10773
10774 // Clean up any connections this application has to other services.
10775 if (app.connections.size() > 0) {
10776 Iterator<ConnectionRecord> it = app.connections.iterator();
10777 while (it.hasNext()) {
10778 ConnectionRecord r = it.next();
10779 removeConnectionLocked(r, app, null);
10780 }
10781 }
10782 app.connections.clear();
10783
10784 if (app.services.size() != 0) {
10785 // Any services running in the application need to be placed
10786 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010787 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010788 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010789 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010790 synchronized (sr.stats.getBatteryStats()) {
10791 sr.stats.stopLaunchedLocked();
10792 }
10793 sr.app = null;
10794 sr.executeNesting = 0;
10795 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010796
10797 boolean hasClients = sr.bindings.size() > 0;
10798 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010799 Iterator<IntentBindRecord> bindings
10800 = sr.bindings.values().iterator();
10801 while (bindings.hasNext()) {
10802 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010803 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010804 + ": shouldUnbind=" + b.hasBound);
10805 b.binder = null;
10806 b.requested = b.received = b.hasBound = false;
10807 }
10808 }
10809
10810 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010811 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010812 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010813 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010814 sr.crashCount, sr.shortName, app.pid);
10815 bringDownServiceLocked(sr, true);
10816 } else if (!allowRestart) {
10817 bringDownServiceLocked(sr, true);
10818 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010819 boolean canceled = scheduleServiceRestartLocked(sr, true);
10820
10821 // Should the service remain running? Note that in the
10822 // extreme case of so many attempts to deliver a command
10823 // that it failed, that we also will stop it here.
10824 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10825 if (sr.pendingStarts.size() == 0) {
10826 sr.startRequested = false;
10827 if (!hasClients) {
10828 // Whoops, no reason to restart!
10829 bringDownServiceLocked(sr, true);
10830 }
10831 }
10832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010833 }
10834 }
10835
10836 if (!allowRestart) {
10837 app.services.clear();
10838 }
10839 }
10840
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010841 // Make sure we have no more records on the stopping list.
10842 int i = mStoppingServices.size();
10843 while (i > 0) {
10844 i--;
10845 ServiceRecord sr = mStoppingServices.get(i);
10846 if (sr.app == app) {
10847 mStoppingServices.remove(i);
10848 }
10849 }
10850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010851 app.executingServices.clear();
10852 }
10853
10854 private final void removeDyingProviderLocked(ProcessRecord proc,
10855 ContentProviderRecord cpr) {
10856 synchronized (cpr) {
10857 cpr.launchingApp = null;
10858 cpr.notifyAll();
10859 }
10860
10861 mProvidersByClass.remove(cpr.info.name);
10862 String names[] = cpr.info.authority.split(";");
10863 for (int j = 0; j < names.length; j++) {
10864 mProvidersByName.remove(names[j]);
10865 }
10866
10867 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10868 while (cit.hasNext()) {
10869 ProcessRecord capp = cit.next();
10870 if (!capp.persistent && capp.thread != null
10871 && capp.pid != 0
10872 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010873 Slog.i(TAG, "Kill " + capp.processName
10874 + " (pid " + capp.pid + "): provider " + cpr.info.name
10875 + " in dying process " + proc.processName);
10876 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10877 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010878 Process.killProcess(capp.pid);
10879 }
10880 }
10881
10882 mLaunchingProviders.remove(cpr);
10883 }
10884
10885 /**
10886 * Main code for cleaning up a process when it has gone away. This is
10887 * called both as a result of the process dying, or directly when stopping
10888 * a process when running in single process mode.
10889 */
10890 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10891 boolean restarting, int index) {
10892 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010893 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 }
10895
Dianne Hackborn36124872009-10-08 16:22:03 -070010896 mProcessesToGc.remove(app);
10897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 // Dismiss any open dialogs.
10899 if (app.crashDialog != null) {
10900 app.crashDialog.dismiss();
10901 app.crashDialog = null;
10902 }
10903 if (app.anrDialog != null) {
10904 app.anrDialog.dismiss();
10905 app.anrDialog = null;
10906 }
10907 if (app.waitDialog != null) {
10908 app.waitDialog.dismiss();
10909 app.waitDialog = null;
10910 }
10911
10912 app.crashing = false;
10913 app.notResponding = false;
10914
10915 app.resetPackageList();
10916 app.thread = null;
10917 app.forcingToForeground = null;
10918 app.foregroundServices = false;
10919
10920 killServicesLocked(app, true);
10921
10922 boolean restart = false;
10923
10924 int NL = mLaunchingProviders.size();
10925
10926 // Remove published content providers.
10927 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010928 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010930 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010931 cpr.provider = null;
10932 cpr.app = null;
10933
10934 // See if someone is waiting for this provider... in which
10935 // case we don't remove it, but just let it restart.
10936 int i = 0;
10937 if (!app.bad) {
10938 for (; i<NL; i++) {
10939 if (mLaunchingProviders.get(i) == cpr) {
10940 restart = true;
10941 break;
10942 }
10943 }
10944 } else {
10945 i = NL;
10946 }
10947
10948 if (i >= NL) {
10949 removeDyingProviderLocked(app, cpr);
10950 NL = mLaunchingProviders.size();
10951 }
10952 }
10953 app.pubProviders.clear();
10954 }
10955
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010956 // Take care of any launching providers waiting for this process.
10957 if (checkAppInLaunchingProvidersLocked(app, false)) {
10958 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010959 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010961 // Unregister from connected content providers.
10962 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010963 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010964 while (it.hasNext()) {
10965 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10966 cpr.clients.remove(app);
10967 }
10968 app.conProviders.clear();
10969 }
10970
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010971 // At this point there may be remaining entries in mLaunchingProviders
10972 // where we were the only one waiting, so they are no longer of use.
10973 // Look for these and clean up if found.
10974 // XXX Commented out for now. Trying to figure out a way to reproduce
10975 // the actual situation to identify what is actually going on.
10976 if (false) {
10977 for (int i=0; i<NL; i++) {
10978 ContentProviderRecord cpr = (ContentProviderRecord)
10979 mLaunchingProviders.get(i);
10980 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10981 synchronized (cpr) {
10982 cpr.launchingApp = null;
10983 cpr.notifyAll();
10984 }
10985 }
10986 }
10987 }
10988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 skipCurrentReceiverLocked(app);
10990
10991 // Unregister any receivers.
10992 if (app.receivers.size() > 0) {
10993 Iterator<ReceiverList> it = app.receivers.iterator();
10994 while (it.hasNext()) {
10995 removeReceiverLocked(it.next());
10996 }
10997 app.receivers.clear();
10998 }
10999
Christopher Tate181fafa2009-05-14 11:12:14 -070011000 // If the app is undergoing backup, tell the backup manager about it
11001 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011002 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070011003 try {
11004 IBackupManager bm = IBackupManager.Stub.asInterface(
11005 ServiceManager.getService(Context.BACKUP_SERVICE));
11006 bm.agentDisconnected(app.info.packageName);
11007 } catch (RemoteException e) {
11008 // can't happen; backup manager is local
11009 }
11010 }
11011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011012 // If the caller is restarting this app, then leave it in its
11013 // current lists and let the caller take care of it.
11014 if (restarting) {
11015 return;
11016 }
11017
11018 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011019 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011020 "Removing non-persistent process during cleanup: " + app);
11021 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070011022 if (mHeavyWeightProcess == app) {
11023 mHeavyWeightProcess = null;
11024 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
11025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011026 } else if (!app.removed) {
11027 // This app is persistent, so we need to keep its record around.
11028 // If it is not already on the pending app list, add it there
11029 // and start a new process for it.
11030 app.thread = null;
11031 app.forcingToForeground = null;
11032 app.foregroundServices = false;
11033 if (mPersistentStartingProcesses.indexOf(app) < 0) {
11034 mPersistentStartingProcesses.add(app);
11035 restart = true;
11036 }
11037 }
11038 mProcessesOnHold.remove(app);
11039
The Android Open Source Project4df24232009-03-05 14:34:35 -080011040 if (app == mHomeProcess) {
11041 mHomeProcess = null;
11042 }
11043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 if (restart) {
11045 // We have components that still need to be running in the
11046 // process, so re-launch it.
11047 mProcessNames.put(app.processName, app.info.uid, app);
11048 startProcessLocked(app, "restart", app.processName);
11049 } else if (app.pid > 0 && app.pid != MY_PID) {
11050 // Goodbye!
11051 synchronized (mPidsSelfLocked) {
11052 mPidsSelfLocked.remove(app.pid);
11053 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
11054 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070011055 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056 }
11057 }
11058
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011059 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
11060 // Look through the content providers we are waiting to have launched,
11061 // and if any run in this process then either schedule a restart of
11062 // the process or kill the client waiting for it if this process has
11063 // gone bad.
11064 int NL = mLaunchingProviders.size();
11065 boolean restart = false;
11066 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011067 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080011068 if (cpr.launchingApp == app) {
11069 if (!alwaysBad && !app.bad) {
11070 restart = true;
11071 } else {
11072 removeDyingProviderLocked(app, cpr);
11073 NL = mLaunchingProviders.size();
11074 }
11075 }
11076 }
11077 return restart;
11078 }
11079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080 // =========================================================
11081 // SERVICES
11082 // =========================================================
11083
11084 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
11085 ActivityManager.RunningServiceInfo info =
11086 new ActivityManager.RunningServiceInfo();
11087 info.service = r.name;
11088 if (r.app != null) {
11089 info.pid = r.app.pid;
11090 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011091 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011092 info.process = r.processName;
11093 info.foreground = r.isForeground;
11094 info.activeSince = r.createTime;
11095 info.started = r.startRequested;
11096 info.clientCount = r.connections.size();
11097 info.crashCount = r.crashCount;
11098 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011099 if (r.isForeground) {
11100 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
11101 }
11102 if (r.startRequested) {
11103 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
11104 }
Dan Egnor42471dd2010-01-07 17:25:22 -080011105 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070011106 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
11107 }
11108 if (r.app != null && r.app.persistent) {
11109 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
11110 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011111 for (ConnectionRecord conn : r.connections.values()) {
11112 if (conn.clientLabel != 0) {
11113 info.clientPackage = conn.binding.client.info.packageName;
11114 info.clientLabel = conn.clientLabel;
11115 break;
11116 }
11117 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011118 return info;
11119 }
11120
11121 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
11122 int flags) {
11123 synchronized (this) {
11124 ArrayList<ActivityManager.RunningServiceInfo> res
11125 = new ArrayList<ActivityManager.RunningServiceInfo>();
11126
11127 if (mServices.size() > 0) {
11128 Iterator<ServiceRecord> it = mServices.values().iterator();
11129 while (it.hasNext() && res.size() < maxNum) {
11130 res.add(makeRunningServiceInfoLocked(it.next()));
11131 }
11132 }
11133
11134 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
11135 ServiceRecord r = mRestartingServices.get(i);
11136 ActivityManager.RunningServiceInfo info =
11137 makeRunningServiceInfoLocked(r);
11138 info.restarting = r.nextRestartTime;
11139 res.add(info);
11140 }
11141
11142 return res;
11143 }
11144 }
11145
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011146 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
11147 synchronized (this) {
11148 ServiceRecord r = mServices.get(name);
11149 if (r != null) {
11150 for (ConnectionRecord conn : r.connections.values()) {
11151 if (conn.clientIntent != null) {
11152 return conn.clientIntent;
11153 }
11154 }
11155 }
11156 }
11157 return null;
11158 }
11159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011160 private final ServiceRecord findServiceLocked(ComponentName name,
11161 IBinder token) {
11162 ServiceRecord r = mServices.get(name);
11163 return r == token ? r : null;
11164 }
11165
11166 private final class ServiceLookupResult {
11167 final ServiceRecord record;
11168 final String permission;
11169
11170 ServiceLookupResult(ServiceRecord _record, String _permission) {
11171 record = _record;
11172 permission = _permission;
11173 }
11174 };
11175
11176 private ServiceLookupResult findServiceLocked(Intent service,
11177 String resolvedType) {
11178 ServiceRecord r = null;
11179 if (service.getComponent() != null) {
11180 r = mServices.get(service.getComponent());
11181 }
11182 if (r == null) {
11183 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11184 r = mServicesByIntent.get(filter);
11185 }
11186
11187 if (r == null) {
11188 try {
11189 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011190 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011191 service, resolvedType, 0);
11192 ServiceInfo sInfo =
11193 rInfo != null ? rInfo.serviceInfo : null;
11194 if (sInfo == null) {
11195 return null;
11196 }
11197
11198 ComponentName name = new ComponentName(
11199 sInfo.applicationInfo.packageName, sInfo.name);
11200 r = mServices.get(name);
11201 } catch (RemoteException ex) {
11202 // pm is in same process, this will never happen.
11203 }
11204 }
11205 if (r != null) {
11206 int callingPid = Binder.getCallingPid();
11207 int callingUid = Binder.getCallingUid();
11208 if (checkComponentPermission(r.permission,
11209 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11210 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011211 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011212 + " from pid=" + callingPid
11213 + ", uid=" + callingUid
11214 + " requires " + r.permission);
11215 return new ServiceLookupResult(null, r.permission);
11216 }
11217 return new ServiceLookupResult(r, null);
11218 }
11219 return null;
11220 }
11221
11222 private class ServiceRestarter implements Runnable {
11223 private ServiceRecord mService;
11224
11225 void setService(ServiceRecord service) {
11226 mService = service;
11227 }
11228
11229 public void run() {
11230 synchronized(ActivityManagerService.this) {
11231 performServiceRestartLocked(mService);
11232 }
11233 }
11234 }
11235
11236 private ServiceLookupResult retrieveServiceLocked(Intent service,
11237 String resolvedType, int callingPid, int callingUid) {
11238 ServiceRecord r = null;
11239 if (service.getComponent() != null) {
11240 r = mServices.get(service.getComponent());
11241 }
11242 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11243 r = mServicesByIntent.get(filter);
11244 if (r == null) {
11245 try {
11246 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011247 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011248 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011249 ServiceInfo sInfo =
11250 rInfo != null ? rInfo.serviceInfo : null;
11251 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011252 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011253 ": not found");
11254 return null;
11255 }
11256
11257 ComponentName name = new ComponentName(
11258 sInfo.applicationInfo.packageName, sInfo.name);
11259 r = mServices.get(name);
11260 if (r == null) {
11261 filter = new Intent.FilterComparison(service.cloneFilter());
11262 ServiceRestarter res = new ServiceRestarter();
11263 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11264 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11265 synchronized (stats) {
11266 ss = stats.getServiceStatsLocked(
11267 sInfo.applicationInfo.uid, sInfo.packageName,
11268 sInfo.name);
11269 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080011270 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011271 res.setService(r);
11272 mServices.put(name, r);
11273 mServicesByIntent.put(filter, r);
11274
11275 // Make sure this component isn't in the pending list.
11276 int N = mPendingServices.size();
11277 for (int i=0; i<N; i++) {
11278 ServiceRecord pr = mPendingServices.get(i);
11279 if (pr.name.equals(name)) {
11280 mPendingServices.remove(i);
11281 i--;
11282 N--;
11283 }
11284 }
11285 }
11286 } catch (RemoteException ex) {
11287 // pm is in same process, this will never happen.
11288 }
11289 }
11290 if (r != null) {
11291 if (checkComponentPermission(r.permission,
11292 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11293 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011294 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 + " from pid=" + Binder.getCallingPid()
11296 + ", uid=" + Binder.getCallingUid()
11297 + " requires " + r.permission);
11298 return new ServiceLookupResult(null, r.permission);
11299 }
11300 return new ServiceLookupResult(r, null);
11301 }
11302 return null;
11303 }
11304
11305 private final void bumpServiceExecutingLocked(ServiceRecord r) {
11306 long now = SystemClock.uptimeMillis();
11307 if (r.executeNesting == 0 && r.app != null) {
11308 if (r.app.executingServices.size() == 0) {
11309 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11310 msg.obj = r.app;
11311 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
11312 }
11313 r.app.executingServices.add(r);
11314 }
11315 r.executeNesting++;
11316 r.executingStart = now;
11317 }
11318
11319 private final void sendServiceArgsLocked(ServiceRecord r,
11320 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011321 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011322 if (N == 0) {
11323 return;
11324 }
11325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011326 int i = 0;
11327 while (i < N) {
11328 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011329 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011330 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011331 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070011332 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011333 // If somehow we got a dummy start at the front, then
11334 // just drop it here.
11335 i++;
11336 continue;
11337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011338 bumpServiceExecutingLocked(r);
11339 if (!oomAdjusted) {
11340 oomAdjusted = true;
11341 updateOomAdjLocked(r.app);
11342 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011343 int flags = 0;
11344 if (si.deliveryCount > 0) {
11345 flags |= Service.START_FLAG_RETRY;
11346 }
11347 if (si.doneExecutingCount > 0) {
11348 flags |= Service.START_FLAG_REDELIVERY;
11349 }
11350 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
11351 si.deliveredTime = SystemClock.uptimeMillis();
11352 r.deliveredStarts.add(si);
11353 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011354 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011355 } catch (RemoteException e) {
11356 // Remote process gone... we'll let the normal cleanup take
11357 // care of this.
11358 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011359 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011360 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011361 break;
11362 }
11363 }
11364 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011365 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011366 } else {
11367 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011368 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011369 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 }
11371 }
11372 }
11373
11374 private final boolean requestServiceBindingLocked(ServiceRecord r,
11375 IntentBindRecord i, boolean rebind) {
11376 if (r.app == null || r.app.thread == null) {
11377 // If service is not currently running, can't yet bind.
11378 return false;
11379 }
11380 if ((!i.requested || rebind) && i.apps.size() > 0) {
11381 try {
11382 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011383 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011384 + ": shouldUnbind=" + i.hasBound);
11385 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11386 if (!rebind) {
11387 i.requested = true;
11388 }
11389 i.hasBound = true;
11390 i.doRebind = false;
11391 } catch (RemoteException e) {
11392 return false;
11393 }
11394 }
11395 return true;
11396 }
11397
11398 private final void requestServiceBindingsLocked(ServiceRecord r) {
11399 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11400 while (bindings.hasNext()) {
11401 IntentBindRecord i = bindings.next();
11402 if (!requestServiceBindingLocked(r, i, false)) {
11403 break;
11404 }
11405 }
11406 }
11407
11408 private final void realStartServiceLocked(ServiceRecord r,
11409 ProcessRecord app) throws RemoteException {
11410 if (app.thread == null) {
11411 throw new RemoteException();
11412 }
11413
11414 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011415 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011416
11417 app.services.add(r);
11418 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011419 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011420
11421 boolean created = false;
11422 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011423 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011424 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011425 mStringBuilder.setLength(0);
11426 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011427 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011428 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011429 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011430 synchronized (r.stats.getBatteryStats()) {
11431 r.stats.startLaunchedLocked();
11432 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011433 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011434 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011435 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 created = true;
11437 } finally {
11438 if (!created) {
11439 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011440 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011441 }
11442 }
11443
11444 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011445
11446 // If the service is in the started state, and there are no
11447 // pending arguments, then fake up one so its onStartCommand() will
11448 // be called.
11449 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11450 r.lastStartId++;
11451 if (r.lastStartId < 1) {
11452 r.lastStartId = 1;
11453 }
11454 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11455 }
11456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011457 sendServiceArgsLocked(r, true);
11458 }
11459
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011460 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11461 boolean allowCancel) {
11462 boolean canceled = false;
11463
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011464 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011465 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011466 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011467
11468 // Any delivered but not yet finished starts should be put back
11469 // on the pending list.
11470 final int N = r.deliveredStarts.size();
11471 if (N > 0) {
11472 for (int i=N-1; i>=0; i--) {
11473 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11474 if (si.intent == null) {
11475 // We'll generate this again if needed.
11476 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11477 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11478 r.pendingStarts.add(0, si);
11479 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11480 dur *= 2;
11481 if (minDuration < dur) minDuration = dur;
11482 if (resetTime < dur) resetTime = dur;
11483 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011484 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011485 + r.name);
11486 canceled = true;
11487 }
11488 }
11489 r.deliveredStarts.clear();
11490 }
11491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011492 r.totalRestartCount++;
11493 if (r.restartDelay == 0) {
11494 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011495 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011496 } else {
11497 // If it has been a "reasonably long time" since the service
11498 // was started, then reset our restart duration back to
11499 // the beginning, so we don't infinitely increase the duration
11500 // on a service that just occasionally gets killed (which is
11501 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011502 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011504 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011505 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011506 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011507 if (r.restartDelay < minDuration) {
11508 r.restartDelay = minDuration;
11509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011510 }
11511 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011512
11513 r.nextRestartTime = now + r.restartDelay;
11514
11515 // Make sure that we don't end up restarting a bunch of services
11516 // all at the same time.
11517 boolean repeat;
11518 do {
11519 repeat = false;
11520 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11521 ServiceRecord r2 = mRestartingServices.get(i);
11522 if (r2 != r && r.nextRestartTime
11523 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11524 && r.nextRestartTime
11525 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11526 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11527 r.restartDelay = r.nextRestartTime - now;
11528 repeat = true;
11529 break;
11530 }
11531 }
11532 } while (repeat);
11533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011534 if (!mRestartingServices.contains(r)) {
11535 mRestartingServices.add(r);
11536 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011537
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011538 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011540 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011541 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011542 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011543 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011544 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011545 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011546 r.shortName, r.restartDelay);
11547
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011548 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011549 }
11550
11551 final void performServiceRestartLocked(ServiceRecord r) {
11552 if (!mRestartingServices.contains(r)) {
11553 return;
11554 }
11555 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11556 }
11557
11558 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11559 if (r.restartDelay == 0) {
11560 return false;
11561 }
11562 r.resetRestartCounter();
11563 mRestartingServices.remove(r);
11564 mHandler.removeCallbacks(r.restarter);
11565 return true;
11566 }
11567
11568 private final boolean bringUpServiceLocked(ServiceRecord r,
11569 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011570 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011571 //r.dump(" ");
11572
Dianne Hackborn36124872009-10-08 16:22:03 -070011573 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011574 sendServiceArgsLocked(r, false);
11575 return true;
11576 }
11577
11578 if (!whileRestarting && r.restartDelay > 0) {
11579 // If waiting for a restart, then do nothing.
11580 return true;
11581 }
11582
Joe Onorato8a9b2202010-02-26 18:56:32 -080011583 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011584 + " " + r.intent);
11585
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011586 // We are now bringing the service up, so no longer in the
11587 // restarting state.
11588 mRestartingServices.remove(r);
11589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011590 final String appName = r.processName;
11591 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11592 if (app != null && app.thread != null) {
11593 try {
11594 realStartServiceLocked(r, app);
11595 return true;
11596 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011597 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 }
11599
11600 // If a dead object exception was thrown -- fall through to
11601 // restart the application.
11602 }
11603
Dianne Hackborn36124872009-10-08 16:22:03 -070011604 // Not running -- get it started, and enqueue this service record
11605 // to be executed when the app comes up.
11606 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11607 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011608 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011609 + r.appInfo.packageName + "/"
11610 + r.appInfo.uid + " for service "
11611 + r.intent.getIntent() + ": process is bad");
11612 bringDownServiceLocked(r, true);
11613 return false;
11614 }
11615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011617 mPendingServices.add(r);
11618 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620 return true;
11621 }
11622
11623 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011624 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011625 //r.dump(" ");
11626
11627 // Does it still need to run?
11628 if (!force && r.startRequested) {
11629 return;
11630 }
11631 if (r.connections.size() > 0) {
11632 if (!force) {
11633 // XXX should probably keep a count of the number of auto-create
11634 // connections directly in the service.
11635 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11636 while (it.hasNext()) {
11637 ConnectionRecord cr = it.next();
11638 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11639 return;
11640 }
11641 }
11642 }
11643
11644 // Report to all of the connections that the service is no longer
11645 // available.
11646 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11647 while (it.hasNext()) {
11648 ConnectionRecord c = it.next();
11649 try {
11650 // todo: shouldn't be a synchronous call!
11651 c.conn.connected(r.name, null);
11652 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011653 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011654 " to connection " + c.conn.asBinder() +
11655 " (in " + c.binding.client.processName + ")", e);
11656 }
11657 }
11658 }
11659
11660 // Tell the service that it has been unbound.
11661 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11662 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11663 while (it.hasNext()) {
11664 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011665 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666 + ": hasBound=" + ibr.hasBound);
11667 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11668 try {
11669 bumpServiceExecutingLocked(r);
11670 updateOomAdjLocked(r.app);
11671 ibr.hasBound = false;
11672 r.app.thread.scheduleUnbindService(r,
11673 ibr.intent.getIntent());
11674 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011675 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011676 + r.shortName, e);
11677 serviceDoneExecutingLocked(r, true);
11678 }
11679 }
11680 }
11681 }
11682
Joe Onorato8a9b2202010-02-26 18:56:32 -080011683 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011684 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011685 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011686 System.identityHashCode(r), r.shortName,
11687 (r.app != null) ? r.app.pid : -1);
11688
11689 mServices.remove(r.name);
11690 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011691 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011692 r.totalRestartCount = 0;
11693 unscheduleServiceRestartLocked(r);
11694
11695 // Also make sure it is not on the pending list.
11696 int N = mPendingServices.size();
11697 for (int i=0; i<N; i++) {
11698 if (mPendingServices.get(i) == r) {
11699 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011700 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011701 TAG, "Removed pending service: " + r.shortName);
11702 i--;
11703 N--;
11704 }
11705 }
11706
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011707 r.cancelNotification();
11708 r.isForeground = false;
11709 r.foregroundId = 0;
11710 r.foregroundNoti = null;
11711
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011712 // Clear start entries.
11713 r.deliveredStarts.clear();
11714 r.pendingStarts.clear();
11715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011716 if (r.app != null) {
11717 synchronized (r.stats.getBatteryStats()) {
11718 r.stats.stopLaunchedLocked();
11719 }
11720 r.app.services.remove(r);
11721 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011722 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011723 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011724 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011725 bumpServiceExecutingLocked(r);
11726 mStoppingServices.add(r);
11727 updateOomAdjLocked(r.app);
11728 r.app.thread.scheduleStopService(r);
11729 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011730 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731 + r.shortName, e);
11732 serviceDoneExecutingLocked(r, true);
11733 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011734 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011735 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011736 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011737 TAG, "Removed service that has no process: " + r.shortName);
11738 }
11739 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011740 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011741 TAG, "Removed service that is not running: " + r.shortName);
11742 }
11743 }
11744
11745 ComponentName startServiceLocked(IApplicationThread caller,
11746 Intent service, String resolvedType,
11747 int callingPid, int callingUid) {
11748 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011749 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011750 + " type=" + resolvedType + " args=" + service.getExtras());
11751
11752 if (caller != null) {
11753 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11754 if (callerApp == null) {
11755 throw new SecurityException(
11756 "Unable to find app for caller " + caller
11757 + " (pid=" + Binder.getCallingPid()
11758 + ") when starting service " + service);
11759 }
11760 }
11761
11762 ServiceLookupResult res =
11763 retrieveServiceLocked(service, resolvedType,
11764 callingPid, callingUid);
11765 if (res == null) {
11766 return null;
11767 }
11768 if (res.record == null) {
11769 return new ComponentName("!", res.permission != null
11770 ? res.permission : "private to package");
11771 }
11772 ServiceRecord r = res.record;
11773 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011774 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011775 + r.shortName);
11776 }
11777 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011778 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 r.lastStartId++;
11780 if (r.lastStartId < 1) {
11781 r.lastStartId = 1;
11782 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011783 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011784 r.lastActivity = SystemClock.uptimeMillis();
11785 synchronized (r.stats.getBatteryStats()) {
11786 r.stats.startRunningLocked();
11787 }
11788 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11789 return new ComponentName("!", "Service process is bad");
11790 }
11791 return r.name;
11792 }
11793 }
11794
11795 public ComponentName startService(IApplicationThread caller, Intent service,
11796 String resolvedType) {
11797 // Refuse possible leaked file descriptors
11798 if (service != null && service.hasFileDescriptors() == true) {
11799 throw new IllegalArgumentException("File descriptors passed in Intent");
11800 }
11801
11802 synchronized(this) {
11803 final int callingPid = Binder.getCallingPid();
11804 final int callingUid = Binder.getCallingUid();
11805 final long origId = Binder.clearCallingIdentity();
11806 ComponentName res = startServiceLocked(caller, service,
11807 resolvedType, callingPid, callingUid);
11808 Binder.restoreCallingIdentity(origId);
11809 return res;
11810 }
11811 }
11812
11813 ComponentName startServiceInPackage(int uid,
11814 Intent service, String resolvedType) {
11815 synchronized(this) {
11816 final long origId = Binder.clearCallingIdentity();
11817 ComponentName res = startServiceLocked(null, service,
11818 resolvedType, -1, uid);
11819 Binder.restoreCallingIdentity(origId);
11820 return res;
11821 }
11822 }
11823
11824 public int stopService(IApplicationThread caller, Intent service,
11825 String resolvedType) {
11826 // Refuse possible leaked file descriptors
11827 if (service != null && service.hasFileDescriptors() == true) {
11828 throw new IllegalArgumentException("File descriptors passed in Intent");
11829 }
11830
11831 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011832 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011833 + " type=" + resolvedType);
11834
11835 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11836 if (caller != null && callerApp == null) {
11837 throw new SecurityException(
11838 "Unable to find app for caller " + caller
11839 + " (pid=" + Binder.getCallingPid()
11840 + ") when stopping service " + service);
11841 }
11842
11843 // If this service is active, make sure it is stopped.
11844 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11845 if (r != null) {
11846 if (r.record != null) {
11847 synchronized (r.record.stats.getBatteryStats()) {
11848 r.record.stats.stopRunningLocked();
11849 }
11850 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011851 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011852 final long origId = Binder.clearCallingIdentity();
11853 bringDownServiceLocked(r.record, false);
11854 Binder.restoreCallingIdentity(origId);
11855 return 1;
11856 }
11857 return -1;
11858 }
11859 }
11860
11861 return 0;
11862 }
11863
11864 public IBinder peekService(Intent service, String resolvedType) {
11865 // Refuse possible leaked file descriptors
11866 if (service != null && service.hasFileDescriptors() == true) {
11867 throw new IllegalArgumentException("File descriptors passed in Intent");
11868 }
11869
11870 IBinder ret = null;
11871
11872 synchronized(this) {
11873 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11874
11875 if (r != null) {
11876 // r.record is null if findServiceLocked() failed the caller permission check
11877 if (r.record == null) {
11878 throw new SecurityException(
11879 "Permission Denial: Accessing service " + r.record.name
11880 + " from pid=" + Binder.getCallingPid()
11881 + ", uid=" + Binder.getCallingUid()
11882 + " requires " + r.permission);
11883 }
11884 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11885 if (ib != null) {
11886 ret = ib.binder;
11887 }
11888 }
11889 }
11890
11891 return ret;
11892 }
11893
11894 public boolean stopServiceToken(ComponentName className, IBinder token,
11895 int startId) {
11896 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011897 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011898 + " " + token + " startId=" + startId);
11899 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011900 if (r != null) {
11901 if (startId >= 0) {
11902 // Asked to only stop if done with all work. Note that
11903 // to avoid leaks, we will take this as dropping all
11904 // start items up to and including this one.
11905 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11906 if (si != null) {
11907 while (r.deliveredStarts.size() > 0) {
11908 if (r.deliveredStarts.remove(0) == si) {
11909 break;
11910 }
11911 }
11912 }
11913
11914 if (r.lastStartId != startId) {
11915 return false;
11916 }
11917
11918 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011919 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011920 + " is last, but have " + r.deliveredStarts.size()
11921 + " remaining args");
11922 }
11923 }
11924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011925 synchronized (r.stats.getBatteryStats()) {
11926 r.stats.stopRunningLocked();
11927 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011928 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011929 }
11930 final long origId = Binder.clearCallingIdentity();
11931 bringDownServiceLocked(r, false);
11932 Binder.restoreCallingIdentity(origId);
11933 return true;
11934 }
11935 }
11936 return false;
11937 }
11938
11939 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011940 int id, Notification notification, boolean removeNotification) {
11941 final long origId = Binder.clearCallingIdentity();
11942 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011943 synchronized(this) {
11944 ServiceRecord r = findServiceLocked(className, token);
11945 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011946 if (id != 0) {
11947 if (notification == null) {
11948 throw new IllegalArgumentException("null notification");
11949 }
11950 if (r.foregroundId != id) {
11951 r.cancelNotification();
11952 r.foregroundId = id;
11953 }
11954 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11955 r.foregroundNoti = notification;
11956 r.isForeground = true;
11957 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011958 if (r.app != null) {
11959 updateServiceForegroundLocked(r.app, true);
11960 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011961 } else {
11962 if (r.isForeground) {
11963 r.isForeground = false;
11964 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011965 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011966 updateServiceForegroundLocked(r.app, true);
11967 }
11968 }
11969 if (removeNotification) {
11970 r.cancelNotification();
11971 r.foregroundId = 0;
11972 r.foregroundNoti = null;
11973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011974 }
11975 }
11976 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011977 } finally {
11978 Binder.restoreCallingIdentity(origId);
11979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011980 }
11981
11982 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11983 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070011984 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011985 if (sr.isForeground) {
11986 anyForeground = true;
11987 break;
11988 }
11989 }
11990 if (anyForeground != proc.foregroundServices) {
11991 proc.foregroundServices = anyForeground;
11992 if (oomAdj) {
11993 updateOomAdjLocked();
11994 }
11995 }
11996 }
11997
11998 public int bindService(IApplicationThread caller, IBinder token,
11999 Intent service, String resolvedType,
12000 IServiceConnection connection, int flags) {
12001 // Refuse possible leaked file descriptors
12002 if (service != null && service.hasFileDescriptors() == true) {
12003 throw new IllegalArgumentException("File descriptors passed in Intent");
12004 }
12005
12006 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012007 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012008 + " type=" + resolvedType + " conn=" + connection.asBinder()
12009 + " flags=0x" + Integer.toHexString(flags));
12010 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12011 if (callerApp == null) {
12012 throw new SecurityException(
12013 "Unable to find app for caller " + caller
12014 + " (pid=" + Binder.getCallingPid()
12015 + ") when binding service " + service);
12016 }
12017
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012018 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012019 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070012020 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012021 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012022 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012023 return 0;
12024 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012025 activity = (ActivityRecord)mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012026 }
12027
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012028 int clientLabel = 0;
12029 PendingIntent clientIntent = null;
12030
12031 if (callerApp.info.uid == Process.SYSTEM_UID) {
12032 // Hacky kind of thing -- allow system stuff to tell us
12033 // what they are, so we can report this elsewhere for
12034 // others to know why certain services are running.
12035 try {
12036 clientIntent = (PendingIntent)service.getParcelableExtra(
12037 Intent.EXTRA_CLIENT_INTENT);
12038 } catch (RuntimeException e) {
12039 }
12040 if (clientIntent != null) {
12041 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
12042 if (clientLabel != 0) {
12043 // There are no useful extras in the intent, trash them.
12044 // System code calling with this stuff just needs to know
12045 // this will happen.
12046 service = service.cloneFilter();
12047 }
12048 }
12049 }
12050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012051 ServiceLookupResult res =
12052 retrieveServiceLocked(service, resolvedType,
12053 Binder.getCallingPid(), Binder.getCallingUid());
12054 if (res == null) {
12055 return 0;
12056 }
12057 if (res.record == null) {
12058 return -1;
12059 }
12060 ServiceRecord s = res.record;
12061
12062 final long origId = Binder.clearCallingIdentity();
12063
12064 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012065 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012066 + s.shortName);
12067 }
12068
12069 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
12070 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012071 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012072
12073 IBinder binder = connection.asBinder();
12074 s.connections.put(binder, c);
12075 b.connections.add(c);
12076 if (activity != null) {
12077 if (activity.connections == null) {
12078 activity.connections = new HashSet<ConnectionRecord>();
12079 }
12080 activity.connections.add(c);
12081 }
12082 b.client.connections.add(c);
12083 mServiceConnections.put(binder, c);
12084
12085 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
12086 s.lastActivity = SystemClock.uptimeMillis();
12087 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
12088 return 0;
12089 }
12090 }
12091
12092 if (s.app != null) {
12093 // This could have made the service more important.
12094 updateOomAdjLocked(s.app);
12095 }
12096
Joe Onorato8a9b2202010-02-26 18:56:32 -080012097 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012098 + ": received=" + b.intent.received
12099 + " apps=" + b.intent.apps.size()
12100 + " doRebind=" + b.intent.doRebind);
12101
12102 if (s.app != null && b.intent.received) {
12103 // Service is already running, so we can immediately
12104 // publish the connection.
12105 try {
12106 c.conn.connected(s.name, b.intent.binder);
12107 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012108 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012109 + " to connection " + c.conn.asBinder()
12110 + " (in " + c.binding.client.processName + ")", e);
12111 }
12112
12113 // If this is the first app connected back to this binding,
12114 // and the service had previously asked to be told when
12115 // rebound, then do so.
12116 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
12117 requestServiceBindingLocked(s, b.intent, true);
12118 }
12119 } else if (!b.intent.requested) {
12120 requestServiceBindingLocked(s, b.intent, false);
12121 }
12122
12123 Binder.restoreCallingIdentity(origId);
12124 }
12125
12126 return 1;
12127 }
12128
12129 private void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012130 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012131 IBinder binder = c.conn.asBinder();
12132 AppBindRecord b = c.binding;
12133 ServiceRecord s = b.service;
12134 s.connections.remove(binder);
12135 b.connections.remove(c);
12136 if (c.activity != null && c.activity != skipAct) {
12137 if (c.activity.connections != null) {
12138 c.activity.connections.remove(c);
12139 }
12140 }
12141 if (b.client != skipApp) {
12142 b.client.connections.remove(c);
12143 }
12144 mServiceConnections.remove(binder);
12145
12146 if (b.connections.size() == 0) {
12147 b.intent.apps.remove(b.client);
12148 }
12149
Joe Onorato8a9b2202010-02-26 18:56:32 -080012150 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012151 + ": shouldUnbind=" + b.intent.hasBound);
12152 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
12153 && b.intent.hasBound) {
12154 try {
12155 bumpServiceExecutingLocked(s);
12156 updateOomAdjLocked(s.app);
12157 b.intent.hasBound = false;
12158 // Assume the client doesn't want to know about a rebind;
12159 // we will deal with that later if it asks for one.
12160 b.intent.doRebind = false;
12161 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
12162 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012163 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012164 serviceDoneExecutingLocked(s, true);
12165 }
12166 }
12167
12168 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
12169 bringDownServiceLocked(s, false);
12170 }
12171 }
12172
12173 public boolean unbindService(IServiceConnection connection) {
12174 synchronized (this) {
12175 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012176 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012177 ConnectionRecord r = mServiceConnections.get(binder);
12178 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012179 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012180 + connection.asBinder());
12181 return false;
12182 }
12183
12184 final long origId = Binder.clearCallingIdentity();
12185
12186 removeConnectionLocked(r, null, null);
12187
12188 if (r.binding.service.app != null) {
12189 // This could have made the service less important.
12190 updateOomAdjLocked(r.binding.service.app);
12191 }
12192
12193 Binder.restoreCallingIdentity(origId);
12194 }
12195
12196 return true;
12197 }
12198
12199 public void publishService(IBinder token, Intent intent, IBinder service) {
12200 // Refuse possible leaked file descriptors
12201 if (intent != null && intent.hasFileDescriptors() == true) {
12202 throw new IllegalArgumentException("File descriptors passed in Intent");
12203 }
12204
12205 synchronized(this) {
12206 if (!(token instanceof ServiceRecord)) {
12207 throw new IllegalArgumentException("Invalid service token");
12208 }
12209 ServiceRecord r = (ServiceRecord)token;
12210
12211 final long origId = Binder.clearCallingIdentity();
12212
Joe Onorato8a9b2202010-02-26 18:56:32 -080012213 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012214 + " " + intent + ": " + service);
12215 if (r != null) {
12216 Intent.FilterComparison filter
12217 = new Intent.FilterComparison(intent);
12218 IntentBindRecord b = r.bindings.get(filter);
12219 if (b != null && !b.received) {
12220 b.binder = service;
12221 b.requested = true;
12222 b.received = true;
12223 if (r.connections.size() > 0) {
12224 Iterator<ConnectionRecord> it
12225 = r.connections.values().iterator();
12226 while (it.hasNext()) {
12227 ConnectionRecord c = it.next();
12228 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012229 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012230 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012231 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012232 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012233 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012234 TAG, "Published intent: " + intent);
12235 continue;
12236 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012237 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012238 try {
12239 c.conn.connected(r.name, service);
12240 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012241 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012242 " to connection " + c.conn.asBinder() +
12243 " (in " + c.binding.client.processName + ")", e);
12244 }
12245 }
12246 }
12247 }
12248
12249 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12250
12251 Binder.restoreCallingIdentity(origId);
12252 }
12253 }
12254 }
12255
12256 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
12257 // Refuse possible leaked file descriptors
12258 if (intent != null && intent.hasFileDescriptors() == true) {
12259 throw new IllegalArgumentException("File descriptors passed in Intent");
12260 }
12261
12262 synchronized(this) {
12263 if (!(token instanceof ServiceRecord)) {
12264 throw new IllegalArgumentException("Invalid service token");
12265 }
12266 ServiceRecord r = (ServiceRecord)token;
12267
12268 final long origId = Binder.clearCallingIdentity();
12269
12270 if (r != null) {
12271 Intent.FilterComparison filter
12272 = new Intent.FilterComparison(intent);
12273 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012274 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012275 + " at " + b + ": apps="
12276 + (b != null ? b.apps.size() : 0));
12277 if (b != null) {
12278 if (b.apps.size() > 0) {
12279 // Applications have already bound since the last
12280 // unbind, so just rebind right here.
12281 requestServiceBindingLocked(r, b, true);
12282 } else {
12283 // Note to tell the service the next time there is
12284 // a new client.
12285 b.doRebind = true;
12286 }
12287 }
12288
12289 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12290
12291 Binder.restoreCallingIdentity(origId);
12292 }
12293 }
12294 }
12295
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012296 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012297 synchronized(this) {
12298 if (!(token instanceof ServiceRecord)) {
12299 throw new IllegalArgumentException("Invalid service token");
12300 }
12301 ServiceRecord r = (ServiceRecord)token;
12302 boolean inStopping = mStoppingServices.contains(token);
12303 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012304 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012305 + ": nesting=" + r.executeNesting
12306 + ", inStopping=" + inStopping);
12307 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012308 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012309 + " with incorrect token: given " + token
12310 + ", expected " + r);
12311 return;
12312 }
12313
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012314 if (type == 1) {
12315 // This is a call from a service start... take care of
12316 // book-keeping.
12317 r.callStart = true;
12318 switch (res) {
12319 case Service.START_STICKY_COMPATIBILITY:
12320 case Service.START_STICKY: {
12321 // We are done with the associated start arguments.
12322 r.findDeliveredStart(startId, true);
12323 // Don't stop if killed.
12324 r.stopIfKilled = false;
12325 break;
12326 }
12327 case Service.START_NOT_STICKY: {
12328 // We are done with the associated start arguments.
12329 r.findDeliveredStart(startId, true);
12330 if (r.lastStartId == startId) {
12331 // There is no more work, and this service
12332 // doesn't want to hang around if killed.
12333 r.stopIfKilled = true;
12334 }
12335 break;
12336 }
12337 case Service.START_REDELIVER_INTENT: {
12338 // We'll keep this item until they explicitly
12339 // call stop for it, but keep track of the fact
12340 // that it was delivered.
12341 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12342 if (si != null) {
12343 si.deliveryCount = 0;
12344 si.doneExecutingCount++;
12345 // Don't stop if killed.
12346 r.stopIfKilled = true;
12347 }
12348 break;
12349 }
12350 default:
12351 throw new IllegalArgumentException(
12352 "Unknown service start result: " + res);
12353 }
12354 if (res == Service.START_STICKY_COMPATIBILITY) {
12355 r.callStart = false;
12356 }
12357 }
12358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012359 final long origId = Binder.clearCallingIdentity();
12360 serviceDoneExecutingLocked(r, inStopping);
12361 Binder.restoreCallingIdentity(origId);
12362 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012363 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012364 + " with token " + token);
12365 }
12366 }
12367 }
12368
12369 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
12370 r.executeNesting--;
12371 if (r.executeNesting <= 0 && r.app != null) {
12372 r.app.executingServices.remove(r);
12373 if (r.app.executingServices.size() == 0) {
12374 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
12375 }
12376 if (inStopping) {
12377 mStoppingServices.remove(r);
12378 }
12379 updateOomAdjLocked(r.app);
12380 }
12381 }
12382
12383 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012384 String anrMessage = null;
12385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012386 synchronized(this) {
12387 if (proc.executingServices.size() == 0 || proc.thread == null) {
12388 return;
12389 }
12390 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12391 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12392 ServiceRecord timeout = null;
12393 long nextTime = 0;
12394 while (it.hasNext()) {
12395 ServiceRecord sr = it.next();
12396 if (sr.executingStart < maxTime) {
12397 timeout = sr;
12398 break;
12399 }
12400 if (sr.executingStart > nextTime) {
12401 nextTime = sr.executingStart;
12402 }
12403 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012404 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012405 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012406 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012407 } else {
12408 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12409 msg.obj = proc;
12410 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12411 }
12412 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012413
12414 if (anrMessage != null) {
12415 appNotResponding(proc, null, null, anrMessage);
12416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012417 }
12418
12419 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012420 // BACKUP AND RESTORE
12421 // =========================================================
12422
12423 // Cause the target app to be launched if necessary and its backup agent
12424 // instantiated. The backup agent will invoke backupAgentCreated() on the
12425 // activity manager to announce its creation.
12426 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012427 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012428 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12429
12430 synchronized(this) {
12431 // !!! TODO: currently no check here that we're already bound
12432 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12433 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12434 synchronized (stats) {
12435 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12436 }
12437
12438 BackupRecord r = new BackupRecord(ss, app, backupMode);
12439 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12440 // startProcessLocked() returns existing proc's record if it's already running
12441 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012442 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012443 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012444 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012445 return false;
12446 }
12447
12448 r.app = proc;
12449 mBackupTarget = r;
12450 mBackupAppName = app.packageName;
12451
Christopher Tate6fa95972009-06-05 18:43:55 -070012452 // Try not to kill the process during backup
12453 updateOomAdjLocked(proc);
12454
Christopher Tate181fafa2009-05-14 11:12:14 -070012455 // If the process is already attached, schedule the creation of the backup agent now.
12456 // If it is not yet live, this will be done when it attaches to the framework.
12457 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012458 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012459 try {
12460 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12461 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012462 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012463 }
12464 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012465 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012466 }
12467 // Invariants: at this point, the target app process exists and the application
12468 // is either already running or in the process of coming up. mBackupTarget and
12469 // mBackupAppName describe the app, so that when it binds back to the AM we
12470 // know that it's scheduled for a backup-agent operation.
12471 }
12472
12473 return true;
12474 }
12475
12476 // A backup agent has just come up
12477 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012478 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012479 + " = " + agent);
12480
12481 synchronized(this) {
12482 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012483 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012484 return;
12485 }
12486
Christopher Tate043dadc2009-06-02 16:11:00 -070012487 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012488 try {
12489 IBackupManager bm = IBackupManager.Stub.asInterface(
12490 ServiceManager.getService(Context.BACKUP_SERVICE));
12491 bm.agentConnected(agentPackageName, agent);
12492 } catch (RemoteException e) {
12493 // can't happen; the backup manager service is local
12494 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012495 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012496 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012497 } finally {
12498 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012499 }
12500 }
12501 }
12502
12503 // done with this agent
12504 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012505 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012506 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012507 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012508 return;
12509 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012510
12511 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012512 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012513 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012514 return;
12515 }
12516
Christopher Tate181fafa2009-05-14 11:12:14 -070012517 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012518 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012519 return;
12520 }
12521
Christopher Tate6fa95972009-06-05 18:43:55 -070012522 ProcessRecord proc = mBackupTarget.app;
12523 mBackupTarget = null;
12524 mBackupAppName = null;
12525
12526 // Not backing this app up any more; reset its OOM adjustment
12527 updateOomAdjLocked(proc);
12528
Christopher Tatec7b31e32009-06-10 15:49:30 -070012529 // If the app crashed during backup, 'thread' will be null here
12530 if (proc.thread != null) {
12531 try {
12532 proc.thread.scheduleDestroyBackupAgent(appInfo);
12533 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012534 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012535 e.printStackTrace();
12536 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012537 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012538 }
12539 }
12540 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012541 // BROADCASTS
12542 // =========================================================
12543
Josh Bartel7f208742010-02-25 11:01:44 -060012544 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012545 List cur) {
12546 final ContentResolver resolver = mContext.getContentResolver();
12547 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12548 if (list == null) {
12549 return cur;
12550 }
12551 int N = list.size();
12552 for (int i=0; i<N; i++) {
12553 Intent intent = list.get(i);
12554 if (filter.match(resolver, intent, true, TAG) >= 0) {
12555 if (cur == null) {
12556 cur = new ArrayList<Intent>();
12557 }
12558 cur.add(intent);
12559 }
12560 }
12561 return cur;
12562 }
12563
12564 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012565 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012566 + mBroadcastsScheduled);
12567
12568 if (mBroadcastsScheduled) {
12569 return;
12570 }
12571 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12572 mBroadcastsScheduled = true;
12573 }
12574
12575 public Intent registerReceiver(IApplicationThread caller,
12576 IIntentReceiver receiver, IntentFilter filter, String permission) {
12577 synchronized(this) {
12578 ProcessRecord callerApp = null;
12579 if (caller != null) {
12580 callerApp = getRecordForAppLocked(caller);
12581 if (callerApp == null) {
12582 throw new SecurityException(
12583 "Unable to find app for caller " + caller
12584 + " (pid=" + Binder.getCallingPid()
12585 + ") when registering receiver " + receiver);
12586 }
12587 }
12588
12589 List allSticky = null;
12590
12591 // Look for any matching sticky broadcasts...
12592 Iterator actions = filter.actionsIterator();
12593 if (actions != null) {
12594 while (actions.hasNext()) {
12595 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012596 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012597 }
12598 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012599 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012600 }
12601
12602 // The first sticky in the list is returned directly back to
12603 // the client.
12604 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12605
Joe Onorato8a9b2202010-02-26 18:56:32 -080012606 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012607 + ": " + sticky);
12608
12609 if (receiver == null) {
12610 return sticky;
12611 }
12612
12613 ReceiverList rl
12614 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12615 if (rl == null) {
12616 rl = new ReceiverList(this, callerApp,
12617 Binder.getCallingPid(),
12618 Binder.getCallingUid(), receiver);
12619 if (rl.app != null) {
12620 rl.app.receivers.add(rl);
12621 } else {
12622 try {
12623 receiver.asBinder().linkToDeath(rl, 0);
12624 } catch (RemoteException e) {
12625 return sticky;
12626 }
12627 rl.linkedToDeath = true;
12628 }
12629 mRegisteredReceivers.put(receiver.asBinder(), rl);
12630 }
12631 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12632 rl.add(bf);
12633 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012634 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012635 }
12636 mReceiverResolver.addFilter(bf);
12637
12638 // Enqueue broadcasts for all existing stickies that match
12639 // this filter.
12640 if (allSticky != null) {
12641 ArrayList receivers = new ArrayList();
12642 receivers.add(bf);
12643
12644 int N = allSticky.size();
12645 for (int i=0; i<N; i++) {
12646 Intent intent = (Intent)allSticky.get(i);
12647 BroadcastRecord r = new BroadcastRecord(intent, null,
12648 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012649 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012650 if (mParallelBroadcasts.size() == 0) {
12651 scheduleBroadcastsLocked();
12652 }
12653 mParallelBroadcasts.add(r);
12654 }
12655 }
12656
12657 return sticky;
12658 }
12659 }
12660
12661 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012662 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012663
12664 boolean doNext = false;
12665
12666 synchronized(this) {
12667 ReceiverList rl
12668 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12669 if (rl != null) {
12670 if (rl.curBroadcast != null) {
12671 BroadcastRecord r = rl.curBroadcast;
12672 doNext = finishReceiverLocked(
12673 receiver.asBinder(), r.resultCode, r.resultData,
12674 r.resultExtras, r.resultAbort, true);
12675 }
12676
12677 if (rl.app != null) {
12678 rl.app.receivers.remove(rl);
12679 }
12680 removeReceiverLocked(rl);
12681 if (rl.linkedToDeath) {
12682 rl.linkedToDeath = false;
12683 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12684 }
12685 }
12686 }
12687
12688 if (!doNext) {
12689 return;
12690 }
12691
12692 final long origId = Binder.clearCallingIdentity();
12693 processNextBroadcast(false);
12694 trimApplications();
12695 Binder.restoreCallingIdentity(origId);
12696 }
12697
12698 void removeReceiverLocked(ReceiverList rl) {
12699 mRegisteredReceivers.remove(rl.receiver.asBinder());
12700 int N = rl.size();
12701 for (int i=0; i<N; i++) {
12702 mReceiverResolver.removeFilter(rl.get(i));
12703 }
12704 }
12705
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012706 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12707 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12708 ProcessRecord r = mLruProcesses.get(i);
12709 if (r.thread != null) {
12710 try {
12711 r.thread.dispatchPackageBroadcast(cmd, packages);
12712 } catch (RemoteException ex) {
12713 }
12714 }
12715 }
12716 }
12717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012718 private final int broadcastIntentLocked(ProcessRecord callerApp,
12719 String callerPackage, Intent intent, String resolvedType,
12720 IIntentReceiver resultTo, int resultCode, String resultData,
12721 Bundle map, String requiredPermission,
12722 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12723 intent = new Intent(intent);
12724
Joe Onorato8a9b2202010-02-26 18:56:32 -080012725 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012726 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12727 + " ordered=" + ordered);
12728 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012729 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012730 }
12731
12732 // Handle special intents: if this broadcast is from the package
12733 // manager about a package being removed, we need to remove all of
12734 // its activities from the history stack.
12735 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12736 intent.getAction());
12737 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12738 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012739 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012740 || uidRemoved) {
12741 if (checkComponentPermission(
12742 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12743 callingPid, callingUid, -1)
12744 == PackageManager.PERMISSION_GRANTED) {
12745 if (uidRemoved) {
12746 final Bundle intentExtras = intent.getExtras();
12747 final int uid = intentExtras != null
12748 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12749 if (uid >= 0) {
12750 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12751 synchronized (bs) {
12752 bs.removeUidStatsLocked(uid);
12753 }
12754 }
12755 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012756 // If resources are unvailble just force stop all
12757 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012758 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012759 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12760 if (list != null && (list.length > 0)) {
12761 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012762 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012763 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012764 sendPackageBroadcastLocked(
12765 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012766 }
12767 } else {
12768 Uri data = intent.getData();
12769 String ssp;
12770 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12771 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12772 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012773 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012774 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012775 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
12776 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12777 new String[] {ssp});
12778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012779 }
12780 }
12781 }
12782 } else {
12783 String msg = "Permission Denial: " + intent.getAction()
12784 + " broadcast from " + callerPackage + " (pid=" + callingPid
12785 + ", uid=" + callingUid + ")"
12786 + " requires "
12787 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012788 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012789 throw new SecurityException(msg);
12790 }
12791 }
12792
12793 /*
12794 * If this is the time zone changed action, queue up a message that will reset the timezone
12795 * of all currently running processes. This message will get queued up before the broadcast
12796 * happens.
12797 */
12798 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12799 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12800 }
12801
Dianne Hackborn854060af2009-07-09 18:14:31 -070012802 /*
12803 * Prevent non-system code (defined here to be non-persistent
12804 * processes) from sending protected broadcasts.
12805 */
12806 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12807 || callingUid == Process.SHELL_UID || callingUid == 0) {
12808 // Always okay.
12809 } else if (callerApp == null || !callerApp.persistent) {
12810 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012811 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070012812 intent.getAction())) {
12813 String msg = "Permission Denial: not allowed to send broadcast "
12814 + intent.getAction() + " from pid="
12815 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012816 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012817 throw new SecurityException(msg);
12818 }
12819 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012820 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012821 return BROADCAST_SUCCESS;
12822 }
12823 }
12824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012825 // Add to the sticky list if requested.
12826 if (sticky) {
12827 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12828 callingPid, callingUid)
12829 != PackageManager.PERMISSION_GRANTED) {
12830 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12831 + callingPid + ", uid=" + callingUid
12832 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012833 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012834 throw new SecurityException(msg);
12835 }
12836 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012837 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012838 + " and enforce permission " + requiredPermission);
12839 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12840 }
12841 if (intent.getComponent() != null) {
12842 throw new SecurityException(
12843 "Sticky broadcasts can't target a specific component");
12844 }
12845 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12846 if (list == null) {
12847 list = new ArrayList<Intent>();
12848 mStickyBroadcasts.put(intent.getAction(), list);
12849 }
12850 int N = list.size();
12851 int i;
12852 for (i=0; i<N; i++) {
12853 if (intent.filterEquals(list.get(i))) {
12854 // This sticky already exists, replace it.
12855 list.set(i, new Intent(intent));
12856 break;
12857 }
12858 }
12859 if (i >= N) {
12860 list.add(new Intent(intent));
12861 }
12862 }
12863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012864 // Figure out who all will receive this broadcast.
12865 List receivers = null;
12866 List<BroadcastFilter> registeredReceivers = null;
12867 try {
12868 if (intent.getComponent() != null) {
12869 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012870 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012871 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012872 if (ai != null) {
12873 receivers = new ArrayList();
12874 ResolveInfo ri = new ResolveInfo();
12875 ri.activityInfo = ai;
12876 receivers.add(ri);
12877 }
12878 } else {
12879 // Need to resolve the intent to interested receivers...
12880 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12881 == 0) {
12882 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012883 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012884 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012885 }
Mihai Preda074edef2009-05-18 17:13:31 +020012886 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012887 }
12888 } catch (RemoteException ex) {
12889 // pm is in same process, this will never happen.
12890 }
12891
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012892 final boolean replacePending =
12893 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12894
Joe Onorato8a9b2202010-02-26 18:56:32 -080012895 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012896 + " replacePending=" + replacePending);
12897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012898 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12899 if (!ordered && NR > 0) {
12900 // If we are not serializing this broadcast, then send the
12901 // registered receivers separately so they don't wait for the
12902 // components to be launched.
12903 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12904 callerPackage, callingPid, callingUid, requiredPermission,
12905 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012906 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012907 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012908 TAG, "Enqueueing parallel broadcast " + r
12909 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012910 boolean replaced = false;
12911 if (replacePending) {
12912 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12913 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012914 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012915 "***** DROPPING PARALLEL: " + intent);
12916 mParallelBroadcasts.set(i, r);
12917 replaced = true;
12918 break;
12919 }
12920 }
12921 }
12922 if (!replaced) {
12923 mParallelBroadcasts.add(r);
12924 scheduleBroadcastsLocked();
12925 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012926 registeredReceivers = null;
12927 NR = 0;
12928 }
12929
12930 // Merge into one list.
12931 int ir = 0;
12932 if (receivers != null) {
12933 // A special case for PACKAGE_ADDED: do not allow the package
12934 // being added to see this broadcast. This prevents them from
12935 // using this as a back door to get run as soon as they are
12936 // installed. Maybe in the future we want to have a special install
12937 // broadcast or such for apps, but we'd like to deliberately make
12938 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012939 String skipPackages[] = null;
12940 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12941 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12942 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12943 Uri data = intent.getData();
12944 if (data != null) {
12945 String pkgName = data.getSchemeSpecificPart();
12946 if (pkgName != null) {
12947 skipPackages = new String[] { pkgName };
12948 }
12949 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012950 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012951 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012952 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012953 if (skipPackages != null && (skipPackages.length > 0)) {
12954 for (String skipPackage : skipPackages) {
12955 if (skipPackage != null) {
12956 int NT = receivers.size();
12957 for (int it=0; it<NT; it++) {
12958 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12959 if (curt.activityInfo.packageName.equals(skipPackage)) {
12960 receivers.remove(it);
12961 it--;
12962 NT--;
12963 }
12964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012965 }
12966 }
12967 }
12968
12969 int NT = receivers != null ? receivers.size() : 0;
12970 int it = 0;
12971 ResolveInfo curt = null;
12972 BroadcastFilter curr = null;
12973 while (it < NT && ir < NR) {
12974 if (curt == null) {
12975 curt = (ResolveInfo)receivers.get(it);
12976 }
12977 if (curr == null) {
12978 curr = registeredReceivers.get(ir);
12979 }
12980 if (curr.getPriority() >= curt.priority) {
12981 // Insert this broadcast record into the final list.
12982 receivers.add(it, curr);
12983 ir++;
12984 curr = null;
12985 it++;
12986 NT++;
12987 } else {
12988 // Skip to the next ResolveInfo in the final list.
12989 it++;
12990 curt = null;
12991 }
12992 }
12993 }
12994 while (ir < NR) {
12995 if (receivers == null) {
12996 receivers = new ArrayList();
12997 }
12998 receivers.add(registeredReceivers.get(ir));
12999 ir++;
13000 }
13001
13002 if ((receivers != null && receivers.size() > 0)
13003 || resultTo != null) {
13004 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
13005 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013006 receivers, resultTo, resultCode, resultData, map, ordered,
13007 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013008 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013009 TAG, "Enqueueing ordered broadcast " + r
13010 + ": prev had " + mOrderedBroadcasts.size());
13011 if (DEBUG_BROADCAST) {
13012 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013013 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013014 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013015 boolean replaced = false;
13016 if (replacePending) {
13017 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
13018 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013019 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013020 "***** DROPPING ORDERED: " + intent);
13021 mOrderedBroadcasts.set(i, r);
13022 replaced = true;
13023 break;
13024 }
13025 }
13026 }
13027 if (!replaced) {
13028 mOrderedBroadcasts.add(r);
13029 scheduleBroadcastsLocked();
13030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013031 }
13032
13033 return BROADCAST_SUCCESS;
13034 }
13035
13036 public final int broadcastIntent(IApplicationThread caller,
13037 Intent intent, String resolvedType, IIntentReceiver resultTo,
13038 int resultCode, String resultData, Bundle map,
13039 String requiredPermission, boolean serialized, boolean sticky) {
13040 // Refuse possible leaked file descriptors
13041 if (intent != null && intent.hasFileDescriptors() == true) {
13042 throw new IllegalArgumentException("File descriptors passed in Intent");
13043 }
13044
13045 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013046 int flags = intent.getFlags();
13047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013048 if (!mSystemReady) {
13049 // if the caller really truly claims to know what they're doing, go
13050 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013051 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
13052 intent = new Intent(intent);
13053 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
13054 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080013055 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013056 + " before boot completion");
13057 throw new IllegalStateException("Cannot broadcast before boot completed");
13058 }
13059 }
13060
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013061 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
13062 throw new IllegalArgumentException(
13063 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
13064 }
13065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013066 final ProcessRecord callerApp = getRecordForAppLocked(caller);
13067 final int callingPid = Binder.getCallingPid();
13068 final int callingUid = Binder.getCallingUid();
13069 final long origId = Binder.clearCallingIdentity();
13070 int res = broadcastIntentLocked(callerApp,
13071 callerApp != null ? callerApp.info.packageName : null,
13072 intent, resolvedType, resultTo,
13073 resultCode, resultData, map, requiredPermission, serialized,
13074 sticky, callingPid, callingUid);
13075 Binder.restoreCallingIdentity(origId);
13076 return res;
13077 }
13078 }
13079
13080 int broadcastIntentInPackage(String packageName, int uid,
13081 Intent intent, String resolvedType, IIntentReceiver resultTo,
13082 int resultCode, String resultData, Bundle map,
13083 String requiredPermission, boolean serialized, boolean sticky) {
13084 synchronized(this) {
13085 final long origId = Binder.clearCallingIdentity();
13086 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
13087 resultTo, resultCode, resultData, map, requiredPermission,
13088 serialized, sticky, -1, uid);
13089 Binder.restoreCallingIdentity(origId);
13090 return res;
13091 }
13092 }
13093
13094 public final void unbroadcastIntent(IApplicationThread caller,
13095 Intent intent) {
13096 // Refuse possible leaked file descriptors
13097 if (intent != null && intent.hasFileDescriptors() == true) {
13098 throw new IllegalArgumentException("File descriptors passed in Intent");
13099 }
13100
13101 synchronized(this) {
13102 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
13103 != PackageManager.PERMISSION_GRANTED) {
13104 String msg = "Permission Denial: unbroadcastIntent() from pid="
13105 + Binder.getCallingPid()
13106 + ", uid=" + Binder.getCallingUid()
13107 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013108 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013109 throw new SecurityException(msg);
13110 }
13111 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
13112 if (list != null) {
13113 int N = list.size();
13114 int i;
13115 for (i=0; i<N; i++) {
13116 if (intent.filterEquals(list.get(i))) {
13117 list.remove(i);
13118 break;
13119 }
13120 }
13121 }
13122 }
13123 }
13124
13125 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
13126 String resultData, Bundle resultExtras, boolean resultAbort,
13127 boolean explicit) {
13128 if (mOrderedBroadcasts.size() == 0) {
13129 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013130 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013131 }
13132 return false;
13133 }
13134 BroadcastRecord r = mOrderedBroadcasts.get(0);
13135 if (r.receiver == null) {
13136 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013137 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013138 }
13139 return false;
13140 }
13141 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013142 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013143 return false;
13144 }
13145 int state = r.state;
13146 r.state = r.IDLE;
13147 if (state == r.IDLE) {
13148 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013149 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013150 }
13151 }
13152 r.receiver = null;
13153 r.intent.setComponent(null);
13154 if (r.curApp != null) {
13155 r.curApp.curReceiver = null;
13156 }
13157 if (r.curFilter != null) {
13158 r.curFilter.receiverList.curBroadcast = null;
13159 }
13160 r.curFilter = null;
13161 r.curApp = null;
13162 r.curComponent = null;
13163 r.curReceiver = null;
13164 mPendingBroadcast = null;
13165
13166 r.resultCode = resultCode;
13167 r.resultData = resultData;
13168 r.resultExtras = resultExtras;
13169 r.resultAbort = resultAbort;
13170
13171 // We will process the next receiver right now if this is finishing
13172 // an app receiver (which is always asynchronous) or after we have
13173 // come back from calling a receiver.
13174 return state == BroadcastRecord.APP_RECEIVE
13175 || state == BroadcastRecord.CALL_DONE_RECEIVE;
13176 }
13177
13178 public void finishReceiver(IBinder who, int resultCode, String resultData,
13179 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013180 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013181
13182 // Refuse possible leaked file descriptors
13183 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
13184 throw new IllegalArgumentException("File descriptors passed in Bundle");
13185 }
13186
13187 boolean doNext;
13188
13189 final long origId = Binder.clearCallingIdentity();
13190
13191 synchronized(this) {
13192 doNext = finishReceiverLocked(
13193 who, resultCode, resultData, resultExtras, resultAbort, true);
13194 }
13195
13196 if (doNext) {
13197 processNextBroadcast(false);
13198 }
13199 trimApplications();
13200
13201 Binder.restoreCallingIdentity(origId);
13202 }
13203
13204 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
13205 if (r.nextReceiver > 0) {
13206 Object curReceiver = r.receivers.get(r.nextReceiver-1);
13207 if (curReceiver instanceof BroadcastFilter) {
13208 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080013209 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013210 System.identityHashCode(r),
13211 r.intent.getAction(),
13212 r.nextReceiver - 1,
13213 System.identityHashCode(bf));
13214 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080013215 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013216 System.identityHashCode(r),
13217 r.intent.getAction(),
13218 r.nextReceiver - 1,
13219 ((ResolveInfo)curReceiver).toString());
13220 }
13221 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013222 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013223 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013224 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013225 System.identityHashCode(r),
13226 r.intent.getAction(),
13227 r.nextReceiver,
13228 "NONE");
13229 }
13230 }
13231
13232 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013233 ProcessRecord app = null;
13234 String anrMessage = null;
13235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013236 synchronized (this) {
13237 if (mOrderedBroadcasts.size() == 0) {
13238 return;
13239 }
13240 long now = SystemClock.uptimeMillis();
13241 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013242 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013243 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013244 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013245 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013246 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013247 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013248 return;
13249 }
13250
Joe Onorato8a9b2202010-02-26 18:56:32 -080013251 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013252 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013253 r.anrCount++;
13254
13255 // Current receiver has passed its expiration date.
13256 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013257 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013258 return;
13259 }
13260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013261 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013262 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013263 logBroadcastReceiverDiscard(r);
13264 if (curReceiver instanceof BroadcastFilter) {
13265 BroadcastFilter bf = (BroadcastFilter)curReceiver;
13266 if (bf.receiverList.pid != 0
13267 && bf.receiverList.pid != MY_PID) {
13268 synchronized (this.mPidsSelfLocked) {
13269 app = this.mPidsSelfLocked.get(
13270 bf.receiverList.pid);
13271 }
13272 }
13273 } else {
13274 app = r.curApp;
13275 }
13276
13277 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013278 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013279 }
13280
13281 if (mPendingBroadcast == r) {
13282 mPendingBroadcast = null;
13283 }
13284
13285 // Move on to the next receiver.
13286 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13287 r.resultExtras, r.resultAbort, true);
13288 scheduleBroadcastsLocked();
13289 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013290
13291 if (anrMessage != null) {
13292 appNotResponding(app, null, null, anrMessage);
13293 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013294 }
13295
13296 private final void processCurBroadcastLocked(BroadcastRecord r,
13297 ProcessRecord app) throws RemoteException {
13298 if (app.thread == null) {
13299 throw new RemoteException();
13300 }
13301 r.receiver = app.thread.asBinder();
13302 r.curApp = app;
13303 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013304 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013305
13306 // Tell the application to launch this receiver.
13307 r.intent.setComponent(r.curComponent);
13308
13309 boolean started = false;
13310 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013311 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013312 "Delivering to component " + r.curComponent
13313 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070013314 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013315 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
13316 r.resultCode, r.resultData, r.resultExtras, r.ordered);
13317 started = true;
13318 } finally {
13319 if (!started) {
13320 r.receiver = null;
13321 r.curApp = null;
13322 app.curReceiver = null;
13323 }
13324 }
13325
13326 }
13327
13328 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013329 Intent intent, int resultCode, String data, Bundle extras,
13330 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013331 if (app != null && app.thread != null) {
13332 // If we have an app thread, do the call through that so it is
13333 // correctly ordered with other one-way calls.
13334 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013335 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013336 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013337 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013338 }
13339 }
13340
13341 private final void deliverToRegisteredReceiver(BroadcastRecord r,
13342 BroadcastFilter filter, boolean ordered) {
13343 boolean skip = false;
13344 if (filter.requiredPermission != null) {
13345 int perm = checkComponentPermission(filter.requiredPermission,
13346 r.callingPid, r.callingUid, -1);
13347 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013348 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013349 + r.intent.toString()
13350 + " from " + r.callerPackage + " (pid="
13351 + r.callingPid + ", uid=" + r.callingUid + ")"
13352 + " requires " + filter.requiredPermission
13353 + " due to registered receiver " + filter);
13354 skip = true;
13355 }
13356 }
13357 if (r.requiredPermission != null) {
13358 int perm = checkComponentPermission(r.requiredPermission,
13359 filter.receiverList.pid, filter.receiverList.uid, -1);
13360 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013361 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013362 + r.intent.toString()
13363 + " to " + filter.receiverList.app
13364 + " (pid=" + filter.receiverList.pid
13365 + ", uid=" + filter.receiverList.uid + ")"
13366 + " requires " + r.requiredPermission
13367 + " due to sender " + r.callerPackage
13368 + " (uid " + r.callingUid + ")");
13369 skip = true;
13370 }
13371 }
13372
13373 if (!skip) {
13374 // If this is not being sent as an ordered broadcast, then we
13375 // don't want to touch the fields that keep track of the current
13376 // state of ordered broadcasts.
13377 if (ordered) {
13378 r.receiver = filter.receiverList.receiver.asBinder();
13379 r.curFilter = filter;
13380 filter.receiverList.curBroadcast = r;
13381 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013382 if (filter.receiverList.app != null) {
13383 // Bump hosting application to no longer be in background
13384 // scheduling class. Note that we can't do that if there
13385 // isn't an app... but we can only be in that case for
13386 // things that directly call the IActivityManager API, which
13387 // are already core system stuff so don't matter for this.
13388 r.curApp = filter.receiverList.app;
13389 filter.receiverList.app.curReceiver = r;
13390 updateOomAdjLocked();
13391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013392 }
13393 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013394 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013395 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013396 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013397 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013398 }
13399 performReceive(filter.receiverList.app, filter.receiverList.receiver,
13400 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013401 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013402 if (ordered) {
13403 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13404 }
13405 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013406 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013407 if (ordered) {
13408 r.receiver = null;
13409 r.curFilter = null;
13410 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013411 if (filter.receiverList.app != null) {
13412 filter.receiverList.app.curReceiver = null;
13413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013414 }
13415 }
13416 }
13417 }
13418
Dianne Hackborn12527f92009-11-11 17:39:50 -080013419 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13420 if (r.callingUid < 0) {
13421 // This was from a registerReceiver() call; ignore it.
13422 return;
13423 }
13424 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13425 MAX_BROADCAST_HISTORY-1);
13426 r.finishTime = SystemClock.uptimeMillis();
13427 mBroadcastHistory[0] = r;
13428 }
13429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013430 private final void processNextBroadcast(boolean fromMsg) {
13431 synchronized(this) {
13432 BroadcastRecord r;
13433
Joe Onorato8a9b2202010-02-26 18:56:32 -080013434 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013435 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013436 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013437
13438 updateCpuStats();
13439
13440 if (fromMsg) {
13441 mBroadcastsScheduled = false;
13442 }
13443
13444 // First, deliver any non-serialized broadcasts right away.
13445 while (mParallelBroadcasts.size() > 0) {
13446 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013447 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013448 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013449 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013450 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013451 for (int i=0; i<N; i++) {
13452 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013453 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013454 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013455 + target + ": " + r);
13456 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13457 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013458 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013459 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013460 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013461 }
13462
13463 // Now take care of the next serialized one...
13464
13465 // If we are waiting for a process to come up to handle the next
13466 // broadcast, then do nothing at this point. Just in case, we
13467 // check that the process we're waiting for still exists.
13468 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013469 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013470 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013471 + mPendingBroadcast.curApp);
13472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013473
13474 boolean isDead;
13475 synchronized (mPidsSelfLocked) {
13476 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13477 }
13478 if (!isDead) {
13479 // It's still alive, so keep waiting
13480 return;
13481 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013482 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013483 + " died before responding to broadcast");
13484 mPendingBroadcast = null;
13485 }
13486 }
13487
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013488 boolean looped = false;
13489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013490 do {
13491 if (mOrderedBroadcasts.size() == 0) {
13492 // No more broadcasts pending, so all done!
13493 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013494 if (looped) {
13495 // If we had finished the last ordered broadcast, then
13496 // make sure all processes have correct oom and sched
13497 // adjustments.
13498 updateOomAdjLocked();
13499 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013500 return;
13501 }
13502 r = mOrderedBroadcasts.get(0);
13503 boolean forceReceive = false;
13504
13505 // Ensure that even if something goes awry with the timeout
13506 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013507 // and continue to make progress.
13508 //
13509 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
13510 // receivers don't get executed with with timeouts. They're intended for
13511 // one time heavy lifting after system upgrades and can take
13512 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013513 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013514 if (mSystemReady && r.dispatchTime > 0) {
13515 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013516 if ((numReceivers > 0) &&
13517 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013518 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013519 + " now=" + now
13520 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013521 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013522 + " intent=" + r.intent
13523 + " numReceivers=" + numReceivers
13524 + " nextReceiver=" + r.nextReceiver
13525 + " state=" + r.state);
13526 broadcastTimeout(); // forcibly finish this broadcast
13527 forceReceive = true;
13528 r.state = BroadcastRecord.IDLE;
13529 }
13530 }
13531
13532 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013533 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013534 "processNextBroadcast() called when not idle (state="
13535 + r.state + ")");
13536 return;
13537 }
13538
13539 if (r.receivers == null || r.nextReceiver >= numReceivers
13540 || r.resultAbort || forceReceive) {
13541 // No more receivers for this broadcast! Send the final
13542 // result if requested...
13543 if (r.resultTo != null) {
13544 try {
13545 if (DEBUG_BROADCAST) {
13546 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013547 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013548 + " seq=" + seq + " app=" + r.callerApp);
13549 }
13550 performReceive(r.callerApp, r.resultTo,
13551 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013552 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013553 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013554 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013555 }
13556 }
13557
Joe Onorato8a9b2202010-02-26 18:56:32 -080013558 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013559 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13560
Joe Onorato8a9b2202010-02-26 18:56:32 -080013561 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013562 + r);
13563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013564 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013565 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013566 mOrderedBroadcasts.remove(0);
13567 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013568 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013569 continue;
13570 }
13571 } while (r == null);
13572
13573 // Get the next receiver...
13574 int recIdx = r.nextReceiver++;
13575
13576 // Keep track of when this receiver started, and make sure there
13577 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013578 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013579 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013580 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013581
Joe Onorato8a9b2202010-02-26 18:56:32 -080013582 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013583 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013584 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013585 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013586 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013587 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013588 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013589 }
13590
13591 Object nextReceiver = r.receivers.get(recIdx);
13592 if (nextReceiver instanceof BroadcastFilter) {
13593 // Simple case: this is a registered receiver who gets
13594 // a direct call.
13595 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013596 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013597 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013598 + filter + ": " + r);
13599 deliverToRegisteredReceiver(r, filter, r.ordered);
13600 if (r.receiver == null || !r.ordered) {
13601 // The receiver has already finished, so schedule to
13602 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013603 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13604 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013605 r.state = BroadcastRecord.IDLE;
13606 scheduleBroadcastsLocked();
13607 }
13608 return;
13609 }
13610
13611 // Hard case: need to instantiate the receiver, possibly
13612 // starting its application process to host it.
13613
13614 ResolveInfo info =
13615 (ResolveInfo)nextReceiver;
13616
13617 boolean skip = false;
13618 int perm = checkComponentPermission(info.activityInfo.permission,
13619 r.callingPid, r.callingUid,
13620 info.activityInfo.exported
13621 ? -1 : info.activityInfo.applicationInfo.uid);
13622 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013623 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013624 + r.intent.toString()
13625 + " from " + r.callerPackage + " (pid=" + r.callingPid
13626 + ", uid=" + r.callingUid + ")"
13627 + " requires " + info.activityInfo.permission
13628 + " due to receiver " + info.activityInfo.packageName
13629 + "/" + info.activityInfo.name);
13630 skip = true;
13631 }
13632 if (r.callingUid != Process.SYSTEM_UID &&
13633 r.requiredPermission != null) {
13634 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013635 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013636 checkPermission(r.requiredPermission,
13637 info.activityInfo.applicationInfo.packageName);
13638 } catch (RemoteException e) {
13639 perm = PackageManager.PERMISSION_DENIED;
13640 }
13641 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013642 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013643 + r.intent + " to "
13644 + info.activityInfo.applicationInfo.packageName
13645 + " requires " + r.requiredPermission
13646 + " due to sender " + r.callerPackage
13647 + " (uid " + r.callingUid + ")");
13648 skip = true;
13649 }
13650 }
13651 if (r.curApp != null && r.curApp.crashing) {
13652 // If the target process is crashing, just skip it.
13653 skip = true;
13654 }
13655
13656 if (skip) {
13657 r.receiver = null;
13658 r.curFilter = null;
13659 r.state = BroadcastRecord.IDLE;
13660 scheduleBroadcastsLocked();
13661 return;
13662 }
13663
13664 r.state = BroadcastRecord.APP_RECEIVE;
13665 String targetProcess = info.activityInfo.processName;
13666 r.curComponent = new ComponentName(
13667 info.activityInfo.applicationInfo.packageName,
13668 info.activityInfo.name);
13669 r.curReceiver = info.activityInfo;
13670
13671 // Is this receiver's application already running?
13672 ProcessRecord app = getProcessRecordLocked(targetProcess,
13673 info.activityInfo.applicationInfo.uid);
13674 if (app != null && app.thread != null) {
13675 try {
13676 processCurBroadcastLocked(r, app);
13677 return;
13678 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013679 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013680 + r.curComponent, e);
13681 }
13682
13683 // If a dead object exception was thrown -- fall through to
13684 // restart the application.
13685 }
13686
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013687 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013688 if ((r.curApp=startProcessLocked(targetProcess,
13689 info.activityInfo.applicationInfo, true,
13690 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013691 "broadcast", r.curComponent,
13692 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13693 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013694 // Ah, this recipient is unavailable. Finish it if necessary,
13695 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013696 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013697 + info.activityInfo.applicationInfo.packageName + "/"
13698 + info.activityInfo.applicationInfo.uid + " for broadcast "
13699 + r.intent + ": process is bad");
13700 logBroadcastReceiverDiscard(r);
13701 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13702 r.resultExtras, r.resultAbort, true);
13703 scheduleBroadcastsLocked();
13704 r.state = BroadcastRecord.IDLE;
13705 return;
13706 }
13707
13708 mPendingBroadcast = r;
13709 }
13710 }
13711
13712 // =========================================================
13713 // INSTRUMENTATION
13714 // =========================================================
13715
13716 public boolean startInstrumentation(ComponentName className,
13717 String profileFile, int flags, Bundle arguments,
13718 IInstrumentationWatcher watcher) {
13719 // Refuse possible leaked file descriptors
13720 if (arguments != null && arguments.hasFileDescriptors()) {
13721 throw new IllegalArgumentException("File descriptors passed in Bundle");
13722 }
13723
13724 synchronized(this) {
13725 InstrumentationInfo ii = null;
13726 ApplicationInfo ai = null;
13727 try {
13728 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013729 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013730 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013731 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013732 } catch (PackageManager.NameNotFoundException e) {
13733 }
13734 if (ii == null) {
13735 reportStartInstrumentationFailure(watcher, className,
13736 "Unable to find instrumentation info for: " + className);
13737 return false;
13738 }
13739 if (ai == null) {
13740 reportStartInstrumentationFailure(watcher, className,
13741 "Unable to find instrumentation target package: " + ii.targetPackage);
13742 return false;
13743 }
13744
13745 int match = mContext.getPackageManager().checkSignatures(
13746 ii.targetPackage, ii.packageName);
13747 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13748 String msg = "Permission Denial: starting instrumentation "
13749 + className + " from pid="
13750 + Binder.getCallingPid()
13751 + ", uid=" + Binder.getCallingPid()
13752 + " not allowed because package " + ii.packageName
13753 + " does not have a signature matching the target "
13754 + ii.targetPackage;
13755 reportStartInstrumentationFailure(watcher, className, msg);
13756 throw new SecurityException(msg);
13757 }
13758
13759 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013760 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013761 ProcessRecord app = addAppLocked(ai);
13762 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013763 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013764 app.instrumentationProfileFile = profileFile;
13765 app.instrumentationArguments = arguments;
13766 app.instrumentationWatcher = watcher;
13767 app.instrumentationResultClass = className;
13768 Binder.restoreCallingIdentity(origId);
13769 }
13770
13771 return true;
13772 }
13773
13774 /**
13775 * Report errors that occur while attempting to start Instrumentation. Always writes the
13776 * error to the logs, but if somebody is watching, send the report there too. This enables
13777 * the "am" command to report errors with more information.
13778 *
13779 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13780 * @param cn The component name of the instrumentation.
13781 * @param report The error report.
13782 */
13783 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13784 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013785 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013786 try {
13787 if (watcher != null) {
13788 Bundle results = new Bundle();
13789 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13790 results.putString("Error", report);
13791 watcher.instrumentationStatus(cn, -1, results);
13792 }
13793 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013794 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013795 }
13796 }
13797
13798 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13799 if (app.instrumentationWatcher != null) {
13800 try {
13801 // NOTE: IInstrumentationWatcher *must* be oneway here
13802 app.instrumentationWatcher.instrumentationFinished(
13803 app.instrumentationClass,
13804 resultCode,
13805 results);
13806 } catch (RemoteException e) {
13807 }
13808 }
13809 app.instrumentationWatcher = null;
13810 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013811 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013812 app.instrumentationProfileFile = null;
13813 app.instrumentationArguments = null;
13814
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013815 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013816 }
13817
13818 public void finishInstrumentation(IApplicationThread target,
13819 int resultCode, Bundle results) {
13820 // Refuse possible leaked file descriptors
13821 if (results != null && results.hasFileDescriptors()) {
13822 throw new IllegalArgumentException("File descriptors passed in Intent");
13823 }
13824
13825 synchronized(this) {
13826 ProcessRecord app = getRecordForAppLocked(target);
13827 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013828 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013829 return;
13830 }
13831 final long origId = Binder.clearCallingIdentity();
13832 finishInstrumentationLocked(app, resultCode, results);
13833 Binder.restoreCallingIdentity(origId);
13834 }
13835 }
13836
13837 // =========================================================
13838 // CONFIGURATION
13839 // =========================================================
13840
13841 public ConfigurationInfo getDeviceConfigurationInfo() {
13842 ConfigurationInfo config = new ConfigurationInfo();
13843 synchronized (this) {
13844 config.reqTouchScreen = mConfiguration.touchscreen;
13845 config.reqKeyboardType = mConfiguration.keyboard;
13846 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013847 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13848 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013849 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13850 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013851 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13852 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013853 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13854 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013855 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013856 }
13857 return config;
13858 }
13859
13860 public Configuration getConfiguration() {
13861 Configuration ci;
13862 synchronized(this) {
13863 ci = new Configuration(mConfiguration);
13864 }
13865 return ci;
13866 }
13867
13868 public void updateConfiguration(Configuration values) {
13869 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13870 "updateConfiguration()");
13871
13872 synchronized(this) {
13873 if (values == null && mWindowManager != null) {
13874 // sentinel: fetch the current configuration from the window manager
13875 values = mWindowManager.computeNewConfiguration();
13876 }
13877
13878 final long origId = Binder.clearCallingIdentity();
13879 updateConfigurationLocked(values, null);
13880 Binder.restoreCallingIdentity(origId);
13881 }
13882 }
13883
13884 /**
13885 * Do either or both things: (1) change the current configuration, and (2)
13886 * make sure the given activity is running with the (now) current
13887 * configuration. Returns true if the activity has been left running, or
13888 * false if <var>starting</var> is being destroyed to match the new
13889 * configuration.
13890 */
13891 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013892 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013893 int changes = 0;
13894
13895 boolean kept = true;
13896
13897 if (values != null) {
13898 Configuration newConfig = new Configuration(mConfiguration);
13899 changes = newConfig.updateFrom(values);
13900 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013901 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013902 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013903 }
13904
Doug Zongker2bec3d42009-12-04 12:52:44 -080013905 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013906
13907 if (values.locale != null) {
13908 saveLocaleLocked(values.locale,
13909 !values.locale.equals(mConfiguration.locale),
13910 values.userSetLocale);
13911 }
13912
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013913 mConfigurationSeq++;
13914 if (mConfigurationSeq <= 0) {
13915 mConfigurationSeq = 1;
13916 }
13917 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013918 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013919 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013920
13921 AttributeCache ac = AttributeCache.instance();
13922 if (ac != null) {
13923 ac.updateConfiguration(mConfiguration);
13924 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013925
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013926 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13927 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13928 msg.obj = new Configuration(mConfiguration);
13929 mHandler.sendMessage(msg);
13930 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013931
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013932 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13933 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013934 try {
13935 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013936 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013937 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013938 app.thread.scheduleConfigurationChanged(mConfiguration);
13939 }
13940 } catch (Exception e) {
13941 }
13942 }
13943 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013944 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13945 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013946 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13947 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013948 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13949 broadcastIntentLocked(null, null,
13950 new Intent(Intent.ACTION_LOCALE_CHANGED),
13951 null, null, 0, null, null,
13952 null, false, false, MY_PID, Process.SYSTEM_UID);
13953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013954 }
13955 }
13956
13957 if (changes != 0 && starting == null) {
13958 // If the configuration changed, and the caller is not already
13959 // in the process of starting an activity, then find the top
13960 // activity to check if its configuration needs to change.
13961 starting = topRunningActivityLocked(null);
13962 }
13963
13964 if (starting != null) {
13965 kept = ensureActivityConfigurationLocked(starting, changes);
13966 if (kept) {
13967 // If this didn't result in the starting activity being
13968 // destroyed, then we need to make sure at this point that all
13969 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013970 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013971 + ", ensuring others are correct.");
13972 ensureActivitiesVisibleLocked(starting, changes);
13973 }
13974 }
13975
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013976 if (values != null && mWindowManager != null) {
13977 mWindowManager.setNewConfiguration(mConfiguration);
13978 }
13979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013980 return kept;
13981 }
13982
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013983 private final boolean relaunchActivityLocked(ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013984 int changes, boolean andResume) {
13985 List<ResultInfo> results = null;
13986 List<Intent> newIntents = null;
13987 if (andResume) {
13988 results = r.results;
13989 newIntents = r.newIntents;
13990 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013991 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013992 + " with results=" + results + " newIntents=" + newIntents
13993 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013994 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13995 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013996 r.task.taskId, r.shortComponentName);
13997
13998 r.startFreezingScreenLocked(r.app, 0);
13999
14000 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014001 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014002 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080014003 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014004 // Note: don't need to call pauseIfSleepingLocked() here, because
14005 // the caller will only pass in 'andResume' if this activity is
14006 // currently resumed, which implies we aren't sleeping.
14007 } catch (RemoteException e) {
14008 return false;
14009 }
14010
14011 if (andResume) {
14012 r.results = null;
14013 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070014014 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014015 }
14016
14017 return true;
14018 }
14019
14020 /**
14021 * Make sure the given activity matches the current configuration. Returns
14022 * false if the activity had to be destroyed. Returns true if the
14023 * configuration is the same, or the activity will remain running as-is
14024 * for whatever reason. Ensures the HistoryRecord is updated with the
14025 * correct configuration and all other bookkeeping is handled.
14026 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014027 private final boolean ensureActivityConfigurationLocked(ActivityRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014028 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070014029 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070014030 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
14031 "Skipping config check (will change): " + r);
14032 return true;
14033 }
14034
Joe Onorato8a9b2202010-02-26 18:56:32 -080014035 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014036 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014037
14038 // Short circuit: if the two configurations are the exact same
14039 // object (the common case), then there is nothing to do.
14040 Configuration newConfig = mConfiguration;
14041 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014042 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014043 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014044 return true;
14045 }
14046
14047 // We don't worry about activities that are finishing.
14048 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014049 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014050 "Configuration doesn't matter in finishing " + r);
14051 r.stopFreezingScreenLocked(false);
14052 return true;
14053 }
14054
14055 // Okay we now are going to make this activity have the new config.
14056 // But then we need to figure out how it needs to deal with that.
14057 Configuration oldConfig = r.configuration;
14058 r.configuration = newConfig;
14059
14060 // If the activity isn't currently running, just leave the new
14061 // configuration and it will pick that up next time it starts.
14062 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014063 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014064 "Configuration doesn't matter not running " + r);
14065 r.stopFreezingScreenLocked(false);
14066 return true;
14067 }
14068
14069 // If the activity isn't persistent, there is a chance we will
14070 // need to restart it.
14071 if (!r.persistent) {
14072
14073 // Figure out what has changed between the two configurations.
14074 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014075 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014076 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014077 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014078 + Integer.toHexString(r.info.configChanges)
14079 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014080 }
14081 if ((changes&(~r.info.configChanges)) != 0) {
14082 // Aha, the activity isn't handling the change, so DIE DIE DIE.
14083 r.configChangeFlags |= changes;
14084 r.startFreezingScreenLocked(r.app, globalChanges);
14085 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014086 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014087 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014088 destroyActivityLocked(r, true);
14089 } else if (r.state == ActivityState.PAUSING) {
14090 // A little annoying: we are waiting for this activity to
14091 // finish pausing. Let's not do anything now, but just
14092 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014093 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014094 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014095 r.configDestroy = true;
14096 return true;
14097 } else if (r.state == ActivityState.RESUMED) {
14098 // Try to optimize this case: the configuration is changing
14099 // and we need to restart the top, resumed activity.
14100 // Instead of doing the normal handshaking, just say
14101 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080014102 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014103 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014104 relaunchActivityLocked(r, r.configChangeFlags, true);
14105 r.configChangeFlags = 0;
14106 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014107 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070014108 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014109 relaunchActivityLocked(r, r.configChangeFlags, false);
14110 r.configChangeFlags = 0;
14111 }
14112
14113 // All done... tell the caller we weren't able to keep this
14114 // activity around.
14115 return false;
14116 }
14117 }
14118
14119 // Default case: the activity can handle this new configuration, so
14120 // hand it over. Note that we don't need to give it the new
14121 // configuration, since we always send configuration changes to all
14122 // process when they happen so it can just use whatever configuration
14123 // it last got.
14124 if (r.app != null && r.app.thread != null) {
14125 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014126 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014127 r.app.thread.scheduleActivityConfigurationChanged(r);
14128 } catch (RemoteException e) {
14129 // If process died, whatever.
14130 }
14131 }
14132 r.stopFreezingScreenLocked(false);
14133
14134 return true;
14135 }
14136
14137 /**
14138 * Save the locale. You must be inside a synchronized (this) block.
14139 */
14140 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
14141 if(isDiff) {
14142 SystemProperties.set("user.language", l.getLanguage());
14143 SystemProperties.set("user.region", l.getCountry());
14144 }
14145
14146 if(isPersist) {
14147 SystemProperties.set("persist.sys.language", l.getLanguage());
14148 SystemProperties.set("persist.sys.country", l.getCountry());
14149 SystemProperties.set("persist.sys.localevar", l.getVariant());
14150 }
14151 }
14152
14153 // =========================================================
14154 // LIFETIME MANAGEMENT
14155 // =========================================================
14156
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014157 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
14158 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014159 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014160 // This adjustment has already been computed. If we are calling
14161 // from the top, we may have already computed our adjustment with
14162 // an earlier hidden adjustment that isn't really for us... if
14163 // so, use the new hidden adjustment.
14164 if (!recursed && app.hidden) {
14165 app.curAdj = hiddenAdj;
14166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014167 return app.curAdj;
14168 }
14169
14170 if (app.thread == null) {
14171 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014172 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014173 return (app.curAdj=EMPTY_APP_ADJ);
14174 }
14175
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014176 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
14177 // The max adjustment doesn't allow this app to be anything
14178 // below foreground, so it is not worth doing work for it.
14179 app.adjType = "fixed";
14180 app.adjSeq = mAdjSeq;
14181 app.curRawAdj = app.maxAdj;
14182 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
14183 return (app.curAdj=app.maxAdj);
14184 }
14185
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014186 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014187 app.adjSource = null;
14188 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014189 app.empty = false;
14190 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014191
The Android Open Source Project4df24232009-03-05 14:34:35 -080014192 // Determine the importance of the process, starting with most
14193 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014194 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014195 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014196 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014197 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014198 // The last app on the list is the foreground app.
14199 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014200 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014201 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014202 } else if (app.instrumentationClass != null) {
14203 // Don't want to kill running instrumentation.
14204 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014205 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014206 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014207 } else if (app.persistentActivities > 0) {
14208 // Special persistent activities... shouldn't be used these days.
14209 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014210 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014211 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014212 } else if (app.curReceiver != null ||
14213 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
14214 // An app that is currently receiving a broadcast also
14215 // counts as being in the foreground.
14216 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014217 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014218 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014219 } else if (app.executingServices.size() > 0) {
14220 // An app that is currently executing a service callback also
14221 // counts as being in the foreground.
14222 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014223 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014224 app.adjType = "exec-service";
14225 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014226 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014227 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014228 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014229 app.adjType = "foreground-service";
14230 } else if (app.forcingToForeground != null) {
14231 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014232 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014233 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014234 app.adjType = "force-foreground";
14235 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014236 } else if (app == mHeavyWeightProcess) {
14237 // We don't want to kill the current heavy-weight process.
14238 adj = HEAVY_WEIGHT_APP_ADJ;
14239 schedGroup = Process.THREAD_GROUP_DEFAULT;
14240 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080014241 } else if (app == mHomeProcess) {
14242 // This process is hosting what we currently consider to be the
14243 // home app, so we don't want to let it go into the background.
14244 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014245 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014246 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014247 } else if ((N=app.activities.size()) != 0) {
14248 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014249 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014250 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014251 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014252 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014253 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014254 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014255 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014256 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014257 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014258 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014259 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014260 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014261 break;
14262 }
14263 }
14264 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014265 // A very not-needed process. If this is lower in the lru list,
14266 // we will push it in to the empty bucket.
14267 app.hidden = true;
14268 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014269 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014270 adj = hiddenAdj;
14271 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014272 }
14273
Joe Onorato8a9b2202010-02-26 18:56:32 -080014274 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014275
The Android Open Source Project4df24232009-03-05 14:34:35 -080014276 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014277 // there are applications dependent on our services or providers, but
14278 // this gives us a baseline and makes sure we don't get into an
14279 // infinite recursion.
14280 app.adjSeq = mAdjSeq;
14281 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014282
Christopher Tate6fa95972009-06-05 18:43:55 -070014283 if (mBackupTarget != null && app == mBackupTarget.app) {
14284 // If possible we want to avoid killing apps while they're being backed up
14285 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014286 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070014287 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014288 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014289 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070014290 }
14291 }
14292
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014293 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
14294 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014295 final long now = SystemClock.uptimeMillis();
14296 // This process is more important if the top activity is
14297 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070014298 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014299 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014300 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014301 if (s.startRequested) {
14302 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14303 // This service has seen some activity within
14304 // recent memory, so we will keep its process ahead
14305 // of the background processes.
14306 if (adj > SECONDARY_SERVER_ADJ) {
14307 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014308 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014309 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014310 }
14311 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014312 // If we have let the service slide into the background
14313 // state, still have some text describing what it is doing
14314 // even though the service no longer has an impact.
14315 if (adj > SECONDARY_SERVER_ADJ) {
14316 app.adjType = "started-bg-services";
14317 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014318 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014319 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
14320 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014321 Iterator<ConnectionRecord> kt
14322 = s.connections.values().iterator();
14323 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14324 // XXX should compute this based on the max of
14325 // all connected clients.
14326 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014327 if (cr.binding.client == app) {
14328 // Binding to ourself is not interesting.
14329 continue;
14330 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014331 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
14332 ProcessRecord client = cr.binding.client;
14333 int myHiddenAdj = hiddenAdj;
14334 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014335 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014336 myHiddenAdj = client.hiddenAdj;
14337 } else {
14338 myHiddenAdj = VISIBLE_APP_ADJ;
14339 }
14340 }
14341 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014342 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014343 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014344 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014345 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014346 if (!client.hidden) {
14347 app.hidden = false;
14348 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014349 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014350 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14351 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014352 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014353 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014354 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014355 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14356 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14357 schedGroup = Process.THREAD_GROUP_DEFAULT;
14358 }
14359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014360 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014361 ActivityRecord a = cr.activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014362 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014363 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014364 //}
14365 if (a != null && adj > FOREGROUND_APP_ADJ &&
14366 (a.state == ActivityState.RESUMED
14367 || a.state == ActivityState.PAUSING)) {
14368 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014369 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014370 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014371 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014372 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14373 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014374 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014375 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014376 }
14377 }
14378 }
14379 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014380
14381 // Finally, f this process has active services running in it, we
14382 // would like to avoid killing it unless it would prevent the current
14383 // application from running. By default we put the process in
14384 // with the rest of the background processes; as we scan through
14385 // its services we may bump it up from there.
14386 if (adj > hiddenAdj) {
14387 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014388 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014389 app.adjType = "bg-services";
14390 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014391 }
14392
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014393 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
14394 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014395 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014396 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
14397 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014398 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014399 if (cpr.clients.size() != 0) {
14400 Iterator<ProcessRecord> kt = cpr.clients.iterator();
14401 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14402 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014403 if (client == app) {
14404 // Being our own client is not interesting.
14405 continue;
14406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014407 int myHiddenAdj = hiddenAdj;
14408 if (myHiddenAdj > client.hiddenAdj) {
14409 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
14410 myHiddenAdj = client.hiddenAdj;
14411 } else {
14412 myHiddenAdj = FOREGROUND_APP_ADJ;
14413 }
14414 }
14415 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014416 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014417 if (adj > clientAdj) {
14418 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014419 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014420 if (!client.hidden) {
14421 app.hidden = false;
14422 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014423 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014424 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14425 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014426 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014427 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014428 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014429 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14430 schedGroup = Process.THREAD_GROUP_DEFAULT;
14431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014432 }
14433 }
14434 // If the provider has external (non-framework) process
14435 // dependencies, ensure that its adjustment is at least
14436 // FOREGROUND_APP_ADJ.
14437 if (cpr.externals != 0) {
14438 if (adj > FOREGROUND_APP_ADJ) {
14439 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014440 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014441 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014442 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014443 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014444 }
14445 }
14446 }
14447 }
14448
14449 app.curRawAdj = adj;
14450
Joe Onorato8a9b2202010-02-26 18:56:32 -080014451 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014452 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14453 if (adj > app.maxAdj) {
14454 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014455 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014456 schedGroup = Process.THREAD_GROUP_DEFAULT;
14457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014458 }
14459
14460 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014461 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014463 return adj;
14464 }
14465
14466 /**
14467 * Ask a given process to GC right now.
14468 */
14469 final void performAppGcLocked(ProcessRecord app) {
14470 try {
14471 app.lastRequestedGc = SystemClock.uptimeMillis();
14472 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014473 if (app.reportLowMemory) {
14474 app.reportLowMemory = false;
14475 app.thread.scheduleLowMemory();
14476 } else {
14477 app.thread.processInBackground();
14478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014479 }
14480 } catch (Exception e) {
14481 // whatever.
14482 }
14483 }
14484
14485 /**
14486 * Returns true if things are idle enough to perform GCs.
14487 */
Josh Bartel7f208742010-02-25 11:01:44 -060014488 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014489 return mParallelBroadcasts.size() == 0
14490 && mOrderedBroadcasts.size() == 0
14491 && (mSleeping || (mResumedActivity != null &&
14492 mResumedActivity.idle));
14493 }
14494
14495 /**
14496 * Perform GCs on all processes that are waiting for it, but only
14497 * if things are idle.
14498 */
14499 final void performAppGcsLocked() {
14500 final int N = mProcessesToGc.size();
14501 if (N <= 0) {
14502 return;
14503 }
Josh Bartel7f208742010-02-25 11:01:44 -060014504 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014505 while (mProcessesToGc.size() > 0) {
14506 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070014507 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014508 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14509 <= SystemClock.uptimeMillis()) {
14510 // To avoid spamming the system, we will GC processes one
14511 // at a time, waiting a few seconds between each.
14512 performAppGcLocked(proc);
14513 scheduleAppGcsLocked();
14514 return;
14515 } else {
14516 // It hasn't been long enough since we last GCed this
14517 // process... put it in the list to wait for its time.
14518 addProcessToGcListLocked(proc);
14519 break;
14520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014521 }
14522 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014523
14524 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014525 }
14526 }
14527
14528 /**
14529 * If all looks good, perform GCs on all processes waiting for them.
14530 */
14531 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014532 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014533 performAppGcsLocked();
14534 return;
14535 }
14536 // Still not idle, wait some more.
14537 scheduleAppGcsLocked();
14538 }
14539
14540 /**
14541 * Schedule the execution of all pending app GCs.
14542 */
14543 final void scheduleAppGcsLocked() {
14544 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014545
14546 if (mProcessesToGc.size() > 0) {
14547 // Schedule a GC for the time to the next process.
14548 ProcessRecord proc = mProcessesToGc.get(0);
14549 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14550
14551 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14552 long now = SystemClock.uptimeMillis();
14553 if (when < (now+GC_TIMEOUT)) {
14554 when = now + GC_TIMEOUT;
14555 }
14556 mHandler.sendMessageAtTime(msg, when);
14557 }
14558 }
14559
14560 /**
14561 * Add a process to the array of processes waiting to be GCed. Keeps the
14562 * list in sorted order by the last GC time. The process can't already be
14563 * on the list.
14564 */
14565 final void addProcessToGcListLocked(ProcessRecord proc) {
14566 boolean added = false;
14567 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14568 if (mProcessesToGc.get(i).lastRequestedGc <
14569 proc.lastRequestedGc) {
14570 added = true;
14571 mProcessesToGc.add(i+1, proc);
14572 break;
14573 }
14574 }
14575 if (!added) {
14576 mProcessesToGc.add(0, proc);
14577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014578 }
14579
14580 /**
14581 * Set up to ask a process to GC itself. This will either do it
14582 * immediately, or put it on the list of processes to gc the next
14583 * time things are idle.
14584 */
14585 final void scheduleAppGcLocked(ProcessRecord app) {
14586 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014587 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014588 return;
14589 }
14590 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014591 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014592 scheduleAppGcsLocked();
14593 }
14594 }
14595
14596 private final boolean updateOomAdjLocked(
14597 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14598 app.hiddenAdj = hiddenAdj;
14599
14600 if (app.thread == null) {
14601 return true;
14602 }
14603
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014604 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014605
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014606 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014607 if (app.curRawAdj != app.setRawAdj) {
14608 if (app.curRawAdj > FOREGROUND_APP_ADJ
14609 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14610 // If this app is transitioning from foreground to
14611 // non-foreground, have it do a gc.
14612 scheduleAppGcLocked(app);
14613 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14614 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14615 // Likewise do a gc when an app is moving in to the
14616 // background (such as a service stopping).
14617 scheduleAppGcLocked(app);
14618 }
14619 app.setRawAdj = app.curRawAdj;
14620 }
14621 if (adj != app.setAdj) {
14622 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014623 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014624 TAG, "Set app " + app.processName +
14625 " oom adj to " + adj);
14626 app.setAdj = adj;
14627 } else {
14628 return false;
14629 }
14630 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014631 if (app.setSchedGroup != app.curSchedGroup) {
14632 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014633 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014634 "Setting process group of " + app.processName
14635 + " to " + app.curSchedGroup);
14636 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014637 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014638 try {
14639 Process.setProcessGroup(app.pid, app.curSchedGroup);
14640 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014641 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014642 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014643 e.printStackTrace();
14644 } finally {
14645 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014646 }
14647 }
14648 if (false) {
14649 if (app.thread != null) {
14650 try {
14651 app.thread.setSchedulingGroup(app.curSchedGroup);
14652 } catch (RemoteException e) {
14653 }
14654 }
14655 }
14656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014657 }
14658
14659 return true;
14660 }
14661
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014662 private final ActivityRecord resumedAppLocked() {
14663 ActivityRecord resumedActivity = mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014664 if (resumedActivity == null || resumedActivity.app == null) {
14665 resumedActivity = mPausingActivity;
14666 if (resumedActivity == null || resumedActivity.app == null) {
14667 resumedActivity = topRunningActivityLocked(null);
14668 }
14669 }
14670 return resumedActivity;
14671 }
14672
14673 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014674 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014675 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14676 int curAdj = app.curAdj;
14677 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14678 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14679
14680 mAdjSeq++;
14681
14682 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14683 if (res) {
14684 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14685 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14686 if (nowHidden != wasHidden) {
14687 // Changed to/from hidden state, so apps after it in the LRU
14688 // list may also be changed.
14689 updateOomAdjLocked();
14690 }
14691 }
14692 return res;
14693 }
14694
14695 private final boolean updateOomAdjLocked() {
14696 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014697 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014698 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14699
14700 if (false) {
14701 RuntimeException e = new RuntimeException();
14702 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014703 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014704 }
14705
14706 mAdjSeq++;
14707
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014708 // Let's determine how many processes we have running vs.
14709 // how many slots we have for background processes; we may want
14710 // to put multiple processes in a slot of there are enough of
14711 // them.
14712 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14713 int factor = (mLruProcesses.size()-4)/numSlots;
14714 if (factor < 1) factor = 1;
14715 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014716 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014718 // First try updating the OOM adjustment for each of the
14719 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014720 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014721 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14722 while (i > 0) {
14723 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014724 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014725 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014726 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014727 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014728 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014729 step++;
14730 if (step >= factor) {
14731 step = 0;
14732 curHiddenAdj++;
14733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014734 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014735 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070014736 if (!app.killedBackground) {
14737 numHidden++;
14738 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070014739 Slog.i(TAG, "No longer want " + app.processName
14740 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014741 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14742 app.processName, app.setAdj, "too many background");
14743 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070014744 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014745 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014746 }
14747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014748 } else {
14749 didOomAdj = false;
14750 }
14751 }
14752
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014753 // If we return false, we will fall back on killing processes to
14754 // have a fixed limit. Do this if a limit has been requested; else
14755 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014756 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14757 }
14758
14759 private final void trimApplications() {
14760 synchronized (this) {
14761 int i;
14762
14763 // First remove any unused application processes whose package
14764 // has been removed.
14765 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14766 final ProcessRecord app = mRemovedProcesses.get(i);
14767 if (app.activities.size() == 0
14768 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014769 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014770 TAG, "Exiting empty application process "
14771 + app.processName + " ("
14772 + (app.thread != null ? app.thread.asBinder() : null)
14773 + ")\n");
14774 if (app.pid > 0 && app.pid != MY_PID) {
14775 Process.killProcess(app.pid);
14776 } else {
14777 try {
14778 app.thread.scheduleExit();
14779 } catch (Exception e) {
14780 // Ignore exceptions.
14781 }
14782 }
14783 cleanUpApplicationRecordLocked(app, false, -1);
14784 mRemovedProcesses.remove(i);
14785
14786 if (app.persistent) {
14787 if (app.persistent) {
14788 addAppLocked(app.info);
14789 }
14790 }
14791 }
14792 }
14793
14794 // Now try updating the OOM adjustment for each of the
14795 // application processes based on their current state.
14796 // If the setOomAdj() API is not supported, then go with our
14797 // back-up plan...
14798 if (!updateOomAdjLocked()) {
14799
14800 // Count how many processes are running services.
14801 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014802 for (i=mLruProcesses.size()-1; i>=0; i--) {
14803 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014804
14805 if (app.persistent || app.services.size() != 0
14806 || app.curReceiver != null
14807 || app.persistentActivities > 0) {
14808 // Don't count processes holding services against our
14809 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014810 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014811 TAG, "Not trimming app " + app + " with services: "
14812 + app.services);
14813 numServiceProcs++;
14814 }
14815 }
14816
14817 int curMaxProcs = mProcessLimit;
14818 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14819 if (mAlwaysFinishActivities) {
14820 curMaxProcs = 1;
14821 }
14822 curMaxProcs += numServiceProcs;
14823
14824 // Quit as many processes as we can to get down to the desired
14825 // process count. First remove any processes that no longer
14826 // have activites running in them.
14827 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014828 i<mLruProcesses.size()
14829 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014830 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014831 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014832 // Quit an application only if it is not currently
14833 // running any activities.
14834 if (!app.persistent && app.activities.size() == 0
14835 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014836 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014837 TAG, "Exiting empty application process "
14838 + app.processName + " ("
14839 + (app.thread != null ? app.thread.asBinder() : null)
14840 + ")\n");
14841 if (app.pid > 0 && app.pid != MY_PID) {
14842 Process.killProcess(app.pid);
14843 } else {
14844 try {
14845 app.thread.scheduleExit();
14846 } catch (Exception e) {
14847 // Ignore exceptions.
14848 }
14849 }
14850 // todo: For now we assume the application is not buggy
14851 // or evil, and will quit as a result of our request.
14852 // Eventually we need to drive this off of the death
14853 // notification, and kill the process if it takes too long.
14854 cleanUpApplicationRecordLocked(app, false, i);
14855 i--;
14856 }
14857 }
14858
14859 // If we still have too many processes, now from the least
14860 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014861 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014862 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014863 " of " + curMaxProcs + " processes");
14864 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014865 i<mLruProcesses.size()
14866 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014867 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014868 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014869 // Quit the application only if we have a state saved for
14870 // all of its activities.
14871 boolean canQuit = !app.persistent && app.curReceiver == null
14872 && app.services.size() == 0
14873 && app.persistentActivities == 0;
14874 int NUMA = app.activities.size();
14875 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014876 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014877 TAG, "Looking to quit " + app.processName);
14878 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014879 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014880 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014881 TAG, " " + r.intent.getComponent().flattenToShortString()
14882 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14883 canQuit = (r.haveState || !r.stateNotNeeded)
14884 && !r.visible && r.stopped;
14885 }
14886 if (canQuit) {
14887 // Finish all of the activities, and then the app itself.
14888 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014889 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014890 if (!r.finishing) {
14891 destroyActivityLocked(r, false);
14892 }
14893 r.resultTo = null;
14894 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014895 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014896 + app.processName + " ("
14897 + (app.thread != null ? app.thread.asBinder() : null)
14898 + ")\n");
14899 if (app.pid > 0 && app.pid != MY_PID) {
14900 Process.killProcess(app.pid);
14901 } else {
14902 try {
14903 app.thread.scheduleExit();
14904 } catch (Exception e) {
14905 // Ignore exceptions.
14906 }
14907 }
14908 // todo: For now we assume the application is not buggy
14909 // or evil, and will quit as a result of our request.
14910 // Eventually we need to drive this off of the death
14911 // notification, and kill the process if it takes too long.
14912 cleanUpApplicationRecordLocked(app, false, i);
14913 i--;
14914 //dump();
14915 }
14916 }
14917
14918 }
14919
14920 int curMaxActivities = MAX_ACTIVITIES;
14921 if (mAlwaysFinishActivities) {
14922 curMaxActivities = 1;
14923 }
14924
14925 // Finally, if there are too many activities now running, try to
14926 // finish as many as we can to get back down to the limit.
14927 for ( i=0;
14928 i<mLRUActivities.size()
14929 && mLRUActivities.size() > curMaxActivities;
14930 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014931 final ActivityRecord r
14932 = (ActivityRecord)mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014933
14934 // We can finish this one if we have its icicle saved and
14935 // it is not persistent.
14936 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14937 && r.stopped && !r.persistent && !r.finishing) {
14938 final int origSize = mLRUActivities.size();
14939 destroyActivityLocked(r, true);
14940
14941 // This will remove it from the LRU list, so keep
14942 // our index at the same value. Note that this check to
14943 // see if the size changes is just paranoia -- if
14944 // something unexpected happens, we don't want to end up
14945 // in an infinite loop.
14946 if (origSize > mLRUActivities.size()) {
14947 i--;
14948 }
14949 }
14950 }
14951 }
14952 }
14953
14954 /** This method sends the specified signal to each of the persistent apps */
14955 public void signalPersistentProcesses(int sig) throws RemoteException {
14956 if (sig != Process.SIGNAL_USR1) {
14957 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14958 }
14959
14960 synchronized (this) {
14961 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14962 != PackageManager.PERMISSION_GRANTED) {
14963 throw new SecurityException("Requires permission "
14964 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14965 }
14966
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014967 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14968 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014969 if (r.thread != null && r.persistent) {
14970 Process.sendSignal(r.pid, sig);
14971 }
14972 }
14973 }
14974 }
14975
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014976 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014977 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014978
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014979 try {
14980 synchronized (this) {
14981 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14982 // its own permission.
14983 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14984 != PackageManager.PERMISSION_GRANTED) {
14985 throw new SecurityException("Requires permission "
14986 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014987 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014988
14989 if (start && fd == null) {
14990 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014991 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014992
14993 ProcessRecord proc = null;
14994 try {
14995 int pid = Integer.parseInt(process);
14996 synchronized (mPidsSelfLocked) {
14997 proc = mPidsSelfLocked.get(pid);
14998 }
14999 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015000 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015001
15002 if (proc == null) {
15003 HashMap<String, SparseArray<ProcessRecord>> all
15004 = mProcessNames.getMap();
15005 SparseArray<ProcessRecord> procs = all.get(process);
15006 if (procs != null && procs.size() > 0) {
15007 proc = procs.valueAt(0);
15008 }
15009 }
15010
15011 if (proc == null || proc.thread == null) {
15012 throw new IllegalArgumentException("Unknown process: " + process);
15013 }
15014
15015 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
15016 if (isSecure) {
15017 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
15018 throw new SecurityException("Process not debuggable: " + proc);
15019 }
15020 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015021
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015022 proc.thread.profilerControl(start, path, fd);
15023 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015024 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070015025 }
15026 } catch (RemoteException e) {
15027 throw new IllegalStateException("Process disappeared");
15028 } finally {
15029 if (fd != null) {
15030 try {
15031 fd.close();
15032 } catch (IOException e) {
15033 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080015034 }
15035 }
15036 }
15037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015038 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
15039 public void monitor() {
15040 synchronized (this) { }
15041 }
15042}