blob: ef509b158e00952c0c4ba922bc75962cc2f918e8 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070027import com.android.server.am.ActivityStack.ActivityState;
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080028import com.android.server.wm.WindowManagerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
Dianne Hackbornf26fd992011-04-08 18:14:09 -070047import android.app.IThumbnailRetriever;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import 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;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070052import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080053import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020054import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080055import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.content.ComponentName;
57import android.content.ContentResolver;
58import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020059import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import 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;
Robert Greenwalt434203a2010-10-11 16:00:27 -070080import android.net.Proxy;
81import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.net.Uri;
83import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080084import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080085import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070086import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080087import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080089import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.os.FileUtils;
91import android.os.Handler;
92import android.os.IBinder;
Dianne Hackborne17aeb32011-04-07 15:11:57 -070093import android.os.IInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.IPermissionController;
95import android.os.Looper;
96import android.os.Message;
97import android.os.Parcel;
98import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700100import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.os.RemoteException;
102import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700103import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.os.SystemClock;
105import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.util.Config;
108import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800109import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800110import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import android.util.PrintWriterPrinter;
112import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700113import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import android.view.Gravity;
115import android.view.LayoutInflater;
116import android.view.View;
117import android.view.WindowManager;
118import android.view.WindowManagerPolicy;
119
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700120import java.io.BufferedInputStream;
121import java.io.BufferedOutputStream;
122import java.io.DataInputStream;
123import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124import java.io.File;
125import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700126import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700128import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200129import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800130import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131import java.io.PrintWriter;
132import java.lang.IllegalStateException;
133import java.lang.ref.WeakReference;
134import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700135import java.util.Collections;
136import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137import java.util.HashMap;
138import java.util.HashSet;
139import java.util.Iterator;
140import java.util.List;
141import java.util.Locale;
142import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700143import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700144import java.util.concurrent.atomic.AtomicBoolean;
145import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700147public final class ActivityManagerService extends ActivityManagerNative
148 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 static final String TAG = "ActivityManager";
150 static final boolean DEBUG = false;
151 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
152 static final boolean DEBUG_SWITCH = localLOGV || false;
153 static final boolean DEBUG_TASKS = localLOGV || false;
154 static final boolean DEBUG_PAUSE = localLOGV || false;
155 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
156 static final boolean DEBUG_TRANSITION = localLOGV || false;
157 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700158 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700160 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static final boolean DEBUG_VISBILITY = localLOGV || false;
162 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700163 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800164 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700166 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700167 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700168 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700169 static final boolean DEBUG_POWER = localLOGV || false;
170 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 static final boolean VALIDATE_TOKENS = false;
172 static final boolean SHOW_ACTIVITY_START_TIME = true;
173
174 // Control over CPU and battery monitoring.
175 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
176 static final boolean MONITOR_CPU_USAGE = true;
177 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
178 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
179 static final boolean MONITOR_THREAD_CPU_USAGE = false;
180
Dianne Hackborn1655be42009-05-08 14:29:01 -0700181 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700182 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 private static final String SYSTEM_SECURE = "ro.secure";
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800185 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186
187 // This is the maximum number of application processes we would like
188 // to have running. Due to the asynchronous nature of things, we can
189 // temporarily go beyond this limit.
190 static final int MAX_PROCESSES = 2;
191
192 // Set to false to leave processes running indefinitely, relying on
193 // the kernel killing them as resources are required.
194 static final boolean ENFORCE_PROCESS_LIMIT = false;
195
196 // This is the maximum number of activities that we would like to have
197 // running at a given time.
198 static final int MAX_ACTIVITIES = 20;
199
200 // Maximum number of recent tasks that we can remember.
201 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700202
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700203 // Amount of time after a call to stopAppSwitches() during which we will
204 // prevent further untrusted switches from happening.
205 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206
207 // How long we wait for a launched process to attach to the activity manager
208 // before we decide it's never going to come up for real.
209 static final int PROC_START_TIMEOUT = 10*1000;
210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 // How long to wait after going idle before forcing apps to GC.
212 static final int GC_TIMEOUT = 5*1000;
213
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700214 // The minimum amount of time between successive GC requests for a process.
215 static final int GC_MIN_INTERVAL = 60*1000;
216
Dianne Hackborn287952c2010-09-22 22:34:31 -0700217 // The rate at which we check for apps using excessive power -- 15 mins.
218 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
219
220 // The minimum sample duration we will allow before deciding we have
221 // enough data on wake locks to start killing things.
222 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
223
224 // The minimum sample duration we will allow before deciding we have
225 // enough data on CPU usage to start killing things.
226 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 // How long we allow a receiver to run before giving up on it.
229 static final int BROADCAST_TIMEOUT = 10*1000;
230
231 // How long we wait for a service to finish executing.
232 static final int SERVICE_TIMEOUT = 20*1000;
233
234 // How long a service needs to be running until restarting its process
235 // is no longer considered to be a relaunch of the service.
236 static final int SERVICE_RESTART_DURATION = 5*1000;
237
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700238 // How long a service needs to be running until it will start back at
239 // SERVICE_RESTART_DURATION after being killed.
240 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
241
242 // Multiplying factor to increase restart duration time by, for each time
243 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
244 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
245
246 // The minimum amount of time between restarting services that we allow.
247 // That is, when multiple services are restarting, we won't allow each
248 // to restart less than this amount of time from the last one.
249 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 // Maximum amount of time for there to be no activity on a service before
252 // we consider it non-essential and allow its process to go on the
253 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700254 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255
256 // How long we wait until we timeout on key dispatching.
257 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
258
259 // The minimum time we allow between crashes, for us to consider this
260 // application to be bad and stop and its services and reject broadcasts.
261 static final int MIN_CRASH_INTERVAL = 60*1000;
262
263 // How long we wait until we timeout on key dispatching during instrumentation.
264 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
265
266 // OOM adjustments for processes in various states:
267
268 // This is a process without anything currently running in it. Definitely
269 // the first to go! Value set in system/rootdir/init.rc on startup.
270 // This value is initalized in the constructor, careful when refering to
271 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800272 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273
274 // This is a process only hosting activities that are not visible,
275 // so it can be killed without any disruption. Value set in
276 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800277 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 static int HIDDEN_APP_MIN_ADJ;
279
The Android Open Source Project4df24232009-03-05 14:34:35 -0800280 // This is a process holding the home application -- we want to try
281 // avoiding killing it, even if it would normally be in the background,
282 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800283 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800284
Christopher Tate6fa95972009-06-05 18:43:55 -0700285 // This is a process currently hosting a backup operation. Killing it
286 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 // This is a process holding a secondary server -- killing it will not
290 // have much of an impact as far as the user is concerned. Value set in
291 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800292 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700294 // This is a process with a heavy-weight application. It is in the
295 // background, but we want to try to avoid killing it. Value set in
296 // system/rootdir/init.rc on startup.
297 static final int HEAVY_WEIGHT_APP_ADJ;
298
299 // This is a process only hosting components that are perceptible to the
300 // user, and we really want to avoid killing them, but they are not
301 // immediately visible. An example is background music playback. Value set in
302 // system/rootdir/init.rc on startup.
303 static final int PERCEPTIBLE_APP_ADJ;
304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 // This is a process only hosting activities that are visible to the
306 // user, so we'd prefer they don't disappear. Value set in
307 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800308 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309
310 // This is the process running the current foreground app. We'd really
311 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800312 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313
314 // This is a process running a core server, such as telephony. Definitely
315 // don't want to kill it, but doing so is not completely fatal.
316 static final int CORE_SERVER_ADJ = -12;
317
318 // The system process runs at the default adjustment.
319 static final int SYSTEM_ADJ = -16;
320
321 // Memory pages are 4K.
322 static final int PAGE_SIZE = 4*1024;
323
324 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800325 static final int EMPTY_APP_MEM;
326 static final int HIDDEN_APP_MEM;
327 static final int HOME_APP_MEM;
328 static final int BACKUP_APP_MEM;
329 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700330 static final int HEAVY_WEIGHT_APP_MEM;
331 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800332 static final int VISIBLE_APP_MEM;
333 static final int FOREGROUND_APP_MEM;
334
335 // The minimum number of hidden apps we want to be able to keep around,
336 // without empty apps being able to push them out of memory.
337 static final int MIN_HIDDEN_APPS = 2;
338
Dianne Hackborn8633e682010-04-22 16:03:41 -0700339 // The maximum number of hidden processes we will keep around before
340 // killing them; this is just a control to not let us go too crazy with
341 // keeping around processes on devices with large amounts of RAM.
342 static final int MAX_HIDDEN_APPS = 15;
343
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800344 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700345 // been idle for less than 15 seconds.
346 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800347
348 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700349 // been idle for less than 120 seconds.
350 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800351
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700352 static int getIntProp(String name, boolean allowZero) {
353 String str = SystemProperties.get(name);
354 if (str == null) {
355 throw new IllegalArgumentException("Property not defined: " + name);
356 }
357 int val = Integer.valueOf(str);
358 if (val == 0 && !allowZero) {
359 throw new IllegalArgumentException("Property must not be zero: " + name);
360 }
361 return val;
362 }
363
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800364 static {
365 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700366 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
367 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
368 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
369 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
370 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
371 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
372 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
373 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
374 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
375 // These days we use the last empty slot for hidden apps as well.
376 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
377 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
378 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
379 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
380 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
381 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
382 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
383 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
384 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
385 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387
Dan Egnor42471dd2010-01-07 17:25:22 -0800388 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389
390 static final String[] EMPTY_STRING_ARRAY = new String[0];
391
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700392 public ActivityStack mMainStack;
393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700395 * Description of a request to start a new activity, which has been held
396 * due to app switches being disabled.
397 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700398 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700399 ActivityRecord r;
400 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700401 Uri[] grantedUriPermissions;
402 int grantedMode;
403 boolean onlyIfNeeded;
404 }
405
406 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
407 = new ArrayList<PendingActivityLaunch>();
408
409 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 * List of all active broadcasts that are to be executed immediately
411 * (without waiting for another broadcast to finish). Currently this only
412 * contains broadcasts to registered receivers, to avoid spinning up
413 * a bunch of processes to execute IntentReceiver components.
414 */
415 final ArrayList<BroadcastRecord> mParallelBroadcasts
416 = new ArrayList<BroadcastRecord>();
417
418 /**
419 * List of all active broadcasts that are to be executed one at a time.
420 * The object at the top of the list is the currently activity broadcasts;
421 * those after it are waiting for the top to finish..
422 */
423 final ArrayList<BroadcastRecord> mOrderedBroadcasts
424 = new ArrayList<BroadcastRecord>();
425
426 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800427 * Historical data of past broadcasts, for debugging.
428 */
429 static final int MAX_BROADCAST_HISTORY = 100;
430 final BroadcastRecord[] mBroadcastHistory
431 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
432
433 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 * Set when we current have a BROADCAST_INTENT_MSG in flight.
435 */
436 boolean mBroadcastsScheduled = false;
437
438 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 * Activity we have told the window manager to have key focus.
440 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700441 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700442 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 * List of intents that were used to start the most recent tasks.
444 */
445 final ArrayList<TaskRecord> mRecentTasks
446 = new ArrayList<TaskRecord>();
447
448 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 * All of the applications we currently have running organized by name.
450 * The keys are strings of the application package name (as
451 * returned by the package manager), and the keys are ApplicationRecord
452 * objects.
453 */
454 final ProcessMap<ProcessRecord> mProcessNames
455 = new ProcessMap<ProcessRecord>();
456
457 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700458 * The currently running heavy-weight process, if any.
459 */
460 ProcessRecord mHeavyWeightProcess = null;
461
462 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 * The last time that various processes have crashed.
464 */
465 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
466
467 /**
468 * Set of applications that we consider to be bad, and will reject
469 * incoming broadcasts from (which the user has no control over).
470 * Processes are added to this set when they have crashed twice within
471 * a minimum amount of time; they are removed from it when they are
472 * later restarted (hopefully due to some user action). The value is the
473 * time it was added to the list.
474 */
475 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
476
477 /**
478 * All of the processes we currently have running organized by pid.
479 * The keys are the pid running the application.
480 *
481 * <p>NOTE: This object is protected by its own lock, NOT the global
482 * activity manager lock!
483 */
484 final SparseArray<ProcessRecord> mPidsSelfLocked
485 = new SparseArray<ProcessRecord>();
486
487 /**
488 * All of the processes that have been forced to be foreground. The key
489 * is the pid of the caller who requested it (we hold a death
490 * link on it).
491 */
492 abstract class ForegroundToken implements IBinder.DeathRecipient {
493 int pid;
494 IBinder token;
495 }
496 final SparseArray<ForegroundToken> mForegroundProcesses
497 = new SparseArray<ForegroundToken>();
498
499 /**
500 * List of records for processes that someone had tried to start before the
501 * system was ready. We don't start them at that point, but ensure they
502 * are started by the time booting is complete.
503 */
504 final ArrayList<ProcessRecord> mProcessesOnHold
505 = new ArrayList<ProcessRecord>();
506
507 /**
508 * List of records for processes that we have started and are waiting
509 * for them to call back. This is really only needed when running in
510 * single processes mode, in which case we do not have a unique pid for
511 * each process.
512 */
513 final ArrayList<ProcessRecord> mStartingProcesses
514 = new ArrayList<ProcessRecord>();
515
516 /**
517 * List of persistent applications that are in the process
518 * of being started.
519 */
520 final ArrayList<ProcessRecord> mPersistentStartingProcesses
521 = new ArrayList<ProcessRecord>();
522
523 /**
524 * Processes that are being forcibly torn down.
525 */
526 final ArrayList<ProcessRecord> mRemovedProcesses
527 = new ArrayList<ProcessRecord>();
528
529 /**
530 * List of running applications, sorted by recent usage.
531 * The first entry in the list is the least recently used.
532 * It contains ApplicationRecord objects. This list does NOT include
533 * any persistent application records (since we never want to exit them).
534 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800535 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 = new ArrayList<ProcessRecord>();
537
538 /**
539 * List of processes that should gc as soon as things are idle.
540 */
541 final ArrayList<ProcessRecord> mProcessesToGc
542 = new ArrayList<ProcessRecord>();
543
544 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800545 * This is the process holding what we currently consider to be
546 * the "home" activity.
547 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700548 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800549
550 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 * Set of PendingResultRecord objects that are currently active.
552 */
553 final HashSet mPendingResultRecords = new HashSet();
554
555 /**
556 * Set of IntentSenderRecord objects that are currently active.
557 */
558 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
559 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
560
561 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800562 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700563 * already logged DropBox entries for. Guarded by itself. If
564 * something (rogue user app) forces this over
565 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
566 */
567 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
568 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
569
570 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700571 * Strict Mode background batched logging state.
572 *
573 * The string buffer is guarded by itself, and its lock is also
574 * used to determine if another batched write is already
575 * in-flight.
576 */
577 private final StringBuilder mStrictModeBuffer = new StringBuilder();
578
579 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700580 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
581 */
582 private boolean mPendingBroadcastTimeoutMessage;
583
584 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 * Intent broadcast that we have tried to start, but are
586 * waiting for its application's process to be created. We only
587 * need one (instead of a list) because we always process broadcasts
588 * one at a time, so no others can be started while waiting for this
589 * one.
590 */
591 BroadcastRecord mPendingBroadcast = null;
592
593 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700594 * The receiver index that is pending, to restart the broadcast if needed.
595 */
596 int mPendingBroadcastRecvIndex;
597
598 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599 * Keeps track of all IIntentReceivers that have been registered for
600 * broadcasts. Hash keys are the receiver IBinder, hash value is
601 * a ReceiverList.
602 */
603 final HashMap mRegisteredReceivers = new HashMap();
604
605 /**
606 * Resolver for broadcast intents to registered receivers.
607 * Holds BroadcastFilter (subclass of IntentFilter).
608 */
609 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
610 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
611 @Override
612 protected boolean allowFilterResult(
613 BroadcastFilter filter, List<BroadcastFilter> dest) {
614 IBinder target = filter.receiverList.receiver.asBinder();
615 for (int i=dest.size()-1; i>=0; i--) {
616 if (dest.get(i).receiverList.receiver.asBinder() == target) {
617 return false;
618 }
619 }
620 return true;
621 }
622 };
623
624 /**
625 * State of all active sticky broadcasts. Keys are the action of the
626 * sticky Intent, values are an ArrayList of all broadcasted intents with
627 * that action (which should usually be one).
628 */
629 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
630 new HashMap<String, ArrayList<Intent>>();
631
632 /**
633 * All currently running services.
634 */
635 final HashMap<ComponentName, ServiceRecord> mServices =
636 new HashMap<ComponentName, ServiceRecord>();
637
638 /**
639 * All currently running services indexed by the Intent used to start them.
640 */
641 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
642 new HashMap<Intent.FilterComparison, ServiceRecord>();
643
644 /**
645 * All currently bound service connections. Keys are the IBinder of
646 * the client's IServiceConnection.
647 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700648 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
649 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650
651 /**
652 * List of services that we have been asked to start,
653 * but haven't yet been able to. It is used to hold start requests
654 * while waiting for their corresponding application thread to get
655 * going.
656 */
657 final ArrayList<ServiceRecord> mPendingServices
658 = new ArrayList<ServiceRecord>();
659
660 /**
661 * List of services that are scheduled to restart following a crash.
662 */
663 final ArrayList<ServiceRecord> mRestartingServices
664 = new ArrayList<ServiceRecord>();
665
666 /**
667 * List of services that are in the process of being stopped.
668 */
669 final ArrayList<ServiceRecord> mStoppingServices
670 = new ArrayList<ServiceRecord>();
671
672 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700673 * Backup/restore process management
674 */
675 String mBackupAppName = null;
676 BackupRecord mBackupTarget = null;
677
678 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679 * List of PendingThumbnailsRecord objects of clients who are still
680 * waiting to receive all of the thumbnails for a task.
681 */
682 final ArrayList mPendingThumbnails = new ArrayList();
683
684 /**
685 * List of HistoryRecord objects that have been finished and must
686 * still report back to a pending thumbnail receiver.
687 */
688 final ArrayList mCancelledThumbnails = new ArrayList();
689
690 /**
691 * All of the currently running global content providers. Keys are a
692 * string containing the provider name and values are a
693 * ContentProviderRecord object containing the data about it. Note
694 * that a single provider may be published under multiple names, so
695 * there may be multiple entries here for a single one in mProvidersByClass.
696 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700697 final HashMap<String, ContentProviderRecord> mProvidersByName
698 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800699
700 /**
701 * All of the currently running global content providers. Keys are a
702 * string containing the provider's implementation class and values are a
703 * ContentProviderRecord object containing the data about it.
704 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700705 final HashMap<String, ContentProviderRecord> mProvidersByClass
706 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707
708 /**
709 * List of content providers who have clients waiting for them. The
710 * application is currently being launched and the provider will be
711 * removed from this list once it is published.
712 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700713 final ArrayList<ContentProviderRecord> mLaunchingProviders
714 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715
716 /**
717 * Global set of specific Uri permissions that have been granted.
718 */
719 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
720 = new SparseArray<HashMap<Uri, UriPermission>>();
721
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800722 CoreSettingsObserver mCoreSettingsObserver;
723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 /**
725 * Thread-local storage used to carry caller permissions over through
726 * indirect content-provider access.
727 * @see #ActivityManagerService.openContentUri()
728 */
729 private class Identity {
730 public int pid;
731 public int uid;
732
733 Identity(int _pid, int _uid) {
734 pid = _pid;
735 uid = _uid;
736 }
737 }
738 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
739
740 /**
741 * All information we have collected about the runtime performance of
742 * any user id that can impact battery performance.
743 */
744 final BatteryStatsService mBatteryStatsService;
745
746 /**
747 * information about component usage
748 */
749 final UsageStatsService mUsageStatsService;
750
751 /**
752 * Current configuration information. HistoryRecord objects are given
753 * a reference to this object to indicate which configuration they are
754 * currently running in, so this object must be kept immutable.
755 */
756 Configuration mConfiguration = new Configuration();
757
758 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800759 * Current sequencing integer of the configuration, for skipping old
760 * configurations.
761 */
762 int mConfigurationSeq = 0;
763
764 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700765 * Hardware-reported OpenGLES version.
766 */
767 final int GL_ES_VERSION;
768
769 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 * List of initialization arguments to pass to all processes when binding applications to them.
771 * For example, references to the commonly used services.
772 */
773 HashMap<String, IBinder> mAppBindArgs;
774
775 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700776 * Temporary to avoid allocations. Protected by main lock.
777 */
778 final StringBuilder mStringBuilder = new StringBuilder(256);
779
780 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 * Used to control how we initialize the service.
782 */
783 boolean mStartRunning = false;
784 ComponentName mTopComponent;
785 String mTopAction;
786 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700787 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 boolean mSystemReady = false;
789 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700790 boolean mWaitingUpdate = false;
791 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700792 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700793 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794
795 Context mContext;
796
797 int mFactoryTest;
798
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700799 boolean mCheckedForSetup;
800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700802 * The time at which we will allow normal application switches again,
803 * after a call to {@link #stopAppSwitches()}.
804 */
805 long mAppSwitchesAllowedTime;
806
807 /**
808 * This is set to true after the first switch after mAppSwitchesAllowedTime
809 * is set; any switches after that will clear the time.
810 */
811 boolean mDidAppSwitch;
812
813 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700814 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700815 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700816 long mLastPowerCheckRealtime;
817
818 /**
819 * Last time (in uptime) at which we checked for power usage.
820 */
821 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700822
823 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824 * Set while we are wanting to sleep, to prevent any
825 * activities from being started/resumed.
826 */
827 boolean mSleeping = false;
828
829 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700830 * Set if we are shutting down the system, similar to sleeping.
831 */
832 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833
834 /**
835 * Task identifier that activities are currently being started
836 * in. Incremented each time a new task is created.
837 * todo: Replace this with a TokenSpace class that generates non-repeating
838 * integers that won't wrap.
839 */
840 int mCurTask = 1;
841
842 /**
843 * Current sequence id for oom_adj computation traversal.
844 */
845 int mAdjSeq = 0;
846
847 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700848 * Current sequence id for process LRU updating.
849 */
850 int mLruSeq = 0;
851
852 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
854 * is set, indicating the user wants processes started in such a way
855 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
856 * running in each process (thus no pre-initialized process, etc).
857 */
858 boolean mSimpleProcessManagement = false;
859
860 /**
861 * System monitoring: number of processes that died since the last
862 * N procs were started.
863 */
864 int[] mProcDeaths = new int[20];
865
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700866 /**
867 * This is set if we had to do a delayed dexopt of an app before launching
868 * it, to increasing the ANR timeouts in that case.
869 */
870 boolean mDidDexOpt;
871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 String mDebugApp = null;
873 boolean mWaitForDebugger = false;
874 boolean mDebugTransient = false;
875 String mOrigDebugApp = null;
876 boolean mOrigWaitForDebugger = false;
877 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700878 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700880 final RemoteCallbackList<IActivityWatcher> mWatchers
881 = new RemoteCallbackList<IActivityWatcher>();
882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 /**
884 * Callback of last caller to {@link #requestPss}.
885 */
886 Runnable mRequestPssCallback;
887
888 /**
889 * Remaining processes for which we are waiting results from the last
890 * call to {@link #requestPss}.
891 */
892 final ArrayList<ProcessRecord> mRequestPssList
893 = new ArrayList<ProcessRecord>();
894
895 /**
896 * Runtime statistics collection thread. This object's lock is used to
897 * protect all related state.
898 */
899 final Thread mProcessStatsThread;
900
901 /**
902 * Used to collect process stats when showing not responding dialog.
903 * Protected by mProcessStatsThread.
904 */
905 final ProcessStats mProcessStats = new ProcessStats(
906 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700907 final AtomicLong mLastCpuTime = new AtomicLong(0);
908 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 long mLastWriteTime = 0;
911
912 /**
913 * Set to true after the system has finished booting.
914 */
915 boolean mBooted = false;
916
917 int mProcessLimit = 0;
918
919 WindowManagerService mWindowManager;
920
921 static ActivityManagerService mSelf;
922 static ActivityThread mSystemThread;
923
924 private final class AppDeathRecipient implements IBinder.DeathRecipient {
925 final ProcessRecord mApp;
926 final int mPid;
927 final IApplicationThread mAppThread;
928
929 AppDeathRecipient(ProcessRecord app, int pid,
930 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800931 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 TAG, "New death recipient " + this
933 + " for thread " + thread.asBinder());
934 mApp = app;
935 mPid = pid;
936 mAppThread = thread;
937 }
938
939 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800940 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 TAG, "Death received in " + this
942 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943 synchronized(ActivityManagerService.this) {
944 appDiedLocked(mApp, mPid, mAppThread);
945 }
946 }
947 }
948
949 static final int SHOW_ERROR_MSG = 1;
950 static final int SHOW_NOT_RESPONDING_MSG = 2;
951 static final int SHOW_FACTORY_ERROR_MSG = 3;
952 static final int UPDATE_CONFIGURATION_MSG = 4;
953 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
954 static final int WAIT_FOR_DEBUGGER_MSG = 6;
955 static final int BROADCAST_INTENT_MSG = 7;
956 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 static final int SERVICE_TIMEOUT_MSG = 12;
958 static final int UPDATE_TIME_ZONE = 13;
959 static final int SHOW_UID_ERROR_MSG = 14;
960 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700962 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700963 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800964 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700965 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
966 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700967 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700968 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700969 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700970 static final int UPDATE_HTTP_PROXY = 29;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971
972 AlertDialog mUidAlert;
973
974 final Handler mHandler = new Handler() {
975 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800976 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 //}
978
979 public void handleMessage(Message msg) {
980 switch (msg.what) {
981 case SHOW_ERROR_MSG: {
982 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 synchronized (ActivityManagerService.this) {
984 ProcessRecord proc = (ProcessRecord)data.get("app");
985 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800986 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 return;
988 }
989 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700990 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800991 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 d.show();
993 proc.crashDialog = d;
994 } else {
995 // The device is asleep, so just pretend that the user
996 // saw a crash dialog and hit "force quit".
997 res.set(0);
998 }
999 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001000
1001 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 } break;
1003 case SHOW_NOT_RESPONDING_MSG: {
1004 synchronized (ActivityManagerService.this) {
1005 HashMap data = (HashMap) msg.obj;
1006 ProcessRecord proc = (ProcessRecord)data.get("app");
1007 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001008 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 return;
1010 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001011
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001012 Intent intent = new Intent("android.intent.action.ANR");
1013 if (!mProcessesReady) {
1014 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1015 }
1016 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001017 null, null, 0, null, null, null,
1018 false, false, MY_PID, Process.SYSTEM_UID);
1019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001021 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 d.show();
1023 proc.anrDialog = d;
1024 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001025
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001026 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001028 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1029 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1030 synchronized (ActivityManagerService.this) {
1031 ProcessRecord proc = (ProcessRecord) data.get("app");
1032 if (proc == null) {
1033 Slog.e(TAG, "App not found when showing strict mode dialog.");
1034 break;
1035 }
1036 if (proc.crashDialog != null) {
1037 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1038 return;
1039 }
1040 AppErrorResult res = (AppErrorResult) data.get("result");
1041 if (!mSleeping && !mShuttingDown) {
1042 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1043 d.show();
1044 proc.crashDialog = d;
1045 } else {
1046 // The device is asleep, so just pretend that the user
1047 // saw a crash dialog and hit "force quit".
1048 res.set(0);
1049 }
1050 }
1051 ensureBootCompleted();
1052 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 case SHOW_FACTORY_ERROR_MSG: {
1054 Dialog d = new FactoryErrorDialog(
1055 mContext, msg.getData().getCharSequence("msg"));
1056 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001057 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 } break;
1059 case UPDATE_CONFIGURATION_MSG: {
1060 final ContentResolver resolver = mContext.getContentResolver();
1061 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1062 } break;
1063 case GC_BACKGROUND_PROCESSES_MSG: {
1064 synchronized (ActivityManagerService.this) {
1065 performAppGcsIfAppropriateLocked();
1066 }
1067 } break;
1068 case WAIT_FOR_DEBUGGER_MSG: {
1069 synchronized (ActivityManagerService.this) {
1070 ProcessRecord app = (ProcessRecord)msg.obj;
1071 if (msg.arg1 != 0) {
1072 if (!app.waitedForDebugger) {
1073 Dialog d = new AppWaitingForDebuggerDialog(
1074 ActivityManagerService.this,
1075 mContext, app);
1076 app.waitDialog = d;
1077 app.waitedForDebugger = true;
1078 d.show();
1079 }
1080 } else {
1081 if (app.waitDialog != null) {
1082 app.waitDialog.dismiss();
1083 app.waitDialog = null;
1084 }
1085 }
1086 }
1087 } break;
1088 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001089 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 TAG, "Received BROADCAST_INTENT_MSG");
1091 processNextBroadcast(true);
1092 } break;
1093 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001094 synchronized (ActivityManagerService.this) {
1095 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001099 if (mDidDexOpt) {
1100 mDidDexOpt = false;
1101 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1102 nmsg.obj = msg.obj;
1103 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1104 return;
1105 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 serviceTimeout((ProcessRecord)msg.obj);
1107 } break;
1108 case UPDATE_TIME_ZONE: {
1109 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001110 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1111 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 if (r.thread != null) {
1113 try {
1114 r.thread.updateTimeZone();
1115 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001116 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001117 }
1118 }
1119 }
1120 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001121 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001122 case CLEAR_DNS_CACHE: {
1123 synchronized (ActivityManagerService.this) {
1124 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1125 ProcessRecord r = mLruProcesses.get(i);
1126 if (r.thread != null) {
1127 try {
1128 r.thread.clearDnsCache();
1129 } catch (RemoteException ex) {
1130 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1131 }
1132 }
1133 }
1134 }
1135 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001136 case UPDATE_HTTP_PROXY: {
1137 ProxyProperties proxy = (ProxyProperties)msg.obj;
1138 String host = "";
1139 String port = "";
1140 String exclList = "";
1141 if (proxy != null) {
1142 host = proxy.getHost();
1143 port = Integer.toString(proxy.getPort());
1144 exclList = proxy.getExclusionList();
1145 }
1146 synchronized (ActivityManagerService.this) {
1147 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1148 ProcessRecord r = mLruProcesses.get(i);
1149 if (r.thread != null) {
1150 try {
1151 r.thread.setHttpProxy(host, port, exclList);
1152 } catch (RemoteException ex) {
1153 Slog.w(TAG, "Failed to update http proxy for: " +
1154 r.info.processName);
1155 }
1156 }
1157 }
1158 }
1159 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 case SHOW_UID_ERROR_MSG: {
1161 // XXX This is a temporary dialog, no need to localize.
1162 AlertDialog d = new BaseErrorDialog(mContext);
1163 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1164 d.setCancelable(false);
1165 d.setTitle("System UIDs Inconsistent");
1166 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
Christian Mehlmauer7664e202010-07-20 08:46:17 +02001167 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1169 mUidAlert = d;
1170 d.show();
1171 } break;
1172 case IM_FEELING_LUCKY_MSG: {
1173 if (mUidAlert != null) {
1174 mUidAlert.dismiss();
1175 mUidAlert = null;
1176 }
1177 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001179 if (mDidDexOpt) {
1180 mDidDexOpt = false;
1181 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1182 nmsg.obj = msg.obj;
1183 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1184 return;
1185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 ProcessRecord app = (ProcessRecord)msg.obj;
1187 synchronized (ActivityManagerService.this) {
1188 processStartTimedOutLocked(app);
1189 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001190 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001191 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1192 synchronized (ActivityManagerService.this) {
1193 doPendingActivityLaunchesLocked(true);
1194 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001195 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001196 case KILL_APPLICATION_MSG: {
1197 synchronized (ActivityManagerService.this) {
1198 int uid = msg.arg1;
1199 boolean restart = (msg.arg2 == 1);
1200 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001201 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001202 }
1203 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001204 case FINALIZE_PENDING_INTENT_MSG: {
1205 ((PendingIntentRecord)msg.obj).completeFinalize();
1206 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001207 case POST_HEAVY_NOTIFICATION_MSG: {
1208 INotificationManager inm = NotificationManager.getService();
1209 if (inm == null) {
1210 return;
1211 }
1212
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001213 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001214 ProcessRecord process = root.app;
1215 if (process == null) {
1216 return;
1217 }
1218
1219 try {
1220 Context context = mContext.createPackageContext(process.info.packageName, 0);
1221 String text = mContext.getString(R.string.heavy_weight_notification,
1222 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1223 Notification notification = new Notification();
1224 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1225 notification.when = 0;
1226 notification.flags = Notification.FLAG_ONGOING_EVENT;
1227 notification.tickerText = text;
1228 notification.defaults = 0; // please be quiet
1229 notification.sound = null;
1230 notification.vibrate = null;
1231 notification.setLatestEventInfo(context, text,
1232 mContext.getText(R.string.heavy_weight_notification_detail),
1233 PendingIntent.getActivity(mContext, 0, root.intent,
1234 PendingIntent.FLAG_CANCEL_CURRENT));
1235
1236 try {
1237 int[] outId = new int[1];
1238 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1239 notification, outId);
1240 } catch (RuntimeException e) {
1241 Slog.w(ActivityManagerService.TAG,
1242 "Error showing notification for heavy-weight app", e);
1243 } catch (RemoteException e) {
1244 }
1245 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001246 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001247 }
1248 } break;
1249 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1250 INotificationManager inm = NotificationManager.getService();
1251 if (inm == null) {
1252 return;
1253 }
1254 try {
1255 inm.cancelNotification("android",
1256 R.string.heavy_weight_notification);
1257 } catch (RuntimeException e) {
1258 Slog.w(ActivityManagerService.TAG,
1259 "Error canceling notification for service", e);
1260 } catch (RemoteException e) {
1261 }
1262 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001263 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1264 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001265 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001266 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001267 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1268 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001269 }
1270 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001271 }
1272 }
1273 };
1274
1275 public static void setSystemProcess() {
1276 try {
1277 ActivityManagerService m = mSelf;
1278
1279 ServiceManager.addService("activity", m);
1280 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07001281 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282 if (MONITOR_CPU_USAGE) {
1283 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285 ServiceManager.addService("permission", new PermissionController(m));
1286
1287 ApplicationInfo info =
1288 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001289 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001290 mSystemThread.installSystemApplicationInfo(info);
1291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 synchronized (mSelf) {
1293 ProcessRecord app = mSelf.newProcessRecordLocked(
1294 mSystemThread.getApplicationThread(), info,
1295 info.processName);
1296 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001297 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298 app.maxAdj = SYSTEM_ADJ;
1299 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1300 synchronized (mSelf.mPidsSelfLocked) {
1301 mSelf.mPidsSelfLocked.put(app.pid, app);
1302 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001303 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304 }
1305 } catch (PackageManager.NameNotFoundException e) {
1306 throw new RuntimeException(
1307 "Unable to find android system package", e);
1308 }
1309 }
1310
1311 public void setWindowManager(WindowManagerService wm) {
1312 mWindowManager = wm;
1313 }
1314
1315 public static final Context main(int factoryTest) {
1316 AThread thr = new AThread();
1317 thr.start();
1318
1319 synchronized (thr) {
1320 while (thr.mService == null) {
1321 try {
1322 thr.wait();
1323 } catch (InterruptedException e) {
1324 }
1325 }
1326 }
1327
1328 ActivityManagerService m = thr.mService;
1329 mSelf = m;
1330 ActivityThread at = ActivityThread.systemMain();
1331 mSystemThread = at;
1332 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001333 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334 m.mContext = context;
1335 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001336 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337
1338 m.mBatteryStatsService.publish(context);
1339 m.mUsageStatsService.publish(context);
1340
1341 synchronized (thr) {
1342 thr.mReady = true;
1343 thr.notifyAll();
1344 }
1345
1346 m.startRunning(null, null, null, null);
1347
1348 return context;
1349 }
1350
1351 public static ActivityManagerService self() {
1352 return mSelf;
1353 }
1354
1355 static class AThread extends Thread {
1356 ActivityManagerService mService;
1357 boolean mReady = false;
1358
1359 public AThread() {
1360 super("ActivityManager");
1361 }
1362
1363 public void run() {
1364 Looper.prepare();
1365
1366 android.os.Process.setThreadPriority(
1367 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001368 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369
1370 ActivityManagerService m = new ActivityManagerService();
1371
1372 synchronized (this) {
1373 mService = m;
1374 notifyAll();
1375 }
1376
1377 synchronized (this) {
1378 while (!mReady) {
1379 try {
1380 wait();
1381 } catch (InterruptedException e) {
1382 }
1383 }
1384 }
1385
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001386 // For debug builds, log event loop stalls to dropbox for analysis.
1387 if (StrictMode.conditionallyEnableDebugLogging()) {
1388 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1389 }
1390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 Looper.loop();
1392 }
1393 }
1394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 static class MemBinder extends Binder {
1396 ActivityManagerService mActivityManagerService;
1397 MemBinder(ActivityManagerService activityManagerService) {
1398 mActivityManagerService = activityManagerService;
1399 }
1400
1401 @Override
1402 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001403 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 }
1405 }
1406
Chet Haase9c1e23b2011-03-24 10:51:31 -07001407 static class GraphicsBinder extends Binder {
1408 ActivityManagerService mActivityManagerService;
1409 GraphicsBinder(ActivityManagerService activityManagerService) {
1410 mActivityManagerService = activityManagerService;
1411 }
1412
1413 @Override
1414 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001415 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07001416 }
1417 }
1418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 static class CpuBinder extends Binder {
1420 ActivityManagerService mActivityManagerService;
1421 CpuBinder(ActivityManagerService activityManagerService) {
1422 mActivityManagerService = activityManagerService;
1423 }
1424
1425 @Override
1426 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1427 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001428 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1429 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1430 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431 }
1432 }
1433 }
1434
1435 private ActivityManagerService() {
1436 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1437 if (v != null && Integer.getInteger(v) != 0) {
1438 mSimpleProcessManagement = true;
1439 }
1440 v = System.getenv("ANDROID_DEBUG_APP");
1441 if (v != null) {
1442 mSimpleProcessManagement = true;
1443 }
1444
Joe Onorato8a9b2202010-02-26 18:56:32 -08001445 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 File dataDir = Environment.getDataDirectory();
1448 File systemDir = new File(dataDir, "system");
1449 systemDir.mkdirs();
1450 mBatteryStatsService = new BatteryStatsService(new File(
1451 systemDir, "batterystats.bin").toString());
1452 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001453 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001454 mOnBattery = DEBUG_POWER ? true
1455 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001456 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001458 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001459 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460
Jack Palevichb90d28c2009-07-22 15:35:24 -07001461 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1462 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1463
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001464 mConfiguration.setToDefaults();
1465 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 mProcessStats.init();
1467
1468 // Add ourself to the Watchdog monitors.
1469 Watchdog.getInstance().addMonitor(this);
1470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 mProcessStatsThread = new Thread("ProcessStats") {
1472 public void run() {
1473 while (true) {
1474 try {
1475 try {
1476 synchronized(this) {
1477 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001478 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001480 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 // + ", write delay=" + nextWriteDelay);
1482 if (nextWriteDelay < nextCpuDelay) {
1483 nextCpuDelay = nextWriteDelay;
1484 }
1485 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001486 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 this.wait(nextCpuDelay);
1488 }
1489 }
1490 } catch (InterruptedException e) {
1491 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 updateCpuStatsNow();
1493 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001494 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 }
1496 }
1497 }
1498 };
1499 mProcessStatsThread.start();
1500 }
1501
1502 @Override
1503 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1504 throws RemoteException {
1505 try {
1506 return super.onTransact(code, data, reply, flags);
1507 } catch (RuntimeException e) {
1508 // The activity manager only throws security exceptions, so let's
1509 // log all others.
1510 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001511 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 }
1513 throw e;
1514 }
1515 }
1516
1517 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001518 final long now = SystemClock.uptimeMillis();
1519 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1520 return;
1521 }
1522 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1523 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 mProcessStatsThread.notify();
1525 }
1526 }
1527 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 void updateCpuStatsNow() {
1530 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001531 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 final long now = SystemClock.uptimeMillis();
1533 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001536 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1537 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 haveNewCpuStats = true;
1539 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001540 //Slog.i(TAG, mProcessStats.printCurrentState());
1541 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 // + mProcessStats.getTotalCpuPercent() + "%");
1543
Joe Onorato8a9b2202010-02-26 18:56:32 -08001544 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 if ("true".equals(SystemProperties.get("events.cpu"))) {
1546 int user = mProcessStats.getLastUserTime();
1547 int system = mProcessStats.getLastSystemTime();
1548 int iowait = mProcessStats.getLastIoWaitTime();
1549 int irq = mProcessStats.getLastIrqTime();
1550 int softIrq = mProcessStats.getLastSoftIrqTime();
1551 int idle = mProcessStats.getLastIdleTime();
1552
1553 int total = user + system + iowait + irq + softIrq + idle;
1554 if (total == 0) total = 1;
1555
Doug Zongker2bec3d42009-12-04 12:52:44 -08001556 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 ((user+system+iowait+irq+softIrq) * 100) / total,
1558 (user * 100) / total,
1559 (system * 100) / total,
1560 (iowait * 100) / total,
1561 (irq * 100) / total,
1562 (softIrq * 100) / total);
1563 }
1564 }
1565
Amith Yamasanie43530a2009-08-21 13:11:37 -07001566 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001567 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001568 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 synchronized(mPidsSelfLocked) {
1570 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001571 if (mOnBattery) {
1572 int perc = bstats.startAddingCpuLocked();
1573 int totalUTime = 0;
1574 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001575 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001577 ProcessStats.Stats st = mProcessStats.getStats(i);
1578 if (!st.working) {
1579 continue;
1580 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001582 int otherUTime = (st.rel_utime*perc)/100;
1583 int otherSTime = (st.rel_stime*perc)/100;
1584 totalUTime += otherUTime;
1585 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 if (pr != null) {
1587 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001588 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1589 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001590 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001591 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001592 } else {
1593 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001594 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001595 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001596 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1597 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001598 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001599 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 }
1601 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001602 bstats.finishAddingCpuLocked(perc, totalUTime,
1603 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 }
1605 }
1606 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1609 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001610 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 }
1612 }
1613 }
1614 }
1615
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001616 @Override
1617 public void batteryNeedsCpuUpdate() {
1618 updateCpuStatsNow();
1619 }
1620
1621 @Override
1622 public void batteryPowerChanged(boolean onBattery) {
1623 // When plugging in, update the CPU stats first before changing
1624 // the plug state.
1625 updateCpuStatsNow();
1626 synchronized (this) {
1627 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001628 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001629 }
1630 }
1631 }
1632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001633 /**
1634 * Initialize the application bind args. These are passed to each
1635 * process when the bindApplication() IPC is sent to the process. They're
1636 * lazily setup to make sure the services are running when they're asked for.
1637 */
1638 private HashMap<String, IBinder> getCommonServicesLocked() {
1639 if (mAppBindArgs == null) {
1640 mAppBindArgs = new HashMap<String, IBinder>();
1641
1642 // Setup the application init args
1643 mAppBindArgs.put("package", ServiceManager.getService("package"));
1644 mAppBindArgs.put("window", ServiceManager.getService("window"));
1645 mAppBindArgs.put(Context.ALARM_SERVICE,
1646 ServiceManager.getService(Context.ALARM_SERVICE));
1647 }
1648 return mAppBindArgs;
1649 }
1650
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001651 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 if (mFocusedActivity != r) {
1653 mFocusedActivity = r;
1654 mWindowManager.setFocusedApp(r, true);
1655 }
1656 }
1657
Dianne Hackborn906497c2010-05-10 15:57:38 -07001658 private final void updateLruProcessInternalLocked(ProcessRecord app,
1659 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001661 int lrui = mLruProcesses.indexOf(app);
1662 if (lrui >= 0) mLruProcesses.remove(lrui);
1663
1664 int i = mLruProcesses.size()-1;
1665 int skipTop = 0;
1666
Dianne Hackborn906497c2010-05-10 15:57:38 -07001667 app.lruSeq = mLruSeq;
1668
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001669 // compute the new weight for this process.
1670 if (updateActivityTime) {
1671 app.lastActivityTime = SystemClock.uptimeMillis();
1672 }
1673 if (app.activities.size() > 0) {
1674 // If this process has activities, we more strongly want to keep
1675 // it around.
1676 app.lruWeight = app.lastActivityTime;
1677 } else if (app.pubProviders.size() > 0) {
1678 // If this process contains content providers, we want to keep
1679 // it a little more strongly.
1680 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1681 // Also don't let it kick out the first few "real" hidden processes.
1682 skipTop = MIN_HIDDEN_APPS;
1683 } else {
1684 // If this process doesn't have activities, we less strongly
1685 // want to keep it around, and generally want to avoid getting
1686 // in front of any very recently used activities.
1687 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1688 // Also don't let it kick out the first few "real" hidden processes.
1689 skipTop = MIN_HIDDEN_APPS;
1690 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001691
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001692 while (i >= 0) {
1693 ProcessRecord p = mLruProcesses.get(i);
1694 // If this app shouldn't be in front of the first N background
1695 // apps, then skip over that many that are currently hidden.
1696 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1697 skipTop--;
1698 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001699 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001700 mLruProcesses.add(i+1, app);
1701 break;
1702 }
1703 i--;
1704 }
1705 if (i < 0) {
1706 mLruProcesses.add(0, app);
1707 }
1708
Dianne Hackborn906497c2010-05-10 15:57:38 -07001709 // If the app is currently using a content provider or service,
1710 // bump those processes as well.
1711 if (app.connections.size() > 0) {
1712 for (ConnectionRecord cr : app.connections) {
1713 if (cr.binding != null && cr.binding.service != null
1714 && cr.binding.service.app != null
1715 && cr.binding.service.app.lruSeq != mLruSeq) {
1716 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1717 updateActivityTime, i+1);
1718 }
1719 }
1720 }
1721 if (app.conProviders.size() > 0) {
1722 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1723 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1724 updateLruProcessInternalLocked(cpr.app, oomAdj,
1725 updateActivityTime, i+1);
1726 }
1727 }
1728 }
1729
Joe Onorato8a9b2202010-02-26 18:56:32 -08001730 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 if (oomAdj) {
1732 updateOomAdjLocked();
1733 }
1734 }
1735
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001736 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001737 boolean oomAdj, boolean updateActivityTime) {
1738 mLruSeq++;
1739 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1740 }
1741
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001742 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 String processName, int uid) {
1744 if (uid == Process.SYSTEM_UID) {
1745 // The system gets to run in any process. If there are multiple
1746 // processes with the same uid, just pick the first (this
1747 // should never happen).
1748 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1749 processName);
1750 return procs != null ? procs.valueAt(0) : null;
1751 }
1752 ProcessRecord proc = mProcessNames.get(processName, uid);
1753 return proc;
1754 }
1755
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001756 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001757 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001758 try {
1759 if (pm.performDexOpt(packageName)) {
1760 mDidDexOpt = true;
1761 }
1762 } catch (RemoteException e) {
1763 }
1764 }
1765
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001766 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 int transit = mWindowManager.getPendingAppTransition();
1768 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1769 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1770 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1771 }
1772
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001773 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001775 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1777 // We don't have to do anything more if:
1778 // (1) There is an existing application record; and
1779 // (2) The caller doesn't think it is dead, OR there is no thread
1780 // object attached to it so we know it couldn't have crashed; and
1781 // (3) There is a pid assigned to it, so it is either starting or
1782 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001783 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 + " app=" + app + " knownToBeDead=" + knownToBeDead
1785 + " thread=" + (app != null ? app.thread : null)
1786 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001787 if (app != null && app.pid > 0) {
1788 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001789 // We already have the app running, or are waiting for it to
1790 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001791 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001792 return app;
1793 } else {
1794 // An application record is attached to a previous process,
1795 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001796 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001797 handleAppDiedLocked(app, true);
1798 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 String hostingNameStr = hostingName != null
1802 ? hostingName.flattenToShortString() : null;
1803
1804 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1805 // If we are in the background, then check to see if this process
1806 // is bad. If so, we will just silently fail.
1807 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001808 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1809 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810 return null;
1811 }
1812 } else {
1813 // When the user is explicitly starting a process, then clear its
1814 // crash count so that we won't make it bad until they see at
1815 // least one crash dialog again, and make the process good again
1816 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001817 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1818 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001819 mProcessCrashTimes.remove(info.processName, info.uid);
1820 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001821 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 info.processName);
1823 mBadProcesses.remove(info.processName, info.uid);
1824 if (app != null) {
1825 app.bad = false;
1826 }
1827 }
1828 }
1829
1830 if (app == null) {
1831 app = newProcessRecordLocked(null, info, processName);
1832 mProcessNames.put(processName, info.uid, app);
1833 } else {
1834 // If this is a new package in the process, add the package to the list
1835 app.addPackage(info.packageName);
1836 }
1837
1838 // If the system is not ready yet, then hold off on starting this
1839 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001840 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001841 && !isAllowedWhileBooting(info)
1842 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 if (!mProcessesOnHold.contains(app)) {
1844 mProcessesOnHold.add(app);
1845 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001846 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 return app;
1848 }
1849
1850 startProcessLocked(app, hostingType, hostingNameStr);
1851 return (app.pid != 0) ? app : null;
1852 }
1853
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001854 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1855 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1856 }
1857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001858 private final void startProcessLocked(ProcessRecord app,
1859 String hostingType, String hostingNameStr) {
1860 if (app.pid > 0 && app.pid != MY_PID) {
1861 synchronized (mPidsSelfLocked) {
1862 mPidsSelfLocked.remove(app.pid);
1863 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1864 }
1865 app.pid = 0;
1866 }
1867
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001868 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1869 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 mProcessesOnHold.remove(app);
1871
1872 updateCpuStats();
1873
1874 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1875 mProcDeaths[0] = 0;
1876
1877 try {
1878 int uid = app.info.uid;
1879 int[] gids = null;
1880 try {
1881 gids = mContext.getPackageManager().getPackageGids(
1882 app.info.packageName);
1883 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001884 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 }
1886 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1887 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1888 && mTopComponent != null
1889 && app.processName.equals(mTopComponent.getPackageName())) {
1890 uid = 0;
1891 }
1892 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1893 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1894 uid = 0;
1895 }
1896 }
1897 int debugFlags = 0;
1898 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1899 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1900 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001901 // Run the app in safe mode if its manifest requests so or the
1902 // system is booted in safe mode.
1903 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1904 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001905 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1906 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001907 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1908 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1909 }
1910 if ("1".equals(SystemProperties.get("debug.assert"))) {
1911 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1912 }
1913 int pid = Process.start("android.app.ActivityThread",
1914 mSimpleProcessManagement ? app.processName : null, uid, uid,
1915 gids, debugFlags, null);
1916 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1917 synchronized (bs) {
1918 if (bs.isOnBattery()) {
1919 app.batteryStats.incStartsLocked();
1920 }
1921 }
1922
Doug Zongker2bec3d42009-12-04 12:52:44 -08001923 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 app.processName, hostingType,
1925 hostingNameStr != null ? hostingNameStr : "");
1926
1927 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001928 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 }
1930
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001931 StringBuilder buf = mStringBuilder;
1932 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933 buf.append("Start proc ");
1934 buf.append(app.processName);
1935 buf.append(" for ");
1936 buf.append(hostingType);
1937 if (hostingNameStr != null) {
1938 buf.append(" ");
1939 buf.append(hostingNameStr);
1940 }
1941 buf.append(": pid=");
1942 buf.append(pid);
1943 buf.append(" uid=");
1944 buf.append(uid);
1945 buf.append(" gids={");
1946 if (gids != null) {
1947 for (int gi=0; gi<gids.length; gi++) {
1948 if (gi != 0) buf.append(", ");
1949 buf.append(gids[gi]);
1950
1951 }
1952 }
1953 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001954 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001955 if (pid == 0 || pid == MY_PID) {
1956 // Processes are being emulated with threads.
1957 app.pid = MY_PID;
1958 app.removed = false;
1959 mStartingProcesses.add(app);
1960 } else if (pid > 0) {
1961 app.pid = pid;
1962 app.removed = false;
1963 synchronized (mPidsSelfLocked) {
1964 this.mPidsSelfLocked.put(pid, app);
1965 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1966 msg.obj = app;
1967 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1968 }
1969 } else {
1970 app.pid = 0;
1971 RuntimeException e = new RuntimeException(
1972 "Failure starting process " + app.processName
1973 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001974 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 }
1976 } catch (RuntimeException e) {
1977 // XXX do better error recovery.
1978 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001979 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 }
1981 }
1982
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001983 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001984 if (resumed) {
1985 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1986 } else {
1987 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1988 }
1989 }
1990
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001991 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001992 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1993 && mTopAction == null) {
1994 // We are running in factory test mode, but unable to find
1995 // the factory test app, so just sit around displaying the
1996 // error message and don't try to start anything.
1997 return false;
1998 }
1999 Intent intent = new Intent(
2000 mTopAction,
2001 mTopData != null ? Uri.parse(mTopData) : null);
2002 intent.setComponent(mTopComponent);
2003 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2004 intent.addCategory(Intent.CATEGORY_HOME);
2005 }
2006 ActivityInfo aInfo =
2007 intent.resolveActivityInfo(mContext.getPackageManager(),
2008 STOCK_PM_FLAGS);
2009 if (aInfo != null) {
2010 intent.setComponent(new ComponentName(
2011 aInfo.applicationInfo.packageName, aInfo.name));
2012 // Don't do this if the home app is currently being
2013 // instrumented.
2014 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2015 aInfo.applicationInfo.uid);
2016 if (app == null || app.instrumentationClass == null) {
2017 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002018 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002019 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002020 }
2021 }
2022
2023
2024 return true;
2025 }
2026
2027 /**
2028 * Starts the "new version setup screen" if appropriate.
2029 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002030 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002031 // Only do this once per boot.
2032 if (mCheckedForSetup) {
2033 return;
2034 }
2035
2036 // We will show this screen if the current one is a different
2037 // version than the last one shown, and we are not running in
2038 // low-level factory test mode.
2039 final ContentResolver resolver = mContext.getContentResolver();
2040 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2041 Settings.Secure.getInt(resolver,
2042 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2043 mCheckedForSetup = true;
2044
2045 // See if we should be showing the platform update setup UI.
2046 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2047 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2048 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2049
2050 // We don't allow third party apps to replace this.
2051 ResolveInfo ri = null;
2052 for (int i=0; ris != null && i<ris.size(); i++) {
2053 if ((ris.get(i).activityInfo.applicationInfo.flags
2054 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2055 ri = ris.get(i);
2056 break;
2057 }
2058 }
2059
2060 if (ri != null) {
2061 String vers = ri.activityInfo.metaData != null
2062 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2063 : null;
2064 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2065 vers = ri.activityInfo.applicationInfo.metaData.getString(
2066 Intent.METADATA_SETUP_VERSION);
2067 }
2068 String lastVers = Settings.Secure.getString(
2069 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2070 if (vers != null && !vers.equals(lastVers)) {
2071 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2072 intent.setComponent(new ComponentName(
2073 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002074 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002075 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002076 }
2077 }
2078 }
2079 }
2080
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002081 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002082 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002083
2084 final int identHash = System.identityHashCode(r);
2085 updateUsageStats(r, true);
2086
2087 int i = mWatchers.beginBroadcast();
2088 while (i > 0) {
2089 i--;
2090 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2091 if (w != null) {
2092 try {
2093 w.activityResuming(identHash);
2094 } catch (RemoteException e) {
2095 }
2096 }
2097 }
2098 mWatchers.finishBroadcast();
2099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002100
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002101 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002102 final int N = mPendingActivityLaunches.size();
2103 if (N <= 0) {
2104 return;
2105 }
2106 for (int i=0; i<N; i++) {
2107 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002108 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002109 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2110 doResume && i == (N-1));
2111 }
2112 mPendingActivityLaunches.clear();
2113 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002114
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002115 public final int startActivity(IApplicationThread caller,
2116 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2117 int grantedMode, IBinder resultTo,
2118 String resultWho, int requestCode, boolean onlyIfNeeded,
2119 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002120 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002121 grantedUriPermissions, grantedMode, resultTo, resultWho,
2122 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002123 }
2124
2125 public final WaitResult startActivityAndWait(IApplicationThread caller,
2126 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2127 int grantedMode, IBinder resultTo,
2128 String resultWho, int requestCode, boolean onlyIfNeeded,
2129 boolean debug) {
2130 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002131 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002132 grantedUriPermissions, grantedMode, resultTo, resultWho,
2133 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002134 return res;
2135 }
2136
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002137 public final int startActivityWithConfig(IApplicationThread caller,
2138 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2139 int grantedMode, IBinder resultTo,
2140 String resultWho, int requestCode, boolean onlyIfNeeded,
2141 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002142 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002143 grantedUriPermissions, grantedMode, resultTo, resultWho,
2144 requestCode, onlyIfNeeded, debug, null, config);
2145 }
2146
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002147 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002148 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002149 IBinder resultTo, String resultWho, int requestCode,
2150 int flagsMask, int flagsValues) {
2151 // Refuse possible leaked file descriptors
2152 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2153 throw new IllegalArgumentException("File descriptors passed in Intent");
2154 }
2155
2156 IIntentSender sender = intent.getTarget();
2157 if (!(sender instanceof PendingIntentRecord)) {
2158 throw new IllegalArgumentException("Bad PendingIntent object");
2159 }
2160
2161 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002162
2163 synchronized (this) {
2164 // If this is coming from the currently resumed activity, it is
2165 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002166 if (mMainStack.mResumedActivity != null
2167 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002168 Binder.getCallingUid()) {
2169 mAppSwitchesAllowedTime = 0;
2170 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002171 }
2172
2173 return pir.sendInner(0, fillInIntent, resolvedType,
2174 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2175 }
2176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 public boolean startNextMatchingActivity(IBinder callingActivity,
2178 Intent intent) {
2179 // Refuse possible leaked file descriptors
2180 if (intent != null && intent.hasFileDescriptors() == true) {
2181 throw new IllegalArgumentException("File descriptors passed in Intent");
2182 }
2183
2184 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002185 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 if (index < 0) {
2187 return false;
2188 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002189 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002190 if (r.app == null || r.app.thread == null) {
2191 // The caller is not running... d'oh!
2192 return false;
2193 }
2194 intent = new Intent(intent);
2195 // The caller is not allowed to change the data.
2196 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2197 // And we are resetting to find the next component...
2198 intent.setComponent(null);
2199
2200 ActivityInfo aInfo = null;
2201 try {
2202 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002203 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002204 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002205 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206
2207 // Look for the original activity in the list...
2208 final int N = resolves != null ? resolves.size() : 0;
2209 for (int i=0; i<N; i++) {
2210 ResolveInfo rInfo = resolves.get(i);
2211 if (rInfo.activityInfo.packageName.equals(r.packageName)
2212 && rInfo.activityInfo.name.equals(r.info.name)) {
2213 // We found the current one... the next matching is
2214 // after it.
2215 i++;
2216 if (i<N) {
2217 aInfo = resolves.get(i).activityInfo;
2218 }
2219 break;
2220 }
2221 }
2222 } catch (RemoteException e) {
2223 }
2224
2225 if (aInfo == null) {
2226 // Nobody who is next!
2227 return false;
2228 }
2229
2230 intent.setComponent(new ComponentName(
2231 aInfo.applicationInfo.packageName, aInfo.name));
2232 intent.setFlags(intent.getFlags()&~(
2233 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2234 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2235 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2236 Intent.FLAG_ACTIVITY_NEW_TASK));
2237
2238 // Okay now we need to start the new activity, replacing the
2239 // currently running activity. This is a little tricky because
2240 // we want to start the new one as if the current one is finished,
2241 // but not finish the current one first so that there is no flicker.
2242 // And thus...
2243 final boolean wasFinishing = r.finishing;
2244 r.finishing = true;
2245
2246 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002247 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002248 final String resultWho = r.resultWho;
2249 final int requestCode = r.requestCode;
2250 r.resultTo = null;
2251 if (resultTo != null) {
2252 resultTo.removeResultsLocked(r, resultWho, requestCode);
2253 }
2254
2255 final long origId = Binder.clearCallingIdentity();
2256 // XXX we are not dealing with propagating grantedUriPermissions...
2257 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002258 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002260 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002261 Binder.restoreCallingIdentity(origId);
2262
2263 r.finishing = wasFinishing;
2264 if (res != START_SUCCESS) {
2265 return false;
2266 }
2267 return true;
2268 }
2269 }
2270
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002271 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 Intent intent, String resolvedType, IBinder resultTo,
2273 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002274
2275 // This is so super not safe, that only the system (or okay root)
2276 // can do it.
2277 final int callingUid = Binder.getCallingUid();
2278 if (callingUid != 0 && callingUid != Process.myUid()) {
2279 throw new SecurityException(
2280 "startActivityInPackage only available to the system");
2281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002283 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2284 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2285 }
2286
2287 public final int startActivities(IApplicationThread caller,
2288 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2289 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2290 }
2291
2292 public final int startActivitiesInPackage(int uid,
2293 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2294
2295 // This is so super not safe, that only the system (or okay root)
2296 // can do it.
2297 final int callingUid = Binder.getCallingUid();
2298 if (callingUid != 0 && callingUid != Process.myUid()) {
2299 throw new SecurityException(
2300 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002301 }
2302
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002303 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002304 }
2305
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002306 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002307 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002308 // Quick case: check if the top-most recent task is the same.
2309 if (N > 0 && mRecentTasks.get(0) == task) {
2310 return;
2311 }
2312 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 for (int i=0; i<N; i++) {
2314 TaskRecord tr = mRecentTasks.get(i);
2315 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2316 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2317 mRecentTasks.remove(i);
2318 i--;
2319 N--;
2320 if (task.intent == null) {
2321 // If the new recent task we are adding is not fully
2322 // specified, then replace it with the existing recent task.
2323 task = tr;
2324 }
2325 }
2326 }
2327 if (N >= MAX_RECENT_TASKS) {
2328 mRecentTasks.remove(N-1);
2329 }
2330 mRecentTasks.add(0, task);
2331 }
2332
2333 public void setRequestedOrientation(IBinder token,
2334 int requestedOrientation) {
2335 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002336 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002337 if (index < 0) {
2338 return;
2339 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002340 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002341 final long origId = Binder.clearCallingIdentity();
2342 mWindowManager.setAppOrientation(r, requestedOrientation);
2343 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002344 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002345 r.mayFreezeScreenLocked(r.app) ? r : null);
2346 if (config != null) {
2347 r.frozenBeforeDestroy = true;
2348 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002349 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350 }
2351 }
2352 Binder.restoreCallingIdentity(origId);
2353 }
2354 }
2355
2356 public int getRequestedOrientation(IBinder token) {
2357 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002358 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002359 if (index < 0) {
2360 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2361 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002362 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 return mWindowManager.getAppOrientation(r);
2364 }
2365 }
2366
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 /**
2368 * This is the internal entry point for handling Activity.finish().
2369 *
2370 * @param token The Binder token referencing the Activity we want to finish.
2371 * @param resultCode Result code, if any, from this Activity.
2372 * @param resultData Result data (Intent), if any, from this Activity.
2373 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002374 * @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 -08002375 */
2376 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2377 // Refuse possible leaked file descriptors
2378 if (resultData != null && resultData.hasFileDescriptors() == true) {
2379 throw new IllegalArgumentException("File descriptors passed in Intent");
2380 }
2381
2382 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002383 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002384 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002385 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002386 if (next != null) {
2387 // ask watcher if this is allowed
2388 boolean resumeOK = true;
2389 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002390 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002391 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002392 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393 }
2394
2395 if (!resumeOK) {
2396 return false;
2397 }
2398 }
2399 }
2400 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002401 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 resultData, "app-request");
2403 Binder.restoreCallingIdentity(origId);
2404 return res;
2405 }
2406 }
2407
Dianne Hackborn860755f2010-06-03 18:47:52 -07002408 public final void finishHeavyWeightApp() {
2409 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2410 != PackageManager.PERMISSION_GRANTED) {
2411 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2412 + Binder.getCallingPid()
2413 + ", uid=" + Binder.getCallingUid()
2414 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2415 Slog.w(TAG, msg);
2416 throw new SecurityException(msg);
2417 }
2418
2419 synchronized(this) {
2420 if (mHeavyWeightProcess == null) {
2421 return;
2422 }
2423
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002424 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002425 mHeavyWeightProcess.activities);
2426 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002427 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002428 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002429 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002430 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002431 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002432 null, "finish-heavy");
2433 }
2434 }
2435 }
2436
2437 mHeavyWeightProcess = null;
2438 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2439 }
2440 }
2441
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002442 public void crashApplication(int uid, int initialPid, String packageName,
2443 String message) {
2444 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2445 != PackageManager.PERMISSION_GRANTED) {
2446 String msg = "Permission Denial: crashApplication() from pid="
2447 + Binder.getCallingPid()
2448 + ", uid=" + Binder.getCallingUid()
2449 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2450 Slog.w(TAG, msg);
2451 throw new SecurityException(msg);
2452 }
2453
2454 synchronized(this) {
2455 ProcessRecord proc = null;
2456
2457 // Figure out which process to kill. We don't trust that initialPid
2458 // still has any relation to current pids, so must scan through the
2459 // list.
2460 synchronized (mPidsSelfLocked) {
2461 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2462 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2463 if (p.info.uid != uid) {
2464 continue;
2465 }
2466 if (p.pid == initialPid) {
2467 proc = p;
2468 break;
2469 }
2470 for (String str : p.pkgList) {
2471 if (str.equals(packageName)) {
2472 proc = p;
2473 }
2474 }
2475 }
2476 }
2477
2478 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002479 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002480 + " initialPid=" + initialPid
2481 + " packageName=" + packageName);
2482 return;
2483 }
2484
2485 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002486 if (proc.pid == Process.myPid()) {
2487 Log.w(TAG, "crashApplication: trying to crash self!");
2488 return;
2489 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002490 long ident = Binder.clearCallingIdentity();
2491 try {
2492 proc.thread.scheduleCrash(message);
2493 } catch (RemoteException e) {
2494 }
2495 Binder.restoreCallingIdentity(ident);
2496 }
2497 }
2498 }
2499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 public final void finishSubActivity(IBinder token, String resultWho,
2501 int requestCode) {
2502 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002503 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002504 if (index < 0) {
2505 return;
2506 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002507 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002508
2509 final long origId = Binder.clearCallingIdentity();
2510
2511 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002512 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2513 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002514 if (r.resultTo == self && r.requestCode == requestCode) {
2515 if ((r.resultWho == null && resultWho == null) ||
2516 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002517 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 Activity.RESULT_CANCELED, null, "request-sub");
2519 }
2520 }
2521 }
2522
2523 Binder.restoreCallingIdentity(origId);
2524 }
2525 }
2526
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002527 public boolean willActivityBeVisible(IBinder token) {
2528 synchronized(this) {
2529 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002530 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2531 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002532 if (r == token) {
2533 return true;
2534 }
2535 if (r.fullscreen && !r.finishing) {
2536 return false;
2537 }
2538 }
2539 return true;
2540 }
2541 }
2542
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002543 public void overridePendingTransition(IBinder token, String packageName,
2544 int enterAnim, int exitAnim) {
2545 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002546 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002547 if (index < 0) {
2548 return;
2549 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002550 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002551
2552 final long origId = Binder.clearCallingIdentity();
2553
2554 if (self.state == ActivityState.RESUMED
2555 || self.state == ActivityState.PAUSING) {
2556 mWindowManager.overridePendingAppTransition(packageName,
2557 enterAnim, exitAnim);
2558 }
2559
2560 Binder.restoreCallingIdentity(origId);
2561 }
2562 }
2563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002564 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002565 * Main function for removing an existing process from the activity manager
2566 * as a result of that process going away. Clears out all connections
2567 * to the process.
2568 */
2569 private final void handleAppDiedLocked(ProcessRecord app,
2570 boolean restarting) {
2571 cleanUpApplicationRecordLocked(app, restarting, -1);
2572 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002573 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574 }
2575
2576 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002577 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2578 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2579 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002581 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2582 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583 }
2584
2585 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002586 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587
2588 boolean atTop = true;
2589 boolean hasVisibleActivities = false;
2590
2591 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002592 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002593 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 TAG, "Removing app " + app + " from history with " + i + " entries");
2595 while (i > 0) {
2596 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002597 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002598 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2600 if (r.app == app) {
2601 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002602 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002603 TAG, "Removing this entry! frozen=" + r.haveState
2604 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002605 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002606 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002607 r.takeFromHistory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608 mWindowManager.removeAppToken(r);
2609 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002610 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002611 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002612 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613
2614 } else {
2615 // We have the current state for this activity, so
2616 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002617 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618 TAG, "Keeping entry, setting app to null");
2619 if (r.visible) {
2620 hasVisibleActivities = true;
2621 }
2622 r.app = null;
2623 r.nowVisible = false;
2624 if (!r.haveState) {
2625 r.icicle = null;
2626 }
2627 }
2628
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002629 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002630 r.state = ActivityState.STOPPED;
2631 }
2632 atTop = false;
2633 }
2634
2635 app.activities.clear();
2636
2637 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002638 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002639 + " running instrumentation " + app.instrumentationClass);
2640 Bundle info = new Bundle();
2641 info.putString("shortMsg", "Process crashed.");
2642 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2643 }
2644
2645 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002646 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002647 // If there was nothing to resume, and we are not already
2648 // restarting this process, but there is a visible activity that
2649 // is hosted by the process... then make sure all visible
2650 // activities are running, taking care of restarting this
2651 // process.
2652 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002653 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 }
2655 }
2656 }
2657 }
2658
2659 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2660 IBinder threadBinder = thread.asBinder();
2661
2662 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002663 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2664 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2666 return i;
2667 }
2668 }
2669 return -1;
2670 }
2671
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002672 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002673 IApplicationThread thread) {
2674 if (thread == null) {
2675 return null;
2676 }
2677
2678 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002679 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680 }
2681
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002682 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 IApplicationThread thread) {
2684
2685 mProcDeaths[0]++;
2686
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002687 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2688 synchronized (stats) {
2689 stats.noteProcessDiedLocked(app.info.uid, pid);
2690 }
2691
Magnus Edlund7bb25812010-02-24 15:45:06 +01002692 // Clean up already done if the process has been re-started.
2693 if (app.pid == pid && app.thread != null &&
2694 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002695 if (!app.killedBackground) {
2696 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2697 + ") has died.");
2698 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002699 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002700 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 TAG, "Dying app: " + app + ", pid: " + pid
2702 + ", thread: " + thread.asBinder());
2703 boolean doLowMem = app.instrumentationClass == null;
2704 handleAppDiedLocked(app, false);
2705
2706 if (doLowMem) {
2707 // If there are no longer any background processes running,
2708 // and the app that died was not running instrumentation,
2709 // then tell everyone we are now low on memory.
2710 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002711 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2712 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2714 haveBg = true;
2715 break;
2716 }
2717 }
2718
2719 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002720 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002721 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002722 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002723 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2724 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002725 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002726 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2727 // The low memory report is overriding any current
2728 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002729 // heavy/important/visible/foreground processes first.
2730 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002731 rec.lastRequestedGc = 0;
2732 } else {
2733 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002735 rec.reportLowMemory = true;
2736 rec.lastLowMemory = now;
2737 mProcessesToGc.remove(rec);
2738 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002739 }
2740 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002741 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 }
2743 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002744 } else if (app.pid != pid) {
2745 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002746 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002747 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002748 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002749 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002750 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002751 + thread.asBinder());
2752 }
2753 }
2754
Dan Egnor42471dd2010-01-07 17:25:22 -08002755 /**
2756 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002757 * @param clearTraces causes the dump file to be erased prior to the new
2758 * traces being written, if true; when false, the new traces will be
2759 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002760 * @param firstPids of dalvik VM processes to dump stack traces for first
2761 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002762 * @return file containing stack traces, or null if no dump file is configured
2763 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002764 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2765 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002766 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2767 if (tracesPath == null || tracesPath.length() == 0) {
2768 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002769 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002770
2771 File tracesFile = new File(tracesPath);
2772 try {
2773 File tracesDir = tracesFile.getParentFile();
2774 if (!tracesDir.exists()) tracesFile.mkdirs();
2775 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2776
Christopher Tate6ee412d2010-05-28 12:01:56 -07002777 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002778 tracesFile.createNewFile();
2779 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2780 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002781 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002782 return null;
2783 }
2784
2785 // Use a FileObserver to detect when traces finish writing.
2786 // The order of traces is considered important to maintain for legibility.
2787 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2788 public synchronized void onEvent(int event, String path) { notify(); }
2789 };
2790
2791 try {
2792 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002793
2794 // First collect all of the stacks of the most important pids.
2795 try {
2796 int num = firstPids.size();
2797 for (int i = 0; i < num; i++) {
2798 synchronized (observer) {
2799 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2800 observer.wait(200); // Wait for write-close, give up after 200msec
2801 }
2802 }
2803 } catch (InterruptedException e) {
2804 Log.wtf(TAG, e);
2805 }
2806
2807 // Next measure CPU usage.
2808 if (processStats != null) {
2809 processStats.init();
2810 System.gc();
2811 processStats.update();
2812 try {
2813 synchronized (processStats) {
2814 processStats.wait(500); // measure over 1/2 second.
2815 }
2816 } catch (InterruptedException e) {
2817 }
2818 processStats.update();
2819
2820 // We'll take the stack crawls of just the top apps using CPU.
2821 final int N = processStats.countWorkingStats();
2822 int numProcs = 0;
2823 for (int i=0; i<N && numProcs<5; i++) {
2824 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2825 if (lastPids.indexOfKey(stats.pid) >= 0) {
2826 numProcs++;
2827 try {
2828 synchronized (observer) {
2829 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2830 observer.wait(200); // Wait for write-close, give up after 200msec
2831 }
2832 } catch (InterruptedException e) {
2833 Log.wtf(TAG, e);
2834 }
2835
2836 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002837 }
2838 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002839
2840 return tracesFile;
2841
Dan Egnor42471dd2010-01-07 17:25:22 -08002842 } finally {
2843 observer.stopWatching();
2844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002845 }
2846
Jeff Brown4d94a762010-09-23 11:33:28 -07002847 private final class AppNotResponding implements Runnable {
2848 private final ProcessRecord mApp;
2849 private final String mAnnotation;
2850
2851 public AppNotResponding(ProcessRecord app, String annotation) {
2852 mApp = app;
2853 mAnnotation = annotation;
2854 }
2855
2856 @Override
2857 public void run() {
2858 appNotResponding(mApp, null, null, mAnnotation);
2859 }
2860 }
2861
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002862 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2863 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002864 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2865 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2866
Dianne Hackborn287952c2010-09-22 22:34:31 -07002867 if (mController != null) {
2868 try {
2869 // 0 == continue, -1 = kill process immediately
2870 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2871 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2872 } catch (RemoteException e) {
2873 mController = null;
2874 }
2875 }
2876
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002877 long anrTime = SystemClock.uptimeMillis();
2878 if (MONITOR_CPU_USAGE) {
2879 updateCpuStatsNow();
2880 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002881
2882 synchronized (this) {
2883 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2884 if (mShuttingDown) {
2885 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2886 return;
2887 } else if (app.notResponding) {
2888 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2889 return;
2890 } else if (app.crashing) {
2891 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2892 return;
2893 }
2894
2895 // In case we come through here for the same app before completing
2896 // this one, mark as anring now so we will bail out.
2897 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002898
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002899 // Log the ANR to the event log.
2900 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2901 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002902
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002903 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002904 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002905
2906 int parentPid = app.pid;
2907 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002908 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002909
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002910 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002911
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002912 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2913 ProcessRecord r = mLruProcesses.get(i);
2914 if (r != null && r.thread != null) {
2915 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002916 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2917 if (r.persistent) {
2918 firstPids.add(pid);
2919 } else {
2920 lastPids.put(pid, Boolean.TRUE);
2921 }
2922 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002923 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002924 }
2925 }
2926
Dan Egnor42471dd2010-01-07 17:25:22 -08002927 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002928 StringBuilder info = mStringBuilder;
2929 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002930 info.append("ANR in ").append(app.processName);
2931 if (activity != null && activity.shortComponentName != null) {
2932 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002933 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002934 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002936 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002937 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002938 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002939 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941
Dianne Hackborn287952c2010-09-22 22:34:31 -07002942 final ProcessStats processStats = new ProcessStats(true);
2943
2944 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2945
Dan Egnor42471dd2010-01-07 17:25:22 -08002946 String cpuInfo = null;
2947 if (MONITOR_CPU_USAGE) {
2948 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002949 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002950 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002951 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002952 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002953 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 }
2955
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002956 info.append(processStats.printCurrentState(anrTime));
2957
Joe Onorato8a9b2202010-02-26 18:56:32 -08002958 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002959 if (tracesFile == null) {
2960 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2961 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2962 }
2963
2964 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2965
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002966 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002967 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002968 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2969 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002971 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2972 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002973 }
2974 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002975 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002976 }
2977 }
2978
Dan Egnor42471dd2010-01-07 17:25:22 -08002979 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2980 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2981 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002982
2983 synchronized (this) {
2984 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2985 Process.killProcess(app.pid);
2986 return;
2987 }
2988
2989 // Set the app's notResponding state, and look up the errorReportReceiver
2990 makeAppNotRespondingLocked(app,
2991 activity != null ? activity.shortComponentName : null,
2992 annotation != null ? "ANR " + annotation : "ANR",
2993 info.toString());
2994
2995 // Bring up the infamous App Not Responding dialog
2996 Message msg = Message.obtain();
2997 HashMap map = new HashMap();
2998 msg.what = SHOW_NOT_RESPONDING_MSG;
2999 msg.obj = map;
3000 map.put("app", app);
3001 if (activity != null) {
3002 map.put("activity", activity);
3003 }
3004
3005 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003007 }
3008
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003009 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3010 if (!mLaunchWarningShown) {
3011 mLaunchWarningShown = true;
3012 mHandler.post(new Runnable() {
3013 @Override
3014 public void run() {
3015 synchronized (ActivityManagerService.this) {
3016 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3017 d.show();
3018 mHandler.postDelayed(new Runnable() {
3019 @Override
3020 public void run() {
3021 synchronized (ActivityManagerService.this) {
3022 d.dismiss();
3023 mLaunchWarningShown = false;
3024 }
3025 }
3026 }, 4000);
3027 }
3028 }
3029 });
3030 }
3031 }
3032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 public boolean clearApplicationUserData(final String packageName,
3034 final IPackageDataObserver observer) {
3035 int uid = Binder.getCallingUid();
3036 int pid = Binder.getCallingPid();
3037 long callingId = Binder.clearCallingIdentity();
3038 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003039 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003040 int pkgUid = -1;
3041 synchronized(this) {
3042 try {
3043 pkgUid = pm.getPackageUid(packageName);
3044 } catch (RemoteException e) {
3045 }
3046 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003047 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 return false;
3049 }
3050 if (uid == pkgUid || checkComponentPermission(
3051 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003052 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003054 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 } else {
3056 throw new SecurityException(pid+" does not have permission:"+
3057 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3058 "for process:"+packageName);
3059 }
3060 }
3061
3062 try {
3063 //clear application user data
3064 pm.clearApplicationUserData(packageName, observer);
3065 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3066 Uri.fromParts("package", packageName, null));
3067 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003068 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3069 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003070 } catch (RemoteException e) {
3071 }
3072 } finally {
3073 Binder.restoreCallingIdentity(callingId);
3074 }
3075 return true;
3076 }
3077
Dianne Hackborn03abb812010-01-04 18:43:19 -08003078 public void killBackgroundProcesses(final String packageName) {
3079 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3080 != PackageManager.PERMISSION_GRANTED &&
3081 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3082 != PackageManager.PERMISSION_GRANTED) {
3083 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003084 + Binder.getCallingPid()
3085 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003086 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003087 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003088 throw new SecurityException(msg);
3089 }
3090
3091 long callingId = Binder.clearCallingIdentity();
3092 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003093 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094 int pkgUid = -1;
3095 synchronized(this) {
3096 try {
3097 pkgUid = pm.getPackageUid(packageName);
3098 } catch (RemoteException e) {
3099 }
3100 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003101 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 return;
3103 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003104 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003105 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003106 }
3107 } finally {
3108 Binder.restoreCallingIdentity(callingId);
3109 }
3110 }
3111
3112 public void forceStopPackage(final String packageName) {
3113 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3114 != PackageManager.PERMISSION_GRANTED) {
3115 String msg = "Permission Denial: forceStopPackage() from pid="
3116 + Binder.getCallingPid()
3117 + ", uid=" + Binder.getCallingUid()
3118 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003119 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003120 throw new SecurityException(msg);
3121 }
3122
3123 long callingId = Binder.clearCallingIdentity();
3124 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003125 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003126 int pkgUid = -1;
3127 synchronized(this) {
3128 try {
3129 pkgUid = pm.getPackageUid(packageName);
3130 } catch (RemoteException e) {
3131 }
3132 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003133 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003134 return;
3135 }
3136 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003137 try {
3138 pm.setPackageStoppedState(packageName, true);
3139 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003140 } catch (IllegalArgumentException e) {
3141 Slog.w(TAG, "Failed trying to unstop package "
3142 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144 }
3145 } finally {
3146 Binder.restoreCallingIdentity(callingId);
3147 }
3148 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003149
3150 /*
3151 * The pkg name and uid have to be specified.
3152 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3153 */
3154 public void killApplicationWithUid(String pkg, int uid) {
3155 if (pkg == null) {
3156 return;
3157 }
3158 // Make sure the uid is valid.
3159 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003160 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003161 return;
3162 }
3163 int callerUid = Binder.getCallingUid();
3164 // Only the system server can kill an application
3165 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003166 // Post an aysnc message to kill the application
3167 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3168 msg.arg1 = uid;
3169 msg.arg2 = 0;
3170 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003171 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003172 } else {
3173 throw new SecurityException(callerUid + " cannot kill pkg: " +
3174 pkg);
3175 }
3176 }
3177
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003178 public void closeSystemDialogs(String reason) {
3179 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003180 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003181 if (reason != null) {
3182 intent.putExtra("reason", reason);
3183 }
3184
3185 final int uid = Binder.getCallingUid();
3186 final long origId = Binder.clearCallingIdentity();
3187 synchronized (this) {
3188 int i = mWatchers.beginBroadcast();
3189 while (i > 0) {
3190 i--;
3191 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3192 if (w != null) {
3193 try {
3194 w.closingSystemDialogs(reason);
3195 } catch (RemoteException e) {
3196 }
3197 }
3198 }
3199 mWatchers.finishBroadcast();
3200
Dianne Hackbornffa42482009-09-23 22:20:11 -07003201 mWindowManager.closeSystemDialogs(reason);
3202
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003203 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3204 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003205 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003206 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003207 Activity.RESULT_CANCELED, null, "close-sys");
3208 }
3209 }
3210
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003211 broadcastIntentLocked(null, null, intent, null,
3212 null, 0, null, null, null, false, false, -1, uid);
3213 }
3214 Binder.restoreCallingIdentity(origId);
3215 }
3216
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003217 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003218 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003219 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3220 for (int i=pids.length-1; i>=0; i--) {
3221 infos[i] = new Debug.MemoryInfo();
3222 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003223 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003224 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003225 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003226
3227 public void killApplicationProcess(String processName, int uid) {
3228 if (processName == null) {
3229 return;
3230 }
3231
3232 int callerUid = Binder.getCallingUid();
3233 // Only the system server can kill an application
3234 if (callerUid == Process.SYSTEM_UID) {
3235 synchronized (this) {
3236 ProcessRecord app = getProcessRecordLocked(processName, uid);
3237 if (app != null) {
3238 try {
3239 app.thread.scheduleSuicide();
3240 } catch (RemoteException e) {
3241 // If the other end already died, then our work here is done.
3242 }
3243 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003244 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003245 + processName + " / " + uid);
3246 }
3247 }
3248 } else {
3249 throw new SecurityException(callerUid + " cannot kill app process: " +
3250 processName);
3251 }
3252 }
3253
Dianne Hackborn03abb812010-01-04 18:43:19 -08003254 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003255 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3257 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003258 if (!mProcessesReady) {
3259 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003261 intent.putExtra(Intent.EXTRA_UID, uid);
3262 broadcastIntentLocked(null, null, intent,
3263 null, null, 0, null, null, null,
3264 false, false, MY_PID, Process.SYSTEM_UID);
3265 }
3266
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003267 private final boolean killPackageProcessesLocked(String packageName, int uid,
3268 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003269 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270
Dianne Hackborn03abb812010-01-04 18:43:19 -08003271 // Remove all processes this package may have touched: all with the
3272 // same UID (except for the system or root user), and all whose name
3273 // matches the package name.
3274 final String procNamePrefix = packageName + ":";
3275 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3276 final int NA = apps.size();
3277 for (int ia=0; ia<NA; ia++) {
3278 ProcessRecord app = apps.valueAt(ia);
3279 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003280 if (doit) {
3281 procs.add(app);
3282 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003283 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3284 || app.processName.equals(packageName)
3285 || app.processName.startsWith(procNamePrefix)) {
3286 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003287 if (!doit) {
3288 return true;
3289 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003290 app.removed = true;
3291 procs.add(app);
3292 }
3293 }
3294 }
3295 }
3296
3297 int N = procs.size();
3298 for (int i=0; i<N; i++) {
3299 removeProcessLocked(procs.get(i), callerWillRestart);
3300 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003301 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003302 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003303
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003304 private final boolean forceStopPackageLocked(String name, int uid,
3305 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003306 int i, N;
3307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 if (uid < 0) {
3309 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003310 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 } catch (RemoteException e) {
3312 }
3313 }
3314
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003315 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003316 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003317
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003318 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3319 while (badApps.hasNext()) {
3320 SparseArray<Long> ba = badApps.next();
3321 if (ba.get(uid) != null) {
3322 badApps.remove();
3323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 }
3325 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003326
3327 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3328 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003330 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3331 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003333 if (!doit) {
3334 return true;
3335 }
3336 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003337 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003338 if (r.app != null) {
3339 r.app.removed = true;
3340 }
3341 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003342 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343 }
3344 }
3345
3346 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3347 for (ServiceRecord service : mServices.values()) {
3348 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003349 if (!doit) {
3350 return true;
3351 }
3352 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003353 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003354 if (service.app != null) {
3355 service.app.removed = true;
3356 }
3357 service.app = null;
3358 services.add(service);
3359 }
3360 }
3361
3362 N = services.size();
3363 for (i=0; i<N; i++) {
3364 bringDownServiceLocked(services.get(i), true);
3365 }
3366
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003367 if (doit) {
3368 if (purgeCache) {
3369 AttributeCache ac = AttributeCache.instance();
3370 if (ac != null) {
3371 ac.removePackage(name);
3372 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003373 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003374 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003375 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003376
3377 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003378 }
3379
3380 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3381 final String name = app.processName;
3382 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003383 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003384 TAG, "Force removing process " + app + " (" + name
3385 + "/" + uid + ")");
3386
3387 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003388 if (mHeavyWeightProcess == app) {
3389 mHeavyWeightProcess = null;
3390 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 boolean needRestart = false;
3393 if (app.pid > 0 && app.pid != MY_PID) {
3394 int pid = app.pid;
3395 synchronized (mPidsSelfLocked) {
3396 mPidsSelfLocked.remove(pid);
3397 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3398 }
3399 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003400 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 Process.killProcess(pid);
3402
3403 if (app.persistent) {
3404 if (!callerWillRestart) {
3405 addAppLocked(app.info);
3406 } else {
3407 needRestart = true;
3408 }
3409 }
3410 } else {
3411 mRemovedProcesses.add(app);
3412 }
3413
3414 return needRestart;
3415 }
3416
3417 private final void processStartTimedOutLocked(ProcessRecord app) {
3418 final int pid = app.pid;
3419 boolean gone = false;
3420 synchronized (mPidsSelfLocked) {
3421 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3422 if (knownApp != null && knownApp.thread == null) {
3423 mPidsSelfLocked.remove(pid);
3424 gone = true;
3425 }
3426 }
3427
3428 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003429 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003430 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003431 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003433 if (mHeavyWeightProcess == app) {
3434 mHeavyWeightProcess = null;
3435 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3436 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003437 // Take care of any launching providers waiting for this process.
3438 checkAppInLaunchingProvidersLocked(app, true);
3439 // Take care of any services that are waiting for the process.
3440 for (int i=0; i<mPendingServices.size(); i++) {
3441 ServiceRecord sr = mPendingServices.get(i);
3442 if (app.info.uid == sr.appInfo.uid
3443 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003444 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003445 mPendingServices.remove(i);
3446 i--;
3447 bringDownServiceLocked(sr, true);
3448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003450 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003451 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003452 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003453 try {
3454 IBackupManager bm = IBackupManager.Stub.asInterface(
3455 ServiceManager.getService(Context.BACKUP_SERVICE));
3456 bm.agentDisconnected(app.info.packageName);
3457 } catch (RemoteException e) {
3458 // Can't happen; the backup manager is local
3459 }
3460 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003461 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003462 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003463 mPendingBroadcast.state = BroadcastRecord.IDLE;
3464 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003465 mPendingBroadcast = null;
3466 scheduleBroadcastsLocked();
3467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003469 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 }
3471 }
3472
3473 private final boolean attachApplicationLocked(IApplicationThread thread,
3474 int pid) {
3475
3476 // Find the application record that is being attached... either via
3477 // the pid if we are running in multiple processes, or just pull the
3478 // next app record if we are emulating process with anonymous threads.
3479 ProcessRecord app;
3480 if (pid != MY_PID && pid >= 0) {
3481 synchronized (mPidsSelfLocked) {
3482 app = mPidsSelfLocked.get(pid);
3483 }
3484 } else if (mStartingProcesses.size() > 0) {
3485 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003486 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003487 } else {
3488 app = null;
3489 }
3490
3491 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003492 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003493 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003494 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 if (pid > 0 && pid != MY_PID) {
3496 Process.killProcess(pid);
3497 } else {
3498 try {
3499 thread.scheduleExit();
3500 } catch (Exception e) {
3501 // Ignore exceptions.
3502 }
3503 }
3504 return false;
3505 }
3506
3507 // If this application record is still attached to a previous
3508 // process, clean it up now.
3509 if (app.thread != null) {
3510 handleAppDiedLocked(app, true);
3511 }
3512
3513 // Tell the process all about itself.
3514
Joe Onorato8a9b2202010-02-26 18:56:32 -08003515 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003516 TAG, "Binding process pid " + pid + " to record " + app);
3517
3518 String processName = app.processName;
3519 try {
3520 thread.asBinder().linkToDeath(new AppDeathRecipient(
3521 app, pid, thread), 0);
3522 } catch (RemoteException e) {
3523 app.resetPackageList();
3524 startProcessLocked(app, "link fail", processName);
3525 return false;
3526 }
3527
Doug Zongker2bec3d42009-12-04 12:52:44 -08003528 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529
3530 app.thread = thread;
3531 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003532 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3533 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003534 app.forcingToForeground = null;
3535 app.foregroundServices = false;
3536 app.debugging = false;
3537
3538 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3539
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003540 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003541 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003543 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003544 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003545 }
3546
Joe Onorato8a9b2202010-02-26 18:56:32 -08003547 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548 TAG, "New app record " + app
3549 + " thread=" + thread.asBinder() + " pid=" + pid);
3550 try {
3551 int testMode = IApplicationThread.DEBUG_OFF;
3552 if (mDebugApp != null && mDebugApp.equals(processName)) {
3553 testMode = mWaitForDebugger
3554 ? IApplicationThread.DEBUG_WAIT
3555 : IApplicationThread.DEBUG_ON;
3556 app.debugging = true;
3557 if (mDebugTransient) {
3558 mDebugApp = mOrigDebugApp;
3559 mWaitForDebugger = mOrigWaitForDebugger;
3560 }
3561 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003562
Christopher Tate181fafa2009-05-14 11:12:14 -07003563 // If the app is being launched for restore or full backup, set it up specially
3564 boolean isRestrictedBackupMode = false;
3565 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3566 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3567 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3568 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003569
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003570 ensurePackageDexOpt(app.instrumentationInfo != null
3571 ? app.instrumentationInfo.packageName
3572 : app.info.packageName);
3573 if (app.instrumentationClass != null) {
3574 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003575 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003576 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003577 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003578 thread.bindApplication(processName, app.instrumentationInfo != null
3579 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 app.instrumentationClass, app.instrumentationProfileFile,
3581 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003582 isRestrictedBackupMode || !normalMode,
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003583 mConfiguration, getCommonServicesLocked(),
3584 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003585 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003586 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003587 } catch (Exception e) {
3588 // todo: Yikes! What should we do? For now we will try to
3589 // start another process, but that could easily get us in
3590 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003591 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003592
3593 app.resetPackageList();
3594 startProcessLocked(app, "bind fail", processName);
3595 return false;
3596 }
3597
3598 // Remove this record from the list of starting applications.
3599 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003600 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3601 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003602 mProcessesOnHold.remove(app);
3603
3604 boolean badApp = false;
3605 boolean didSomething = false;
3606
3607 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003608 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003609 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3611 && processName.equals(hr.processName)) {
3612 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003613 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 didSomething = true;
3615 }
3616 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003617 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 + hr.intent.getComponent().flattenToShortString(), e);
3619 badApp = true;
3620 }
3621 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003622 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003623 }
3624 }
3625
3626 // Find any services that should be running in this process...
3627 if (!badApp && mPendingServices.size() > 0) {
3628 ServiceRecord sr = null;
3629 try {
3630 for (int i=0; i<mPendingServices.size(); i++) {
3631 sr = mPendingServices.get(i);
3632 if (app.info.uid != sr.appInfo.uid
3633 || !processName.equals(sr.processName)) {
3634 continue;
3635 }
3636
3637 mPendingServices.remove(i);
3638 i--;
3639 realStartServiceLocked(sr, app);
3640 didSomething = true;
3641 }
3642 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003643 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644 + sr.shortName, e);
3645 badApp = true;
3646 }
3647 }
3648
3649 // Check if the next broadcast receiver is in this process...
3650 BroadcastRecord br = mPendingBroadcast;
3651 if (!badApp && br != null && br.curApp == app) {
3652 try {
3653 mPendingBroadcast = null;
3654 processCurBroadcastLocked(br, app);
3655 didSomething = true;
3656 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003657 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003658 + br.curComponent.flattenToShortString(), e);
3659 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003660 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3662 br.resultExtras, br.resultAbort, true);
3663 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003664 // We need to reset the state if we fails to start the receiver.
3665 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003666 }
3667 }
3668
Christopher Tate181fafa2009-05-14 11:12:14 -07003669 // Check whether the next backup agent is in this process...
3670 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003671 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003672 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003673 try {
3674 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3675 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003676 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003677 e.printStackTrace();
3678 }
3679 }
3680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003681 if (badApp) {
3682 // todo: Also need to kill application to deal with all
3683 // kinds of exceptions.
3684 handleAppDiedLocked(app, false);
3685 return false;
3686 }
3687
3688 if (!didSomething) {
3689 updateOomAdjLocked();
3690 }
3691
3692 return true;
3693 }
3694
3695 public final void attachApplication(IApplicationThread thread) {
3696 synchronized (this) {
3697 int callingPid = Binder.getCallingPid();
3698 final long origId = Binder.clearCallingIdentity();
3699 attachApplicationLocked(thread, callingPid);
3700 Binder.restoreCallingIdentity(origId);
3701 }
3702 }
3703
Dianne Hackborne88846e2009-09-30 21:34:25 -07003704 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003705 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003706 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003707 Binder.restoreCallingIdentity(origId);
3708 }
3709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003711 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003712 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713 mWindowManager.enableScreenAfterBoot();
3714 }
3715
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003716 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003717 IntentFilter pkgFilter = new IntentFilter();
3718 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3719 pkgFilter.addDataScheme("package");
3720 mContext.registerReceiver(new BroadcastReceiver() {
3721 @Override
3722 public void onReceive(Context context, Intent intent) {
3723 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3724 if (pkgs != null) {
3725 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003726 synchronized (ActivityManagerService.this) {
3727 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3728 setResultCode(Activity.RESULT_OK);
3729 return;
3730 }
3731 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003732 }
3733 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003734 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003735 }, pkgFilter);
3736
3737 synchronized (this) {
3738 // Ensure that any processes we had put on hold are now started
3739 // up.
3740 final int NP = mProcessesOnHold.size();
3741 if (NP > 0) {
3742 ArrayList<ProcessRecord> procs =
3743 new ArrayList<ProcessRecord>(mProcessesOnHold);
3744 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003745 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3746 + procs.get(ip));
3747 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003748 }
3749 }
3750
3751 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003752 // Start looking for apps that are abusing wake locks.
3753 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003754 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003755 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003756 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003757 broadcastIntentLocked(null, null,
3758 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3759 null, null, 0, null, null,
3760 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3761 false, false, MY_PID, Process.SYSTEM_UID);
3762 }
3763 }
3764 }
3765
3766 final void ensureBootCompleted() {
3767 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003768 boolean enableScreen;
3769 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003770 booting = mBooting;
3771 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003772 enableScreen = !mBooted;
3773 mBooted = true;
3774 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003775
3776 if (booting) {
3777 finishBooting();
3778 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003779
3780 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003781 enableScreenAfterBoot();
3782 }
3783 }
3784
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003785 public final void activityPaused(IBinder token) {
3786 final long origId = Binder.clearCallingIdentity();
3787 mMainStack.activityPaused(token, false);
3788 Binder.restoreCallingIdentity(origId);
3789 }
3790
3791 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3792 CharSequence description) {
3793 if (localLOGV) Slog.v(
3794 TAG, "Activity stopped: token=" + token);
3795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003796 // Refuse possible leaked file descriptors
3797 if (icicle != null && icicle.hasFileDescriptors()) {
3798 throw new IllegalArgumentException("File descriptors passed in Bundle");
3799 }
3800
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003801 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003802
3803 final long origId = Binder.clearCallingIdentity();
3804
3805 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003806 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003808 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003809 r.icicle = icicle;
3810 r.haveState = true;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003811 r.updateThumbnail(thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003812 r.stopped = true;
3813 r.state = ActivityState.STOPPED;
3814 if (!r.finishing) {
3815 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003816 r.stack.destroyActivityLocked(r, true);
3817 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003818 }
3819 }
3820 }
3821 }
3822
3823 if (r != null) {
3824 sendPendingThumbnail(r, null, null, null, false);
3825 }
3826
3827 trimApplications();
3828
3829 Binder.restoreCallingIdentity(origId);
3830 }
3831
3832 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003833 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003834 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 }
3836
3837 public String getCallingPackage(IBinder token) {
3838 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003839 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003840 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003841 }
3842 }
3843
3844 public ComponentName getCallingActivity(IBinder token) {
3845 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003846 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003847 return r != null ? r.intent.getComponent() : null;
3848 }
3849 }
3850
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003851 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003852 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003853 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003854 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003855 if (r != null) {
3856 return r.resultTo;
3857 }
3858 }
3859 return null;
3860 }
3861
3862 public ComponentName getActivityClassForToken(IBinder token) {
3863 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003864 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003866 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003867 return r.intent.getComponent();
3868 }
3869 return null;
3870 }
3871 }
3872
3873 public String getPackageForToken(IBinder token) {
3874 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003875 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003876 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003877 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003878 return r.packageName;
3879 }
3880 return null;
3881 }
3882 }
3883
3884 public IIntentSender getIntentSender(int type,
3885 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003886 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003887 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003888 if (intents != null) {
3889 if (intents.length < 1) {
3890 throw new IllegalArgumentException("Intents array length must be >= 1");
3891 }
3892 for (int i=0; i<intents.length; i++) {
3893 Intent intent = intents[i];
3894 if (intent == null) {
3895 throw new IllegalArgumentException("Null intent at index " + i);
3896 }
3897 if (intent.hasFileDescriptors()) {
3898 throw new IllegalArgumentException("File descriptors passed in Intent");
3899 }
3900 if (type == INTENT_SENDER_BROADCAST &&
3901 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3902 throw new IllegalArgumentException(
3903 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3904 }
3905 intents[i] = new Intent(intent);
3906 }
3907 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003908 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003909 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003910 }
3911 }
3912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 synchronized(this) {
3914 int callingUid = Binder.getCallingUid();
3915 try {
3916 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3917 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003918 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003919 .getPackageUid(packageName);
3920 if (uid != Binder.getCallingUid()) {
3921 String msg = "Permission Denial: getIntentSender() from pid="
3922 + Binder.getCallingPid()
3923 + ", uid=" + Binder.getCallingUid()
3924 + ", (need uid=" + uid + ")"
3925 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003926 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003927 throw new SecurityException(msg);
3928 }
3929 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003930
3931 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003932 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 } catch (RemoteException e) {
3935 throw new SecurityException(e);
3936 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003937 }
3938 }
3939
3940 IIntentSender getIntentSenderLocked(int type,
3941 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003942 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003943 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003944 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003945 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003946 if (index < 0) {
3947 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003948 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003949 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003950 if (activity.finishing) {
3951 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003953 }
3954
3955 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3956 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3957 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3958 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3959 |PendingIntent.FLAG_UPDATE_CURRENT);
3960
3961 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3962 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003963 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003964 WeakReference<PendingIntentRecord> ref;
3965 ref = mIntentSenderRecords.get(key);
3966 PendingIntentRecord rec = ref != null ? ref.get() : null;
3967 if (rec != null) {
3968 if (!cancelCurrent) {
3969 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003970 if (rec.key.requestIntent != null) {
3971 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3972 }
3973 if (intents != null) {
3974 intents[intents.length-1] = rec.key.requestIntent;
3975 rec.key.allIntents = intents;
3976 rec.key.allResolvedTypes = resolvedTypes;
3977 } else {
3978 rec.key.allIntents = null;
3979 rec.key.allResolvedTypes = null;
3980 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003981 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003982 return rec;
3983 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003984 rec.canceled = true;
3985 mIntentSenderRecords.remove(key);
3986 }
3987 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 return rec;
3989 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003990 rec = new PendingIntentRecord(this, key, callingUid);
3991 mIntentSenderRecords.put(key, rec.ref);
3992 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3993 if (activity.pendingResults == null) {
3994 activity.pendingResults
3995 = new HashSet<WeakReference<PendingIntentRecord>>();
3996 }
3997 activity.pendingResults.add(rec.ref);
3998 }
3999 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 }
4001
4002 public void cancelIntentSender(IIntentSender sender) {
4003 if (!(sender instanceof PendingIntentRecord)) {
4004 return;
4005 }
4006 synchronized(this) {
4007 PendingIntentRecord rec = (PendingIntentRecord)sender;
4008 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004009 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 .getPackageUid(rec.key.packageName);
4011 if (uid != Binder.getCallingUid()) {
4012 String msg = "Permission Denial: cancelIntentSender() from pid="
4013 + Binder.getCallingPid()
4014 + ", uid=" + Binder.getCallingUid()
4015 + " is not allowed to cancel packges "
4016 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004017 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 throw new SecurityException(msg);
4019 }
4020 } catch (RemoteException e) {
4021 throw new SecurityException(e);
4022 }
4023 cancelIntentSenderLocked(rec, true);
4024 }
4025 }
4026
4027 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4028 rec.canceled = true;
4029 mIntentSenderRecords.remove(rec.key);
4030 if (cleanActivity && rec.key.activity != null) {
4031 rec.key.activity.pendingResults.remove(rec.ref);
4032 }
4033 }
4034
4035 public String getPackageForIntentSender(IIntentSender pendingResult) {
4036 if (!(pendingResult instanceof PendingIntentRecord)) {
4037 return null;
4038 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004039 try {
4040 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4041 return res.key.packageName;
4042 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004043 }
4044 return null;
4045 }
4046
4047 public void setProcessLimit(int max) {
4048 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4049 "setProcessLimit()");
4050 mProcessLimit = max;
4051 }
4052
4053 public int getProcessLimit() {
4054 return mProcessLimit;
4055 }
4056
4057 void foregroundTokenDied(ForegroundToken token) {
4058 synchronized (ActivityManagerService.this) {
4059 synchronized (mPidsSelfLocked) {
4060 ForegroundToken cur
4061 = mForegroundProcesses.get(token.pid);
4062 if (cur != token) {
4063 return;
4064 }
4065 mForegroundProcesses.remove(token.pid);
4066 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4067 if (pr == null) {
4068 return;
4069 }
4070 pr.forcingToForeground = null;
4071 pr.foregroundServices = false;
4072 }
4073 updateOomAdjLocked();
4074 }
4075 }
4076
4077 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4078 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4079 "setProcessForeground()");
4080 synchronized(this) {
4081 boolean changed = false;
4082
4083 synchronized (mPidsSelfLocked) {
4084 ProcessRecord pr = mPidsSelfLocked.get(pid);
4085 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004086 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004087 return;
4088 }
4089 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4090 if (oldToken != null) {
4091 oldToken.token.unlinkToDeath(oldToken, 0);
4092 mForegroundProcesses.remove(pid);
4093 pr.forcingToForeground = null;
4094 changed = true;
4095 }
4096 if (isForeground && token != null) {
4097 ForegroundToken newToken = new ForegroundToken() {
4098 public void binderDied() {
4099 foregroundTokenDied(this);
4100 }
4101 };
4102 newToken.pid = pid;
4103 newToken.token = token;
4104 try {
4105 token.linkToDeath(newToken, 0);
4106 mForegroundProcesses.put(pid, newToken);
4107 pr.forcingToForeground = token;
4108 changed = true;
4109 } catch (RemoteException e) {
4110 // If the process died while doing this, we will later
4111 // do the cleanup with the process death link.
4112 }
4113 }
4114 }
4115
4116 if (changed) {
4117 updateOomAdjLocked();
4118 }
4119 }
4120 }
4121
4122 // =========================================================
4123 // PERMISSIONS
4124 // =========================================================
4125
4126 static class PermissionController extends IPermissionController.Stub {
4127 ActivityManagerService mActivityManagerService;
4128 PermissionController(ActivityManagerService activityManagerService) {
4129 mActivityManagerService = activityManagerService;
4130 }
4131
4132 public boolean checkPermission(String permission, int pid, int uid) {
4133 return mActivityManagerService.checkPermission(permission, pid,
4134 uid) == PackageManager.PERMISSION_GRANTED;
4135 }
4136 }
4137
4138 /**
4139 * This can be called with or without the global lock held.
4140 */
4141 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004142 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004143 // We might be performing an operation on behalf of an indirect binder
4144 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4145 // client identity accordingly before proceeding.
4146 Identity tlsIdentity = sCallerIdentity.get();
4147 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004148 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004149 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4150 uid = tlsIdentity.uid;
4151 pid = tlsIdentity.pid;
4152 }
4153
4154 // Root, system server and our own process get to do everything.
4155 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4156 !Process.supportsProcesses()) {
4157 return PackageManager.PERMISSION_GRANTED;
4158 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004159 // If there is a uid that owns whatever is being accessed, it has
4160 // blanket access to it regardless of the permissions it requires.
4161 if (owningUid >= 0 && uid == owningUid) {
4162 return PackageManager.PERMISSION_GRANTED;
4163 }
4164 // If the target is not exported, then nobody else can get to it.
4165 if (!exported) {
4166 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004167 return PackageManager.PERMISSION_DENIED;
4168 }
4169 if (permission == null) {
4170 return PackageManager.PERMISSION_GRANTED;
4171 }
4172 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004173 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174 .checkUidPermission(permission, uid);
4175 } catch (RemoteException e) {
4176 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004177 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004178 }
4179 return PackageManager.PERMISSION_DENIED;
4180 }
4181
4182 /**
4183 * As the only public entry point for permissions checking, this method
4184 * can enforce the semantic that requesting a check on a null global
4185 * permission is automatically denied. (Internally a null permission
4186 * string is used when calling {@link #checkComponentPermission} in cases
4187 * when only uid-based security is needed.)
4188 *
4189 * This can be called with or without the global lock held.
4190 */
4191 public int checkPermission(String permission, int pid, int uid) {
4192 if (permission == null) {
4193 return PackageManager.PERMISSION_DENIED;
4194 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004195 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004196 }
4197
4198 /**
4199 * Binder IPC calls go through the public entry point.
4200 * This can be called with or without the global lock held.
4201 */
4202 int checkCallingPermission(String permission) {
4203 return checkPermission(permission,
4204 Binder.getCallingPid(),
4205 Binder.getCallingUid());
4206 }
4207
4208 /**
4209 * This can be called with or without the global lock held.
4210 */
4211 void enforceCallingPermission(String permission, String func) {
4212 if (checkCallingPermission(permission)
4213 == PackageManager.PERMISSION_GRANTED) {
4214 return;
4215 }
4216
4217 String msg = "Permission Denial: " + func + " from pid="
4218 + Binder.getCallingPid()
4219 + ", uid=" + Binder.getCallingUid()
4220 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004221 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004222 throw new SecurityException(msg);
4223 }
4224
4225 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004226 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4227 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4228 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4229 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4230 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004231 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004232 // Is the component private from the target uid?
4233 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4234
4235 // Acceptable if the there is no read permission needed from the
4236 // target or the target is holding the read permission.
4237 if (!readPerm) {
4238 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004239 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004240 == PackageManager.PERMISSION_GRANTED)) {
4241 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 }
4243 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004244
4245 // Acceptable if the there is no write permission needed from the
4246 // target or the target is holding the read permission.
4247 if (!writePerm) {
4248 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004250 == PackageManager.PERMISSION_GRANTED)) {
4251 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004252 }
4253 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004254
4255 // Acceptable if there is a path permission matching the URI that
4256 // the target holds the permission on.
4257 PathPermission[] pps = pi.pathPermissions;
4258 if (pps != null && (!readPerm || !writePerm)) {
4259 final String path = uri.getPath();
4260 int i = pps.length;
4261 while (i > 0 && (!readPerm || !writePerm)) {
4262 i--;
4263 PathPermission pp = pps[i];
4264 if (!readPerm) {
4265 final String pprperm = pp.getReadPermission();
4266 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4267 + pprperm + " for " + pp.getPath()
4268 + ": match=" + pp.match(path)
4269 + " check=" + pm.checkUidPermission(pprperm, uid));
4270 if (pprperm != null && pp.match(path) &&
4271 (pm.checkUidPermission(pprperm, uid)
4272 == PackageManager.PERMISSION_GRANTED)) {
4273 readPerm = true;
4274 }
4275 }
4276 if (!writePerm) {
4277 final String ppwperm = pp.getWritePermission();
4278 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4279 + ppwperm + " for " + pp.getPath()
4280 + ": match=" + pp.match(path)
4281 + " check=" + pm.checkUidPermission(ppwperm, uid));
4282 if (ppwperm != null && pp.match(path) &&
4283 (pm.checkUidPermission(ppwperm, uid)
4284 == PackageManager.PERMISSION_GRANTED)) {
4285 writePerm = true;
4286 }
4287 }
4288 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 } catch (RemoteException e) {
4291 return false;
4292 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004293
4294 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 }
4296
4297 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4298 int modeFlags) {
4299 // Root gets to do everything.
4300 if (uid == 0 || !Process.supportsProcesses()) {
4301 return true;
4302 }
4303 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4304 if (perms == null) return false;
4305 UriPermission perm = perms.get(uri);
4306 if (perm == null) return false;
4307 return (modeFlags&perm.modeFlags) == modeFlags;
4308 }
4309
4310 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4311 // Another redirected-binder-call permissions check as in
4312 // {@link checkComponentPermission}.
4313 Identity tlsIdentity = sCallerIdentity.get();
4314 if (tlsIdentity != null) {
4315 uid = tlsIdentity.uid;
4316 pid = tlsIdentity.pid;
4317 }
4318
4319 // Our own process gets to do everything.
4320 if (pid == MY_PID) {
4321 return PackageManager.PERMISSION_GRANTED;
4322 }
4323 synchronized(this) {
4324 return checkUriPermissionLocked(uri, uid, modeFlags)
4325 ? PackageManager.PERMISSION_GRANTED
4326 : PackageManager.PERMISSION_DENIED;
4327 }
4328 }
4329
Dianne Hackborn39792d22010-08-19 18:01:52 -07004330 /**
4331 * Check if the targetPkg can be granted permission to access uri by
4332 * the callingUid using the given modeFlags. Throws a security exception
4333 * if callingUid is not allowed to do this. Returns the uid of the target
4334 * if the URI permission grant should be performed; returns -1 if it is not
4335 * needed (for example targetPkg already has permission to access the URI).
4336 */
4337 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4338 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4340 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4341 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004342 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004343 }
4344
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004345 if (targetPkg != null) {
4346 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4347 "Checking grant " + targetPkg + " permission to " + uri);
4348 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004349
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004350 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004351
4352 // If this is not a content: uri, we can't do anything with it.
4353 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004354 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004355 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004356 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 }
4358
4359 String name = uri.getAuthority();
4360 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004361 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004362 if (cpr != null) {
4363 pi = cpr.info;
4364 } else {
4365 try {
4366 pi = pm.resolveContentProvider(name,
4367 PackageManager.GET_URI_PERMISSION_PATTERNS);
4368 } catch (RemoteException ex) {
4369 }
4370 }
4371 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004372 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004373 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 }
4375
4376 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004377 if (targetPkg != null) {
4378 try {
4379 targetUid = pm.getPackageUid(targetPkg);
4380 if (targetUid < 0) {
4381 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4382 "Can't grant URI permission no uid for: " + targetPkg);
4383 return -1;
4384 }
4385 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004386 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004387 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004388 } else {
4389 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004390 }
4391
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004392 if (targetUid >= 0) {
4393 // First... does the target actually need this permission?
4394 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4395 // No need to grant the target this permission.
4396 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4397 "Target " + targetPkg + " already has full permission to " + uri);
4398 return -1;
4399 }
4400 } else {
4401 // First... there is no target package, so can anyone access it?
4402 boolean allowed = pi.exported;
4403 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4404 if (pi.readPermission != null) {
4405 allowed = false;
4406 }
4407 }
4408 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4409 if (pi.writePermission != null) {
4410 allowed = false;
4411 }
4412 }
4413 if (allowed) {
4414 return -1;
4415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004416 }
4417
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004418 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004419 if (!pi.grantUriPermissions) {
4420 throw new SecurityException("Provider " + pi.packageName
4421 + "/" + pi.name
4422 + " does not allow granting of Uri permissions (uri "
4423 + uri + ")");
4424 }
4425 if (pi.uriPermissionPatterns != null) {
4426 final int N = pi.uriPermissionPatterns.length;
4427 boolean allowed = false;
4428 for (int i=0; i<N; i++) {
4429 if (pi.uriPermissionPatterns[i] != null
4430 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4431 allowed = true;
4432 break;
4433 }
4434 }
4435 if (!allowed) {
4436 throw new SecurityException("Provider " + pi.packageName
4437 + "/" + pi.name
4438 + " does not allow granting of permission to path of Uri "
4439 + uri);
4440 }
4441 }
4442
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004443 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004445 if (callingUid != Process.myUid()) {
4446 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4447 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4448 throw new SecurityException("Uid " + callingUid
4449 + " does not have permission to uri " + uri);
4450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 }
4452 }
4453
Dianne Hackborn39792d22010-08-19 18:01:52 -07004454 return targetUid;
4455 }
4456
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004457 public int checkGrantUriPermission(int callingUid, String targetPkg,
4458 Uri uri, int modeFlags) {
4459 synchronized(this) {
4460 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4461 }
4462 }
4463
Dianne Hackborn39792d22010-08-19 18:01:52 -07004464 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4465 Uri uri, int modeFlags, UriPermissionOwner owner) {
4466 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4467 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4468 if (modeFlags == 0) {
4469 return;
4470 }
4471
4472 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 // to the uri, and the target doesn't. Let's now give this to
4474 // the target.
4475
Joe Onorato8a9b2202010-02-26 18:56:32 -08004476 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004477 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 HashMap<Uri, UriPermission> targetUris
4480 = mGrantedUriPermissions.get(targetUid);
4481 if (targetUris == null) {
4482 targetUris = new HashMap<Uri, UriPermission>();
4483 mGrantedUriPermissions.put(targetUid, targetUris);
4484 }
4485
4486 UriPermission perm = targetUris.get(uri);
4487 if (perm == null) {
4488 perm = new UriPermission(targetUid, uri);
4489 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004492 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004493 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004494 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004495 } else {
4496 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4497 perm.readOwners.add(owner);
4498 owner.addReadPermission(perm);
4499 }
4500 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4501 perm.writeOwners.add(owner);
4502 owner.addWritePermission(perm);
4503 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504 }
4505 }
4506
Dianne Hackborn39792d22010-08-19 18:01:52 -07004507 void grantUriPermissionLocked(int callingUid,
4508 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004509 if (targetPkg == null) {
4510 throw new NullPointerException("targetPkg");
4511 }
4512
Dianne Hackborn39792d22010-08-19 18:01:52 -07004513 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4514 if (targetUid < 0) {
4515 return;
4516 }
4517
4518 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4519 }
4520
4521 /**
4522 * Like checkGrantUriPermissionLocked, but takes an Intent.
4523 */
4524 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4525 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004526 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004527 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004528 + " from " + intent + "; flags=0x"
4529 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4530
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004531 if (targetPkg == null) {
4532 throw new NullPointerException("targetPkg");
4533 }
4534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004535 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004536 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004537 }
4538 Uri data = intent.getData();
4539 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004540 return -1;
4541 }
4542 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4543 intent.getFlags());
4544 }
4545
4546 /**
4547 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4548 */
4549 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4550 String targetPkg, Intent intent, UriPermissionOwner owner) {
4551 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4552 intent.getFlags(), owner);
4553 }
4554
4555 void grantUriPermissionFromIntentLocked(int callingUid,
4556 String targetPkg, Intent intent, UriPermissionOwner owner) {
4557 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4558 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 return;
4560 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004561
4562 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004563 }
4564
4565 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4566 Uri uri, int modeFlags) {
4567 synchronized(this) {
4568 final ProcessRecord r = getRecordForAppLocked(caller);
4569 if (r == null) {
4570 throw new SecurityException("Unable to find app for caller "
4571 + caller
4572 + " when granting permission to uri " + uri);
4573 }
4574 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004575 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 }
4577 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004578 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 }
4580
4581 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4582 null);
4583 }
4584 }
4585
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004586 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004587 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4588 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4589 HashMap<Uri, UriPermission> perms
4590 = mGrantedUriPermissions.get(perm.uid);
4591 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004592 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004593 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 perms.remove(perm.uri);
4595 if (perms.size() == 0) {
4596 mGrantedUriPermissions.remove(perm.uid);
4597 }
4598 }
4599 }
4600 }
4601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4603 int modeFlags) {
4604 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4605 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4606 if (modeFlags == 0) {
4607 return;
4608 }
4609
Joe Onorato8a9b2202010-02-26 18:56:32 -08004610 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004611 "Revoking all granted permissions to " + uri);
4612
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004613 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004614
4615 final String authority = uri.getAuthority();
4616 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004617 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 if (cpr != null) {
4619 pi = cpr.info;
4620 } else {
4621 try {
4622 pi = pm.resolveContentProvider(authority,
4623 PackageManager.GET_URI_PERMISSION_PATTERNS);
4624 } catch (RemoteException ex) {
4625 }
4626 }
4627 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004628 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 return;
4630 }
4631
4632 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004633 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634 // Right now, if you are not the original owner of the permission,
4635 // you are not allowed to revoke it.
4636 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4637 throw new SecurityException("Uid " + callingUid
4638 + " does not have permission to uri " + uri);
4639 //}
4640 }
4641
4642 // Go through all of the permissions and remove any that match.
4643 final List<String> SEGMENTS = uri.getPathSegments();
4644 if (SEGMENTS != null) {
4645 final int NS = SEGMENTS.size();
4646 int N = mGrantedUriPermissions.size();
4647 for (int i=0; i<N; i++) {
4648 HashMap<Uri, UriPermission> perms
4649 = mGrantedUriPermissions.valueAt(i);
4650 Iterator<UriPermission> it = perms.values().iterator();
4651 toploop:
4652 while (it.hasNext()) {
4653 UriPermission perm = it.next();
4654 Uri targetUri = perm.uri;
4655 if (!authority.equals(targetUri.getAuthority())) {
4656 continue;
4657 }
4658 List<String> targetSegments = targetUri.getPathSegments();
4659 if (targetSegments == null) {
4660 continue;
4661 }
4662 if (targetSegments.size() < NS) {
4663 continue;
4664 }
4665 for (int j=0; j<NS; j++) {
4666 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4667 continue toploop;
4668 }
4669 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004670 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004671 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004672 perm.clearModes(modeFlags);
4673 if (perm.modeFlags == 0) {
4674 it.remove();
4675 }
4676 }
4677 if (perms.size() == 0) {
4678 mGrantedUriPermissions.remove(
4679 mGrantedUriPermissions.keyAt(i));
4680 N--;
4681 i--;
4682 }
4683 }
4684 }
4685 }
4686
4687 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4688 int modeFlags) {
4689 synchronized(this) {
4690 final ProcessRecord r = getRecordForAppLocked(caller);
4691 if (r == null) {
4692 throw new SecurityException("Unable to find app for caller "
4693 + caller
4694 + " when revoking permission to uri " + uri);
4695 }
4696 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004697 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004698 return;
4699 }
4700
4701 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4702 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4703 if (modeFlags == 0) {
4704 return;
4705 }
4706
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004707 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004708
4709 final String authority = uri.getAuthority();
4710 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004711 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 if (cpr != null) {
4713 pi = cpr.info;
4714 } else {
4715 try {
4716 pi = pm.resolveContentProvider(authority,
4717 PackageManager.GET_URI_PERMISSION_PATTERNS);
4718 } catch (RemoteException ex) {
4719 }
4720 }
4721 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004722 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004723 return;
4724 }
4725
4726 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4727 }
4728 }
4729
Dianne Hackborn7e269642010-08-25 19:50:20 -07004730 @Override
4731 public IBinder newUriPermissionOwner(String name) {
4732 synchronized(this) {
4733 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4734 return owner.getExternalTokenLocked();
4735 }
4736 }
4737
4738 @Override
4739 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4740 Uri uri, int modeFlags) {
4741 synchronized(this) {
4742 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4743 if (owner == null) {
4744 throw new IllegalArgumentException("Unknown owner: " + token);
4745 }
4746 if (fromUid != Binder.getCallingUid()) {
4747 if (Binder.getCallingUid() != Process.myUid()) {
4748 // Only system code can grant URI permissions on behalf
4749 // of other users.
4750 throw new SecurityException("nice try");
4751 }
4752 }
4753 if (targetPkg == null) {
4754 throw new IllegalArgumentException("null target");
4755 }
4756 if (uri == null) {
4757 throw new IllegalArgumentException("null uri");
4758 }
4759
4760 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4761 }
4762 }
4763
4764 @Override
4765 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4766 synchronized(this) {
4767 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4768 if (owner == null) {
4769 throw new IllegalArgumentException("Unknown owner: " + token);
4770 }
4771
4772 if (uri == null) {
4773 owner.removeUriPermissionsLocked(mode);
4774 } else {
4775 owner.removeUriPermissionLocked(uri, mode);
4776 }
4777 }
4778 }
4779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4781 synchronized (this) {
4782 ProcessRecord app =
4783 who != null ? getRecordForAppLocked(who) : null;
4784 if (app == null) return;
4785
4786 Message msg = Message.obtain();
4787 msg.what = WAIT_FOR_DEBUGGER_MSG;
4788 msg.obj = app;
4789 msg.arg1 = waiting ? 1 : 0;
4790 mHandler.sendMessage(msg);
4791 }
4792 }
4793
4794 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4795 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004796 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004798 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004799 }
4800
4801 // =========================================================
4802 // TASK MANAGEMENT
4803 // =========================================================
4804
4805 public List getTasks(int maxNum, int flags,
4806 IThumbnailReceiver receiver) {
4807 ArrayList list = new ArrayList();
4808
4809 PendingThumbnailsRecord pending = null;
4810 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004811 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004812
4813 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004814 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4816 + ", receiver=" + receiver);
4817
4818 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4819 != PackageManager.PERMISSION_GRANTED) {
4820 if (receiver != null) {
4821 // If the caller wants to wait for pending thumbnails,
4822 // it ain't gonna get them.
4823 try {
4824 receiver.finished();
4825 } catch (RemoteException ex) {
4826 }
4827 }
4828 String msg = "Permission Denial: getTasks() from pid="
4829 + Binder.getCallingPid()
4830 + ", uid=" + Binder.getCallingUid()
4831 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004832 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004833 throw new SecurityException(msg);
4834 }
4835
Dianne Hackbornd2835932010-12-13 16:28:46 -08004836 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4837 && checkCallingPermission(
4838 android.Manifest.permission.READ_FRAME_BUFFER)
4839 == PackageManager.PERMISSION_GRANTED;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004840
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004841 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004842 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004843 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004844 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 TaskRecord curTask = null;
4846 int numActivities = 0;
4847 int numRunning = 0;
4848 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004849 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004850 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004851 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004852
4853 // Initialize state for next task if needed.
4854 if (top == null ||
4855 (top.state == ActivityState.INITIALIZING
4856 && top.task == r.task)) {
4857 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 curTask = r.task;
4859 numActivities = numRunning = 0;
4860 }
4861
4862 // Add 'r' into the current task.
4863 numActivities++;
4864 if (r.app != null && r.app.thread != null) {
4865 numRunning++;
4866 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004867
Joe Onorato8a9b2202010-02-26 18:56:32 -08004868 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004869 TAG, r.intent.getComponent().flattenToShortString()
4870 + ": task=" + r.task);
4871
4872 // If the next one is a different task, generate a new
4873 // TaskInfo entry for what we have.
4874 if (next == null || next.task != curTask) {
4875 ActivityManager.RunningTaskInfo ci
4876 = new ActivityManager.RunningTaskInfo();
4877 ci.id = curTask.taskId;
4878 ci.baseActivity = r.intent.getComponent();
4879 ci.topActivity = top.intent.getComponent();
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004880 if (canReadFb) {
Dianne Hackbornf26fd992011-04-08 18:14:09 -07004881 if (top.state == ActivityState.RESUMED) {
Dianne Hackbornd2835932010-12-13 16:28:46 -08004882 ci.thumbnail = top.stack.screenshotActivities(top);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07004883 } else if (top.thumbHolder != null) {
4884 ci.thumbnail = top.thumbHolder.lastThumbnail;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004885 }
4886 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07004887 if (top.thumbHolder != null) {
4888 ci.description = top.thumbHolder.lastDescription;
4889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004890 ci.numActivities = numActivities;
4891 ci.numRunning = numRunning;
4892 //System.out.println(
4893 // "#" + maxNum + ": " + " descr=" + ci.description);
4894 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004895 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 TAG, "State=" + top.state + "Idle=" + top.idle
4897 + " app=" + top.app
4898 + " thr=" + (top.app != null ? top.app.thread : null));
4899 if (top.state == ActivityState.RESUMED
4900 || top.state == ActivityState.PAUSING) {
4901 if (top.idle && top.app != null
4902 && top.app.thread != null) {
4903 topRecord = top;
4904 topThumbnail = top.app.thread;
4905 } else {
4906 top.thumbnailNeeded = true;
4907 }
4908 }
4909 if (pending == null) {
4910 pending = new PendingThumbnailsRecord(receiver);
4911 }
4912 pending.pendingRecords.add(top);
4913 }
4914 list.add(ci);
4915 maxNum--;
4916 top = null;
4917 }
4918 }
4919
4920 if (pending != null) {
4921 mPendingThumbnails.add(pending);
4922 }
4923 }
4924
Joe Onorato8a9b2202010-02-26 18:56:32 -08004925 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004926
4927 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004928 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 try {
4930 topThumbnail.requestThumbnail(topRecord);
4931 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004932 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 sendPendingThumbnail(null, topRecord, null, null, true);
4934 }
4935 }
4936
4937 if (pending == null && receiver != null) {
4938 // In this case all thumbnails were available and the client
4939 // is being asked to be told when the remaining ones come in...
4940 // which is unusually, since the top-most currently running
4941 // activity should never have a canned thumbnail! Oh well.
4942 try {
4943 receiver.finished();
4944 } catch (RemoteException ex) {
4945 }
4946 }
4947
4948 return list;
4949 }
4950
4951 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4952 int flags) {
4953 synchronized (this) {
4954 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4955 "getRecentTasks()");
4956
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004957 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004958
Dianne Hackbornd2835932010-12-13 16:28:46 -08004959 ActivityRecord resumed = mMainStack.mResumedActivity;
4960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 final int N = mRecentTasks.size();
4962 ArrayList<ActivityManager.RecentTaskInfo> res
4963 = new ArrayList<ActivityManager.RecentTaskInfo>(
4964 maxNum < N ? maxNum : N);
4965 for (int i=0; i<N && maxNum > 0; i++) {
4966 TaskRecord tr = mRecentTasks.get(i);
4967 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4968 || (tr.intent == null)
4969 || ((tr.intent.getFlags()
4970 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4971 ActivityManager.RecentTaskInfo rti
4972 = new ActivityManager.RecentTaskInfo();
4973 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08004974 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004975 rti.baseIntent = new Intent(
4976 tr.intent != null ? tr.intent : tr.affinityIntent);
4977 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08004978 rti.description = tr.lastDescription;
4979
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004980 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4981 // Check whether this activity is currently available.
4982 try {
4983 if (rti.origActivity != null) {
4984 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4985 continue;
4986 }
4987 } else if (rti.baseIntent != null) {
4988 if (pm.queryIntentActivities(rti.baseIntent,
4989 null, 0) == null) {
4990 continue;
4991 }
4992 }
4993 } catch (RemoteException e) {
4994 // Will never happen.
4995 }
4996 }
4997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004998 res.add(rti);
4999 maxNum--;
5000 }
5001 }
5002 return res;
5003 }
5004 }
5005
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005006 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005007 synchronized (this) {
5008 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5009 "getTaskThumbnail()");
5010 ActivityRecord resumed = mMainStack.mResumedActivity;
5011 final int N = mRecentTasks.size();
5012 for (int i=0; i<N; i++) {
5013 TaskRecord tr = mRecentTasks.get(i);
5014 if (tr.taskId == id) {
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005015 final ActivityManager.TaskThumbnails thumbs
5016 = new ActivityManager.TaskThumbnails();
5017 if (resumed != null && resumed.thumbHolder == tr) {
5018 thumbs.mainThumbnail = resumed.stack.screenshotActivities(resumed);
Dianne Hackbornd94df452011-02-16 18:53:31 -08005019 } else {
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005020 thumbs.mainThumbnail = tr.lastThumbnail;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005021 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005022 // How many different sub-thumbnails?
5023 final int NA = mMainStack.mHistory.size();
5024 int j = 0;
5025 ThumbnailHolder holder = null;
5026 while (j < NA) {
5027 ActivityRecord ar = (ActivityRecord)mMainStack.mHistory.get(j);
5028 j++;
5029 if (ar.task == tr) {
5030 holder = ar.thumbHolder;
5031 break;
5032 }
5033 }
5034 ArrayList<Bitmap> bitmaps = new ArrayList<Bitmap>();
5035 thumbs.otherThumbnails = bitmaps;
5036 ActivityRecord lastActivity = null;
5037 while (j < NA) {
5038 ActivityRecord ar = (ActivityRecord)mMainStack.mHistory.get(j);
5039 j++;
5040 if (ar.task != tr) {
5041 break;
5042 }
5043 lastActivity = ar;
5044 if (ar.thumbHolder != holder && holder != null) {
5045 thumbs.numSubThumbbails++;
5046 holder = ar.thumbHolder;
5047 bitmaps.add(holder.lastThumbnail);
5048 }
5049 }
5050 if (lastActivity != null && bitmaps.size() > 0) {
5051 if (resumed == lastActivity) {
5052 Bitmap bm = lastActivity.stack.screenshotActivities(lastActivity);
5053 if (bm != null) {
5054 bitmaps.remove(bitmaps.size()-1);
5055 bitmaps.add(bm);
5056 }
5057 }
5058 }
5059 if (thumbs.numSubThumbbails > 0) {
5060 thumbs.retriever = new IThumbnailRetriever.Stub() {
5061 public Bitmap getThumbnail(int index) {
5062 if (index < 0 || index >= thumbs.otherThumbnails.size()) {
5063 return null;
5064 }
5065 return thumbs.otherThumbnails.get(index);
5066 }
5067 };
5068 }
5069 return thumbs;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005070 }
5071 }
5072 }
5073 return null;
5074 }
5075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005076 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5077 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005078 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 TaskRecord jt = startTask;
5080
5081 // First look backwards
5082 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005083 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005084 if (r.task != jt) {
5085 jt = r.task;
5086 if (affinity.equals(jt.affinity)) {
5087 return j;
5088 }
5089 }
5090 }
5091
5092 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005093 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005094 jt = startTask;
5095 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005096 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 if (r.task != jt) {
5098 if (affinity.equals(jt.affinity)) {
5099 return j;
5100 }
5101 jt = r.task;
5102 }
5103 }
5104
5105 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005106 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005107 return N-1;
5108 }
5109
5110 return -1;
5111 }
5112
5113 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005114 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005116 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005117 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5118 "moveTaskToFront()");
5119
5120 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005121 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5122 Binder.getCallingUid(), "Task to front")) {
5123 return;
5124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005125 final long origId = Binder.clearCallingIdentity();
5126 try {
5127 int N = mRecentTasks.size();
5128 for (int i=0; i<N; i++) {
5129 TaskRecord tr = mRecentTasks.get(i);
5130 if (tr.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005131 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5132 mMainStack.mUserLeaving = true;
5133 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005134 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5135 // Caller wants the home activity moved with it. To accomplish this,
5136 // we'll just move the home task to the top first.
5137 mMainStack.moveHomeToFrontLocked();
5138 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005139 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 return;
5141 }
5142 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005143 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5144 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005146 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5147 mMainStack.mUserLeaving = true;
5148 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005149 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5150 // Caller wants the home activity moved with it. To accomplish this,
5151 // we'll just move the home task to the top first.
5152 mMainStack.moveHomeToFrontLocked();
5153 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005154 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005155 return;
5156 }
5157 }
5158 } finally {
5159 Binder.restoreCallingIdentity(origId);
5160 }
5161 }
5162 }
5163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005164 public void moveTaskToBack(int task) {
5165 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5166 "moveTaskToBack()");
5167
5168 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005169 if (mMainStack.mResumedActivity != null
5170 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005171 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5172 Binder.getCallingUid(), "Task to back")) {
5173 return;
5174 }
5175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005176 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005177 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005178 Binder.restoreCallingIdentity(origId);
5179 }
5180 }
5181
5182 /**
5183 * Moves an activity, and all of the other activities within the same task, to the bottom
5184 * of the history stack. The activity's order within the task is unchanged.
5185 *
5186 * @param token A reference to the activity we wish to move
5187 * @param nonRoot If false then this only works if the activity is the root
5188 * of a task; if true it will work for any activity in a task.
5189 * @return Returns true if the move completed, false if not.
5190 */
5191 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5192 synchronized(this) {
5193 final long origId = Binder.clearCallingIdentity();
5194 int taskId = getTaskForActivityLocked(token, !nonRoot);
5195 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005196 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 }
5198 Binder.restoreCallingIdentity(origId);
5199 }
5200 return false;
5201 }
5202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203 public void moveTaskBackwards(int task) {
5204 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5205 "moveTaskBackwards()");
5206
5207 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005208 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5209 Binder.getCallingUid(), "Task backwards")) {
5210 return;
5211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005212 final long origId = Binder.clearCallingIdentity();
5213 moveTaskBackwardsLocked(task);
5214 Binder.restoreCallingIdentity(origId);
5215 }
5216 }
5217
5218 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005219 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 }
5221
5222 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5223 synchronized(this) {
5224 return getTaskForActivityLocked(token, onlyRoot);
5225 }
5226 }
5227
5228 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005229 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005230 TaskRecord lastTask = null;
5231 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005232 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 if (r == token) {
5234 if (!onlyRoot || lastTask != r.task) {
5235 return r.task.taskId;
5236 }
5237 return -1;
5238 }
5239 lastTask = r.task;
5240 }
5241
5242 return -1;
5243 }
5244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 public void finishOtherInstances(IBinder token, ComponentName className) {
5246 synchronized(this) {
5247 final long origId = Binder.clearCallingIdentity();
5248
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005249 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005250 TaskRecord lastTask = null;
5251 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005252 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005253 if (r.realActivity.equals(className)
5254 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005255 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 null, "others")) {
5257 i--;
5258 N--;
5259 }
5260 }
5261 lastTask = r.task;
5262 }
5263
5264 Binder.restoreCallingIdentity(origId);
5265 }
5266 }
5267
5268 // =========================================================
5269 // THUMBNAILS
5270 // =========================================================
5271
5272 public void reportThumbnail(IBinder token,
5273 Bitmap thumbnail, CharSequence description) {
5274 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5275 final long origId = Binder.clearCallingIdentity();
5276 sendPendingThumbnail(null, token, thumbnail, description, true);
5277 Binder.restoreCallingIdentity(origId);
5278 }
5279
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005280 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005281 Bitmap thumbnail, CharSequence description, boolean always) {
5282 TaskRecord task = null;
5283 ArrayList receivers = null;
5284
5285 //System.out.println("Send pending thumbnail: " + r);
5286
5287 synchronized(this) {
5288 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005289 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005290 if (index < 0) {
5291 return;
5292 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005293 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005295 if (thumbnail == null && r.thumbHolder != null) {
5296 thumbnail = r.thumbHolder.lastThumbnail;
5297 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005298 }
5299 if (thumbnail == null && !always) {
5300 // If there is no thumbnail, and this entry is not actually
5301 // going away, then abort for now and pick up the next
5302 // thumbnail we get.
5303 return;
5304 }
5305 task = r.task;
5306
5307 int N = mPendingThumbnails.size();
5308 int i=0;
5309 while (i<N) {
5310 PendingThumbnailsRecord pr =
5311 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5312 //System.out.println("Looking in " + pr.pendingRecords);
5313 if (pr.pendingRecords.remove(r)) {
5314 if (receivers == null) {
5315 receivers = new ArrayList();
5316 }
5317 receivers.add(pr);
5318 if (pr.pendingRecords.size() == 0) {
5319 pr.finished = true;
5320 mPendingThumbnails.remove(i);
5321 N--;
5322 continue;
5323 }
5324 }
5325 i++;
5326 }
5327 }
5328
5329 if (receivers != null) {
5330 final int N = receivers.size();
5331 for (int i=0; i<N; i++) {
5332 try {
5333 PendingThumbnailsRecord pr =
5334 (PendingThumbnailsRecord)receivers.get(i);
5335 pr.receiver.newThumbnail(
5336 task != null ? task.taskId : -1, thumbnail, description);
5337 if (pr.finished) {
5338 pr.receiver.finished();
5339 }
5340 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005341 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 }
5343 }
5344 }
5345 }
5346
5347 // =========================================================
5348 // CONTENT PROVIDERS
5349 // =========================================================
5350
5351 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5352 List providers = null;
5353 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005354 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005356 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 } catch (RemoteException ex) {
5358 }
5359 if (providers != null) {
5360 final int N = providers.size();
5361 for (int i=0; i<N; i++) {
5362 ProviderInfo cpi =
5363 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005364 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365 if (cpr == null) {
5366 cpr = new ContentProviderRecord(cpi, app.info);
5367 mProvidersByClass.put(cpi.name, cpr);
5368 }
5369 app.pubProviders.put(cpi.name, cpr);
5370 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005371 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005372 }
5373 }
5374 return providers;
5375 }
5376
5377 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005378 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5380 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5381 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005382 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005383 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005384 return null;
5385 }
5386 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005387 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 == PackageManager.PERMISSION_GRANTED) {
5389 return null;
5390 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005391
5392 PathPermission[] pps = cpi.pathPermissions;
5393 if (pps != null) {
5394 int i = pps.length;
5395 while (i > 0) {
5396 i--;
5397 PathPermission pp = pps[i];
5398 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005399 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005400 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005401 return null;
5402 }
5403 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005404 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005405 == PackageManager.PERMISSION_GRANTED) {
5406 return null;
5407 }
5408 }
5409 }
5410
Dianne Hackbornb424b632010-08-18 15:59:05 -07005411 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5412 if (perms != null) {
5413 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5414 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5415 return null;
5416 }
5417 }
5418 }
5419
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005420 String msg;
5421 if (!cpi.exported) {
5422 msg = "Permission Denial: opening provider " + cpi.name
5423 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5424 + ", uid=" + callingUid + ") that is not exported from uid "
5425 + cpi.applicationInfo.uid;
5426 } else {
5427 msg = "Permission Denial: opening provider " + cpi.name
5428 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5429 + ", uid=" + callingUid + ") requires "
5430 + cpi.readPermission + " or " + cpi.writePermission;
5431 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005432 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005433 return msg;
5434 }
5435
5436 private final ContentProviderHolder getContentProviderImpl(
5437 IApplicationThread caller, String name) {
5438 ContentProviderRecord cpr;
5439 ProviderInfo cpi = null;
5440
5441 synchronized(this) {
5442 ProcessRecord r = null;
5443 if (caller != null) {
5444 r = getRecordForAppLocked(caller);
5445 if (r == null) {
5446 throw new SecurityException(
5447 "Unable to find app for caller " + caller
5448 + " (pid=" + Binder.getCallingPid()
5449 + ") when getting content provider " + name);
5450 }
5451 }
5452
5453 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005454 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005455 if (cpr != null) {
5456 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005457 String msg;
5458 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5459 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005460 }
5461
5462 if (r != null && cpr.canRunHere(r)) {
5463 // This provider has been published or is in the process
5464 // of being published... but it is also allowed to run
5465 // in the caller's process, so don't make a connection
5466 // and just let the caller instantiate its own instance.
5467 if (cpr.provider != null) {
5468 // don't give caller the provider object, it needs
5469 // to make its own.
5470 cpr = new ContentProviderRecord(cpr);
5471 }
5472 return cpr;
5473 }
5474
5475 final long origId = Binder.clearCallingIdentity();
5476
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005477 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005478 // return it right away.
5479 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005480 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005481 "Adding provider requested by "
5482 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005483 + cpr.info.processName);
5484 Integer cnt = r.conProviders.get(cpr);
5485 if (cnt == null) {
5486 r.conProviders.put(cpr, new Integer(1));
5487 } else {
5488 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005490 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005491 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5492 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005493 // make sure to count it as being accessed and thus
5494 // back up on the LRU list. This is good because
5495 // content providers are often expensive to start.
5496 updateLruProcessLocked(cpr.app, false, true);
5497 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005498 } else {
5499 cpr.externals++;
5500 }
5501
5502 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005503 updateOomAdjLocked(cpr.app);
5504 }
5505
5506 Binder.restoreCallingIdentity(origId);
5507
5508 } else {
5509 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005510 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005511 resolveContentProvider(name,
5512 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 } catch (RemoteException ex) {
5514 }
5515 if (cpi == null) {
5516 return null;
5517 }
5518
Dianne Hackbornb424b632010-08-18 15:59:05 -07005519 String msg;
5520 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5521 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005522 }
5523
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005524 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005525 && !cpi.processName.equals("system")) {
5526 // If this content provider does not run in the system
5527 // process, and the system is not yet ready to run other
5528 // processes, then fail fast instead of hanging.
5529 throw new IllegalArgumentException(
5530 "Attempt to launch content provider before system ready");
5531 }
5532
Dianne Hackborn860755f2010-06-03 18:47:52 -07005533 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 final boolean firstClass = cpr == null;
5535 if (firstClass) {
5536 try {
5537 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005538 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005539 getApplicationInfo(
5540 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005541 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005542 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005543 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 + cpi.name);
5545 return null;
5546 }
5547 cpr = new ContentProviderRecord(cpi, ai);
5548 } catch (RemoteException ex) {
5549 // pm is in same process, this will never happen.
5550 }
5551 }
5552
5553 if (r != null && cpr.canRunHere(r)) {
5554 // If this is a multiprocess provider, then just return its
5555 // info and allow the caller to instantiate it. Only do
5556 // this if the provider is the same user as the caller's
5557 // process, or can run as root (so can be in any process).
5558 return cpr;
5559 }
5560
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005561 if (DEBUG_PROVIDER) {
5562 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005563 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005564 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 }
5566
5567 // This is single process, and our app is now connecting to it.
5568 // See if we are already in the process of launching this
5569 // provider.
5570 final int N = mLaunchingProviders.size();
5571 int i;
5572 for (i=0; i<N; i++) {
5573 if (mLaunchingProviders.get(i) == cpr) {
5574 break;
5575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 }
5577
5578 // If the provider is not already being launched, then get it
5579 // started.
5580 if (i >= N) {
5581 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005582
5583 try {
5584 // Content provider is now in use, its package can't be stopped.
5585 try {
5586 AppGlobals.getPackageManager().setPackageStoppedState(
5587 cpr.appInfo.packageName, false);
5588 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005589 } catch (IllegalArgumentException e) {
5590 Slog.w(TAG, "Failed trying to unstop package "
5591 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005592 }
5593
5594 ProcessRecord proc = startProcessLocked(cpi.processName,
5595 cpr.appInfo, false, 0, "content provider",
5596 new ComponentName(cpi.applicationInfo.packageName,
5597 cpi.name), false);
5598 if (proc == null) {
5599 Slog.w(TAG, "Unable to launch app "
5600 + cpi.applicationInfo.packageName + "/"
5601 + cpi.applicationInfo.uid + " for provider "
5602 + name + ": process is bad");
5603 return null;
5604 }
5605 cpr.launchingApp = proc;
5606 mLaunchingProviders.add(cpr);
5607 } finally {
5608 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005610 }
5611
5612 // Make sure the provider is published (the same provider class
5613 // may be published under multiple names).
5614 if (firstClass) {
5615 mProvidersByClass.put(cpi.name, cpr);
5616 }
5617 mProvidersByName.put(name, cpr);
5618
5619 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005620 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005621 "Adding provider requested by "
5622 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005623 + cpr.info.processName);
5624 Integer cnt = r.conProviders.get(cpr);
5625 if (cnt == null) {
5626 r.conProviders.put(cpr, new Integer(1));
5627 } else {
5628 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5629 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005630 cpr.clients.add(r);
5631 } else {
5632 cpr.externals++;
5633 }
5634 }
5635 }
5636
5637 // Wait for the provider to be published...
5638 synchronized (cpr) {
5639 while (cpr.provider == null) {
5640 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005641 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005642 + cpi.applicationInfo.packageName + "/"
5643 + cpi.applicationInfo.uid + " for provider "
5644 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005645 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005646 cpi.applicationInfo.packageName,
5647 cpi.applicationInfo.uid, name);
5648 return null;
5649 }
5650 try {
5651 cpr.wait();
5652 } catch (InterruptedException ex) {
5653 }
5654 }
5655 }
5656 return cpr;
5657 }
5658
5659 public final ContentProviderHolder getContentProvider(
5660 IApplicationThread caller, String name) {
5661 if (caller == null) {
5662 String msg = "null IApplicationThread when getting content provider "
5663 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005664 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005665 throw new SecurityException(msg);
5666 }
5667
5668 return getContentProviderImpl(caller, name);
5669 }
5670
5671 private ContentProviderHolder getContentProviderExternal(String name) {
5672 return getContentProviderImpl(null, name);
5673 }
5674
5675 /**
5676 * Drop a content provider from a ProcessRecord's bookkeeping
5677 * @param cpr
5678 */
5679 public void removeContentProvider(IApplicationThread caller, String name) {
5680 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005681 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005683 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005684 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005685 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005686 return;
5687 }
5688 final ProcessRecord r = getRecordForAppLocked(caller);
5689 if (r == null) {
5690 throw new SecurityException(
5691 "Unable to find app for caller " + caller +
5692 " when removing content provider " + name);
5693 }
5694 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005695 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005696 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005697 + r.info.processName + " from process "
5698 + localCpr.appInfo.processName);
5699 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005701 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005702 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005703 return;
5704 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005705 Integer cnt = r.conProviders.get(localCpr);
5706 if (cnt == null || cnt.intValue() <= 1) {
5707 localCpr.clients.remove(r);
5708 r.conProviders.remove(localCpr);
5709 } else {
5710 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5711 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005712 }
5713 updateOomAdjLocked();
5714 }
5715 }
5716
5717 private void removeContentProviderExternal(String name) {
5718 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005719 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 if(cpr == null) {
5721 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005722 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005723 return;
5724 }
5725
5726 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005727 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005728 localCpr.externals--;
5729 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005730 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005731 }
5732 updateOomAdjLocked();
5733 }
5734 }
5735
5736 public final void publishContentProviders(IApplicationThread caller,
5737 List<ContentProviderHolder> providers) {
5738 if (providers == null) {
5739 return;
5740 }
5741
5742 synchronized(this) {
5743 final ProcessRecord r = getRecordForAppLocked(caller);
5744 if (r == null) {
5745 throw new SecurityException(
5746 "Unable to find app for caller " + caller
5747 + " (pid=" + Binder.getCallingPid()
5748 + ") when publishing content providers");
5749 }
5750
5751 final long origId = Binder.clearCallingIdentity();
5752
5753 final int N = providers.size();
5754 for (int i=0; i<N; i++) {
5755 ContentProviderHolder src = providers.get(i);
5756 if (src == null || src.info == null || src.provider == null) {
5757 continue;
5758 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005759 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 if (dst != null) {
5761 mProvidersByClass.put(dst.info.name, dst);
5762 String names[] = dst.info.authority.split(";");
5763 for (int j = 0; j < names.length; j++) {
5764 mProvidersByName.put(names[j], dst);
5765 }
5766
5767 int NL = mLaunchingProviders.size();
5768 int j;
5769 for (j=0; j<NL; j++) {
5770 if (mLaunchingProviders.get(j) == dst) {
5771 mLaunchingProviders.remove(j);
5772 j--;
5773 NL--;
5774 }
5775 }
5776 synchronized (dst) {
5777 dst.provider = src.provider;
5778 dst.app = r;
5779 dst.notifyAll();
5780 }
5781 updateOomAdjLocked(r);
5782 }
5783 }
5784
5785 Binder.restoreCallingIdentity(origId);
5786 }
5787 }
5788
5789 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005790 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005791 synchronized (mSelf) {
5792 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5793 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005794 if (providers != null) {
5795 for (int i=providers.size()-1; i>=0; i--) {
5796 ProviderInfo pi = (ProviderInfo)providers.get(i);
5797 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5798 Slog.w(TAG, "Not installing system proc provider " + pi.name
5799 + ": not system .apk");
5800 providers.remove(i);
5801 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005802 }
5803 }
5804 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005805 if (providers != null) {
5806 mSystemThread.installSystemProviders(providers);
5807 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005808
5809 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005810 }
5811
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005812 /**
5813 * Allows app to retrieve the MIME type of a URI without having permission
5814 * to access its content provider.
5815 *
5816 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5817 *
5818 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5819 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5820 */
5821 public String getProviderMimeType(Uri uri) {
5822 final String name = uri.getAuthority();
5823 final long ident = Binder.clearCallingIdentity();
5824 ContentProviderHolder holder = null;
5825
5826 try {
5827 holder = getContentProviderExternal(name);
5828 if (holder != null) {
5829 return holder.provider.getType(uri);
5830 }
5831 } catch (RemoteException e) {
5832 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5833 return null;
5834 } finally {
5835 if (holder != null) {
5836 removeContentProviderExternal(name);
5837 }
5838 Binder.restoreCallingIdentity(ident);
5839 }
5840
5841 return null;
5842 }
5843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005844 // =========================================================
5845 // GLOBAL MANAGEMENT
5846 // =========================================================
5847
5848 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5849 ApplicationInfo info, String customProcess) {
5850 String proc = customProcess != null ? customProcess : info.processName;
5851 BatteryStatsImpl.Uid.Proc ps = null;
5852 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5853 synchronized (stats) {
5854 ps = stats.getProcessStatsLocked(info.uid, proc);
5855 }
5856 return new ProcessRecord(ps, thread, info, proc);
5857 }
5858
5859 final ProcessRecord addAppLocked(ApplicationInfo info) {
5860 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5861
5862 if (app == null) {
5863 app = newProcessRecordLocked(null, info, null);
5864 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005865 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005866 }
5867
Dianne Hackborne7f97212011-02-24 14:40:20 -08005868 // This package really, really can not be stopped.
5869 try {
5870 AppGlobals.getPackageManager().setPackageStoppedState(
5871 info.packageName, false);
5872 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005873 } catch (IllegalArgumentException e) {
5874 Slog.w(TAG, "Failed trying to unstop package "
5875 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005876 }
5877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5879 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5880 app.persistent = true;
5881 app.maxAdj = CORE_SERVER_ADJ;
5882 }
5883 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5884 mPersistentStartingProcesses.add(app);
5885 startProcessLocked(app, "added application", app.processName);
5886 }
5887
5888 return app;
5889 }
5890
5891 public void unhandledBack() {
5892 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5893 "unhandledBack()");
5894
5895 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005896 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005897 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005898 TAG, "Performing unhandledBack(): stack size = " + count);
5899 if (count > 1) {
5900 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005901 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005902 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5903 Binder.restoreCallingIdentity(origId);
5904 }
5905 }
5906 }
5907
5908 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5909 String name = uri.getAuthority();
5910 ContentProviderHolder cph = getContentProviderExternal(name);
5911 ParcelFileDescriptor pfd = null;
5912 if (cph != null) {
5913 // We record the binder invoker's uid in thread-local storage before
5914 // going to the content provider to open the file. Later, in the code
5915 // that handles all permissions checks, we look for this uid and use
5916 // that rather than the Activity Manager's own uid. The effect is that
5917 // we do the check against the caller's permissions even though it looks
5918 // to the content provider like the Activity Manager itself is making
5919 // the request.
5920 sCallerIdentity.set(new Identity(
5921 Binder.getCallingPid(), Binder.getCallingUid()));
5922 try {
5923 pfd = cph.provider.openFile(uri, "r");
5924 } catch (FileNotFoundException e) {
5925 // do nothing; pfd will be returned null
5926 } finally {
5927 // Ensure that whatever happens, we clean up the identity state
5928 sCallerIdentity.remove();
5929 }
5930
5931 // We've got the fd now, so we're done with the provider.
5932 removeContentProviderExternal(name);
5933 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005934 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 }
5936 return pfd;
5937 }
5938
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005939 // Actually is sleeping or shutting down or whatever else in the future
5940 // is an inactive state.
5941 public boolean isSleeping() {
5942 return mSleeping || mShuttingDown;
5943 }
5944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005945 public void goingToSleep() {
5946 synchronized(this) {
5947 mSleeping = true;
5948 mWindowManager.setEventDispatching(false);
5949
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005950 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005951
5952 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005953 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005954 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5955 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005956 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 }
5958 }
5959
Dianne Hackborn55280a92009-05-07 15:53:46 -07005960 public boolean shutdown(int timeout) {
5961 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5962 != PackageManager.PERMISSION_GRANTED) {
5963 throw new SecurityException("Requires permission "
5964 + android.Manifest.permission.SHUTDOWN);
5965 }
5966
5967 boolean timedout = false;
5968
5969 synchronized(this) {
5970 mShuttingDown = true;
5971 mWindowManager.setEventDispatching(false);
5972
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005973 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005974 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005975 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005976 while (mMainStack.mResumedActivity != null
5977 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005978 long delay = endTime - System.currentTimeMillis();
5979 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005980 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005981 timedout = true;
5982 break;
5983 }
5984 try {
5985 this.wait();
5986 } catch (InterruptedException e) {
5987 }
5988 }
5989 }
5990 }
5991
5992 mUsageStatsService.shutdown();
5993 mBatteryStatsService.shutdown();
5994
5995 return timedout;
5996 }
5997
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005998 public final void activitySlept(IBinder token) {
5999 if (localLOGV) Slog.v(
6000 TAG, "Activity slept: token=" + token);
6001
6002 ActivityRecord r = null;
6003
6004 final long origId = Binder.clearCallingIdentity();
6005
6006 synchronized (this) {
6007 int index = mMainStack.indexOfTokenLocked(token);
6008 if (index >= 0) {
6009 r = (ActivityRecord)mMainStack.mHistory.get(index);
6010 mMainStack.activitySleptLocked(r);
6011 }
6012 }
6013
6014 Binder.restoreCallingIdentity(origId);
6015 }
6016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006017 public void wakingUp() {
6018 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006019 mWindowManager.setEventDispatching(true);
6020 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006021 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006022 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006023 }
6024 }
6025
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006026 public void stopAppSwitches() {
6027 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6028 != PackageManager.PERMISSION_GRANTED) {
6029 throw new SecurityException("Requires permission "
6030 + android.Manifest.permission.STOP_APP_SWITCHES);
6031 }
6032
6033 synchronized(this) {
6034 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6035 + APP_SWITCH_DELAY_TIME;
6036 mDidAppSwitch = false;
6037 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6038 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6039 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6040 }
6041 }
6042
6043 public void resumeAppSwitches() {
6044 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6045 != PackageManager.PERMISSION_GRANTED) {
6046 throw new SecurityException("Requires permission "
6047 + android.Manifest.permission.STOP_APP_SWITCHES);
6048 }
6049
6050 synchronized(this) {
6051 // Note that we don't execute any pending app switches... we will
6052 // let those wait until either the timeout, or the next start
6053 // activity request.
6054 mAppSwitchesAllowedTime = 0;
6055 }
6056 }
6057
6058 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6059 String name) {
6060 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6061 return true;
6062 }
6063
6064 final int perm = checkComponentPermission(
6065 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006066 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006067 if (perm == PackageManager.PERMISSION_GRANTED) {
6068 return true;
6069 }
6070
Joe Onorato8a9b2202010-02-26 18:56:32 -08006071 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006072 return false;
6073 }
6074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006075 public void setDebugApp(String packageName, boolean waitForDebugger,
6076 boolean persistent) {
6077 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6078 "setDebugApp()");
6079
6080 // Note that this is not really thread safe if there are multiple
6081 // callers into it at the same time, but that's not a situation we
6082 // care about.
6083 if (persistent) {
6084 final ContentResolver resolver = mContext.getContentResolver();
6085 Settings.System.putString(
6086 resolver, Settings.System.DEBUG_APP,
6087 packageName);
6088 Settings.System.putInt(
6089 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6090 waitForDebugger ? 1 : 0);
6091 }
6092
6093 synchronized (this) {
6094 if (!persistent) {
6095 mOrigDebugApp = mDebugApp;
6096 mOrigWaitForDebugger = mWaitForDebugger;
6097 }
6098 mDebugApp = packageName;
6099 mWaitForDebugger = waitForDebugger;
6100 mDebugTransient = !persistent;
6101 if (packageName != null) {
6102 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006103 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006104 Binder.restoreCallingIdentity(origId);
6105 }
6106 }
6107 }
6108
6109 public void setAlwaysFinish(boolean enabled) {
6110 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6111 "setAlwaysFinish()");
6112
6113 Settings.System.putInt(
6114 mContext.getContentResolver(),
6115 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6116
6117 synchronized (this) {
6118 mAlwaysFinishActivities = enabled;
6119 }
6120 }
6121
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006122 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006123 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006124 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006125 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006126 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006127 }
6128 }
6129
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006130 public boolean isUserAMonkey() {
6131 // For now the fact that there is a controller implies
6132 // we have a monkey.
6133 synchronized (this) {
6134 return mController != null;
6135 }
6136 }
6137
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006138 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006139 synchronized (this) {
6140 mWatchers.register(watcher);
6141 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006142 }
6143
6144 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006145 synchronized (this) {
6146 mWatchers.unregister(watcher);
6147 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006148 }
6149
Daniel Sandler69a48172010-06-23 16:29:36 -04006150 public void setImmersive(IBinder token, boolean immersive) {
6151 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006152 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006153 if (index < 0) {
6154 throw new IllegalArgumentException();
6155 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006156 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006157 r.immersive = immersive;
6158 }
6159 }
6160
6161 public boolean isImmersive(IBinder token) {
6162 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006163 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006164 if (index < 0) {
6165 throw new IllegalArgumentException();
6166 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006167 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006168 return r.immersive;
6169 }
6170 }
6171
6172 public boolean isTopActivityImmersive() {
6173 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006174 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006175 return (r != null) ? r.immersive : false;
6176 }
6177 }
6178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006179 public final void enterSafeMode() {
6180 synchronized(this) {
6181 // It only makes sense to do this before the system is ready
6182 // and started launching other packages.
6183 if (!mSystemReady) {
6184 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006185 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006186 } catch (RemoteException e) {
6187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006188 }
6189 }
6190 }
6191
Jeff Brownb09abc12011-01-13 21:08:27 -08006192 public final void showSafeModeOverlay() {
6193 View v = LayoutInflater.from(mContext).inflate(
6194 com.android.internal.R.layout.safe_mode, null);
6195 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6196 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6197 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6198 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6199 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6200 lp.format = v.getBackground().getOpacity();
6201 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6202 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6203 ((WindowManager)mContext.getSystemService(
6204 Context.WINDOW_SERVICE)).addView(v, lp);
6205 }
6206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006207 public void noteWakeupAlarm(IIntentSender sender) {
6208 if (!(sender instanceof PendingIntentRecord)) {
6209 return;
6210 }
6211 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6212 synchronized (stats) {
6213 if (mBatteryStatsService.isOnBattery()) {
6214 mBatteryStatsService.enforceCallingPermission();
6215 PendingIntentRecord rec = (PendingIntentRecord)sender;
6216 int MY_UID = Binder.getCallingUid();
6217 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6218 BatteryStatsImpl.Uid.Pkg pkg =
6219 stats.getPackageStatsLocked(uid, rec.key.packageName);
6220 pkg.incWakeupsLocked();
6221 }
6222 }
6223 }
6224
Dianne Hackborn64825172011-03-02 21:32:58 -08006225 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006226 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006227 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006228 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006229 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006230 // XXX Note: don't acquire main activity lock here, because the window
6231 // manager calls in with its locks held.
6232
6233 boolean killed = false;
6234 synchronized (mPidsSelfLocked) {
6235 int[] types = new int[pids.length];
6236 int worstType = 0;
6237 for (int i=0; i<pids.length; i++) {
6238 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6239 if (proc != null) {
6240 int type = proc.setAdj;
6241 types[i] = type;
6242 if (type > worstType) {
6243 worstType = type;
6244 }
6245 }
6246 }
6247
Dianne Hackborn64825172011-03-02 21:32:58 -08006248 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006249 // then constrain it so we will kill all hidden procs.
6250 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6251 worstType = HIDDEN_APP_MIN_ADJ;
6252 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006253
6254 // If this is not a secure call, don't let it kill processes that
6255 // are important.
6256 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6257 worstType = SECONDARY_SERVER_ADJ;
6258 }
6259
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006260 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006261 for (int i=0; i<pids.length; i++) {
6262 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6263 if (proc == null) {
6264 continue;
6265 }
6266 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006267 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006268 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006269 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6270 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006271 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006272 proc.killedBackground = true;
6273 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006274 }
6275 }
6276 }
6277 return killed;
6278 }
6279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006280 public final void startRunning(String pkg, String cls, String action,
6281 String data) {
6282 synchronized(this) {
6283 if (mStartRunning) {
6284 return;
6285 }
6286 mStartRunning = true;
6287 mTopComponent = pkg != null && cls != null
6288 ? new ComponentName(pkg, cls) : null;
6289 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6290 mTopData = data;
6291 if (!mSystemReady) {
6292 return;
6293 }
6294 }
6295
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006296 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006297 }
6298
6299 private void retrieveSettings() {
6300 final ContentResolver resolver = mContext.getContentResolver();
6301 String debugApp = Settings.System.getString(
6302 resolver, Settings.System.DEBUG_APP);
6303 boolean waitForDebugger = Settings.System.getInt(
6304 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6305 boolean alwaysFinishActivities = Settings.System.getInt(
6306 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6307
6308 Configuration configuration = new Configuration();
6309 Settings.System.getConfiguration(resolver, configuration);
6310
6311 synchronized (this) {
6312 mDebugApp = mOrigDebugApp = debugApp;
6313 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6314 mAlwaysFinishActivities = alwaysFinishActivities;
6315 // This happens before any activities are started, so we can
6316 // change mConfiguration in-place.
6317 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006318 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006319 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006320 }
6321 }
6322
6323 public boolean testIsSystemReady() {
6324 // no need to synchronize(this) just to read & return the value
6325 return mSystemReady;
6326 }
6327
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006328 private static File getCalledPreBootReceiversFile() {
6329 File dataDir = Environment.getDataDirectory();
6330 File systemDir = new File(dataDir, "system");
6331 File fname = new File(systemDir, "called_pre_boots.dat");
6332 return fname;
6333 }
6334
6335 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6336 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6337 File file = getCalledPreBootReceiversFile();
6338 FileInputStream fis = null;
6339 try {
6340 fis = new FileInputStream(file);
6341 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6342 int vers = dis.readInt();
6343 String codename = dis.readUTF();
6344 if (vers == android.os.Build.VERSION.SDK_INT
6345 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6346 int num = dis.readInt();
6347 while (num > 0) {
6348 num--;
6349 String pkg = dis.readUTF();
6350 String cls = dis.readUTF();
6351 lastDoneReceivers.add(new ComponentName(pkg, cls));
6352 }
6353 }
6354 } catch (FileNotFoundException e) {
6355 } catch (IOException e) {
6356 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6357 } finally {
6358 if (fis != null) {
6359 try {
6360 fis.close();
6361 } catch (IOException e) {
6362 }
6363 }
6364 }
6365 return lastDoneReceivers;
6366 }
6367
6368 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6369 File file = getCalledPreBootReceiversFile();
6370 FileOutputStream fos = null;
6371 DataOutputStream dos = null;
6372 try {
6373 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6374 fos = new FileOutputStream(file);
6375 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6376 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6377 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6378 dos.writeInt(list.size());
6379 for (int i=0; i<list.size(); i++) {
6380 dos.writeUTF(list.get(i).getPackageName());
6381 dos.writeUTF(list.get(i).getClassName());
6382 }
6383 } catch (IOException e) {
6384 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6385 file.delete();
6386 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006387 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006388 if (dos != null) {
6389 try {
6390 dos.close();
6391 } catch (IOException e) {
6392 // TODO Auto-generated catch block
6393 e.printStackTrace();
6394 }
6395 }
6396 }
6397 }
6398
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006399 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006400 // In the simulator, startRunning will never have been called, which
6401 // normally sets a few crucial variables. Do it here instead.
6402 if (!Process.supportsProcesses()) {
6403 mStartRunning = true;
6404 mTopAction = Intent.ACTION_MAIN;
6405 }
6406
6407 synchronized(this) {
6408 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006409 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006410 return;
6411 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006412
6413 // Check to see if there are any update receivers to run.
6414 if (!mDidUpdate) {
6415 if (mWaitingUpdate) {
6416 return;
6417 }
6418 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6419 List<ResolveInfo> ris = null;
6420 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006421 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006422 intent, null, 0);
6423 } catch (RemoteException e) {
6424 }
6425 if (ris != null) {
6426 for (int i=ris.size()-1; i>=0; i--) {
6427 if ((ris.get(i).activityInfo.applicationInfo.flags
6428 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6429 ris.remove(i);
6430 }
6431 }
6432 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006433
6434 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6435
6436 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006437 for (int i=0; i<ris.size(); i++) {
6438 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006439 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6440 if (lastDoneReceivers.contains(comp)) {
6441 ris.remove(i);
6442 i--;
6443 }
6444 }
6445
6446 for (int i=0; i<ris.size(); i++) {
6447 ActivityInfo ai = ris.get(i).activityInfo;
6448 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6449 doneReceivers.add(comp);
6450 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006451 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006452 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006453 finisher = new IIntentReceiver.Stub() {
6454 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006455 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006456 boolean sticky) {
6457 // The raw IIntentReceiver interface is called
6458 // with the AM lock held, so redispatch to
6459 // execute our code without the lock.
6460 mHandler.post(new Runnable() {
6461 public void run() {
6462 synchronized (ActivityManagerService.this) {
6463 mDidUpdate = true;
6464 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006465 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006466 systemReady(goingCallback);
6467 }
6468 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006469 }
6470 };
6471 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006472 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006473 broadcastIntentLocked(null, null, intent, null, finisher,
6474 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006475 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006476 mWaitingUpdate = true;
6477 }
6478 }
6479 }
6480 if (mWaitingUpdate) {
6481 return;
6482 }
6483 mDidUpdate = true;
6484 }
6485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 mSystemReady = true;
6487 if (!mStartRunning) {
6488 return;
6489 }
6490 }
6491
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006492 ArrayList<ProcessRecord> procsToKill = null;
6493 synchronized(mPidsSelfLocked) {
6494 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6495 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6496 if (!isAllowedWhileBooting(proc.info)){
6497 if (procsToKill == null) {
6498 procsToKill = new ArrayList<ProcessRecord>();
6499 }
6500 procsToKill.add(proc);
6501 }
6502 }
6503 }
6504
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006505 synchronized(this) {
6506 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006507 for (int i=procsToKill.size()-1; i>=0; i--) {
6508 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006509 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006510 removeProcessLocked(proc, true);
6511 }
6512 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006513
6514 // Now that we have cleaned up any update processes, we
6515 // are ready to start launching real processes and know that
6516 // we won't trample on them any more.
6517 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006518 }
6519
Joe Onorato8a9b2202010-02-26 18:56:32 -08006520 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006521 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006522 SystemClock.uptimeMillis());
6523
6524 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006525 // Make sure we have no pre-ready processes sitting around.
6526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006527 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6528 ResolveInfo ri = mContext.getPackageManager()
6529 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006530 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006531 CharSequence errorMsg = null;
6532 if (ri != null) {
6533 ActivityInfo ai = ri.activityInfo;
6534 ApplicationInfo app = ai.applicationInfo;
6535 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6536 mTopAction = Intent.ACTION_FACTORY_TEST;
6537 mTopData = null;
6538 mTopComponent = new ComponentName(app.packageName,
6539 ai.name);
6540 } else {
6541 errorMsg = mContext.getResources().getText(
6542 com.android.internal.R.string.factorytest_not_system);
6543 }
6544 } else {
6545 errorMsg = mContext.getResources().getText(
6546 com.android.internal.R.string.factorytest_no_action);
6547 }
6548 if (errorMsg != null) {
6549 mTopAction = null;
6550 mTopData = null;
6551 mTopComponent = null;
6552 Message msg = Message.obtain();
6553 msg.what = SHOW_FACTORY_ERROR_MSG;
6554 msg.getData().putCharSequence("msg", errorMsg);
6555 mHandler.sendMessage(msg);
6556 }
6557 }
6558 }
6559
6560 retrieveSettings();
6561
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006562 if (goingCallback != null) goingCallback.run();
6563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 synchronized (this) {
6565 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6566 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006567 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006568 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006569 if (apps != null) {
6570 int N = apps.size();
6571 int i;
6572 for (i=0; i<N; i++) {
6573 ApplicationInfo info
6574 = (ApplicationInfo)apps.get(i);
6575 if (info != null &&
6576 !info.packageName.equals("android")) {
6577 addAppLocked(info);
6578 }
6579 }
6580 }
6581 } catch (RemoteException ex) {
6582 // pm is in same process, this will never happen.
6583 }
6584 }
6585
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006586 // Start up initial activity.
6587 mBooting = true;
6588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006589 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006590 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006591 Message msg = Message.obtain();
6592 msg.what = SHOW_UID_ERROR_MSG;
6593 mHandler.sendMessage(msg);
6594 }
6595 } catch (RemoteException e) {
6596 }
6597
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006598 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006599 }
6600 }
6601
Dan Egnorb7f03672009-12-09 16:22:32 -08006602 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006603 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006604 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006605 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006606 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006607 startAppProblemLocked(app);
6608 app.stopFreezingAllLocked();
6609 return handleAppCrashLocked(app);
6610 }
6611
Dan Egnorb7f03672009-12-09 16:22:32 -08006612 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006613 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006614 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006615 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006616 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6617 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006618 startAppProblemLocked(app);
6619 app.stopFreezingAllLocked();
6620 }
6621
6622 /**
6623 * Generate a process error record, suitable for attachment to a ProcessRecord.
6624 *
6625 * @param app The ProcessRecord in which the error occurred.
6626 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6627 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006628 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006629 * @param shortMsg Short message describing the crash.
6630 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006631 * @param stackTrace Full crash stack trace, may be null.
6632 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006633 * @return Returns a fully-formed AppErrorStateInfo record.
6634 */
6635 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006636 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006637 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006639 report.condition = condition;
6640 report.processName = app.processName;
6641 report.pid = app.pid;
6642 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006643 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006644 report.shortMsg = shortMsg;
6645 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006646 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006647
6648 return report;
6649 }
6650
Dan Egnor42471dd2010-01-07 17:25:22 -08006651 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006652 synchronized (this) {
6653 app.crashing = false;
6654 app.crashingReport = null;
6655 app.notResponding = false;
6656 app.notRespondingReport = null;
6657 if (app.anrDialog == fromDialog) {
6658 app.anrDialog = null;
6659 }
6660 if (app.waitDialog == fromDialog) {
6661 app.waitDialog = null;
6662 }
6663 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006664 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006665 Slog.i(ActivityManagerService.TAG, "Killing "
6666 + app.processName + " (pid=" + app.pid + "): user's request");
6667 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6668 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006669 Process.killProcess(app.pid);
6670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006671 }
6672 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006673
Dan Egnorb7f03672009-12-09 16:22:32 -08006674 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006675 long now = SystemClock.uptimeMillis();
6676
6677 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6678 app.info.uid);
6679 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6680 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006681 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006682 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006683 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006684 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006685 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6686 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006687 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006688 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006689 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006690 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006691 }
6692 }
6693 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006694 // Don't let services in this process be restarted and potentially
6695 // annoy the user repeatedly. Unless it is persistent, since those
6696 // processes run critical code.
6697 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006698 // We don't want to start this process again until the user
6699 // explicitly does so... but for persistent process, we really
6700 // need to keep it running. If a persistent process is actually
6701 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006702 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006703 app.info.processName);
6704 mBadProcesses.put(app.info.processName, app.info.uid, now);
6705 app.bad = true;
6706 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6707 app.removed = true;
6708 removeProcessLocked(app, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006709 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006710 return false;
6711 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006712 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006713 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006714 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006715 if (r.app == app) {
6716 // If the top running activity is from this crashing
6717 // process, then terminate it to avoid getting in a loop.
6718 Slog.w(TAG, " Force finishing activity "
6719 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006720 int index = mMainStack.indexOfTokenLocked(r);
6721 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006722 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006723 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006724 // stopped, to avoid a situation where one will get
6725 // re-start our crashing activity once it gets resumed again.
6726 index--;
6727 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006728 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006729 if (r.state == ActivityState.RESUMED
6730 || r.state == ActivityState.PAUSING
6731 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006732 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006733 Slog.w(TAG, " Force finishing activity "
6734 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006735 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006736 Activity.RESULT_CANCELED, null, "crashed");
6737 }
6738 }
6739 }
6740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006741 }
6742
6743 // Bump up the crash count of any services currently running in the proc.
6744 if (app.services.size() != 0) {
6745 // Any services running in the application need to be placed
6746 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006747 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006748 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006749 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006750 sr.crashCount++;
6751 }
6752 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006753
6754 // If the crashing process is what we consider to be the "home process" and it has been
6755 // replaced by a third-party app, clear the package preferred activities from packages
6756 // with a home activity running in the process to prevent a repeatedly crashing app
6757 // from blocking the user to manually clear the list.
6758 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6759 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6760 Iterator it = mHomeProcess.activities.iterator();
6761 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006762 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006763 if (r.isHomeActivity) {
6764 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6765 try {
6766 ActivityThread.getPackageManager()
6767 .clearPackagePreferredActivities(r.packageName);
6768 } catch (RemoteException c) {
6769 // pm is in same process, this will never happen.
6770 }
6771 }
6772 }
6773 }
6774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006775 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6776 return true;
6777 }
6778
6779 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006780 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6781 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006782 skipCurrentReceiverLocked(app);
6783 }
6784
6785 void skipCurrentReceiverLocked(ProcessRecord app) {
6786 boolean reschedule = false;
6787 BroadcastRecord r = app.curReceiver;
6788 if (r != null) {
6789 // The current broadcast is waiting for this app's receiver
6790 // to be finished. Looks like that's not going to happen, so
6791 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006792 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006793 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6794 r.resultExtras, r.resultAbort, true);
6795 reschedule = true;
6796 }
6797 r = mPendingBroadcast;
6798 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006799 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006800 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006801 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006802 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6803 r.resultExtras, r.resultAbort, true);
6804 reschedule = true;
6805 }
6806 if (reschedule) {
6807 scheduleBroadcastsLocked();
6808 }
6809 }
6810
Dan Egnor60d87622009-12-16 16:32:58 -08006811 /**
6812 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6813 * The application process will exit immediately after this call returns.
6814 * @param app object of the crashing app, null for the system server
6815 * @param crashInfo describing the exception
6816 */
6817 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006818 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08006819
6820 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6821 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006822 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006823 crashInfo.exceptionClassName,
6824 crashInfo.exceptionMessage,
6825 crashInfo.throwFileName,
6826 crashInfo.throwLineNumber);
6827
Dan Egnor42471dd2010-01-07 17:25:22 -08006828 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006829
6830 crashApplication(r, crashInfo);
6831 }
6832
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006833 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006834 IBinder app,
6835 int violationMask,
6836 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006837 ProcessRecord r = findAppProcess(app, "StrictMode");
6838 if (r == null) {
6839 return;
6840 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006841
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006842 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006843 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006844 boolean logIt = true;
6845 synchronized (mAlreadyLoggedViolatedStacks) {
6846 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6847 logIt = false;
6848 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006849 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006850 // the relative pain numbers, without logging all
6851 // the stack traces repeatedly. We'd want to do
6852 // likewise in the client code, which also does
6853 // dup suppression, before the Binder call.
6854 } else {
6855 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6856 mAlreadyLoggedViolatedStacks.clear();
6857 }
6858 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6859 }
6860 }
6861 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006862 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006863 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006864 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006865
6866 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6867 AppErrorResult result = new AppErrorResult();
6868 synchronized (this) {
6869 final long origId = Binder.clearCallingIdentity();
6870
6871 Message msg = Message.obtain();
6872 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6873 HashMap<String, Object> data = new HashMap<String, Object>();
6874 data.put("result", result);
6875 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006876 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006877 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006878 msg.obj = data;
6879 mHandler.sendMessage(msg);
6880
6881 Binder.restoreCallingIdentity(origId);
6882 }
6883 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006884 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006885 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006886 }
6887
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006888 // Depending on the policy in effect, there could be a bunch of
6889 // these in quick succession so we try to batch these together to
6890 // minimize disk writes, number of dropbox entries, and maximize
6891 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006892 private void logStrictModeViolationToDropBox(
6893 ProcessRecord process,
6894 StrictMode.ViolationInfo info) {
6895 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006896 return;
6897 }
6898 final boolean isSystemApp = process == null ||
6899 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6900 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6901 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6902 final DropBoxManager dbox = (DropBoxManager)
6903 mContext.getSystemService(Context.DROPBOX_SERVICE);
6904
6905 // Exit early if the dropbox isn't configured to accept this report type.
6906 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6907
6908 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006909 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006910 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6911 synchronized (sb) {
6912 bufferWasEmpty = sb.length() == 0;
6913 appendDropBoxProcessHeaders(process, sb);
6914 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6915 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006916 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6917 if (info.violationNumThisLoop != 0) {
6918 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6919 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006920 if (info.numAnimationsRunning != 0) {
6921 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6922 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006923 if (info.broadcastIntentAction != null) {
6924 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6925 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006926 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006927 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006928 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08006929 if (info.numInstances != -1) {
6930 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
6931 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006932 if (info.tags != null) {
6933 for (String tag : info.tags) {
6934 sb.append("Span-Tag: ").append(tag).append("\n");
6935 }
6936 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006937 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006938 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6939 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006940 }
6941 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006942
6943 // Only buffer up to ~64k. Various logging bits truncate
6944 // things at 128k.
6945 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006946 }
6947
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006948 // Flush immediately if the buffer's grown too large, or this
6949 // is a non-system app. Non-system apps are isolated with a
6950 // different tag & policy and not batched.
6951 //
6952 // Batching is useful during internal testing with
6953 // StrictMode settings turned up high. Without batching,
6954 // thousands of separate files could be created on boot.
6955 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006956 new Thread("Error dump: " + dropboxTag) {
6957 @Override
6958 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006959 String report;
6960 synchronized (sb) {
6961 report = sb.toString();
6962 sb.delete(0, sb.length());
6963 sb.trimToSize();
6964 }
6965 if (report.length() != 0) {
6966 dbox.addText(dropboxTag, report);
6967 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006968 }
6969 }.start();
6970 return;
6971 }
6972
6973 // System app batching:
6974 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006975 // An existing dropbox-writing thread is outstanding, so
6976 // we don't need to start it up. The existing thread will
6977 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006978 return;
6979 }
6980
6981 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6982 // (After this point, we shouldn't access AMS internal data structures.)
6983 new Thread("Error dump: " + dropboxTag) {
6984 @Override
6985 public void run() {
6986 // 5 second sleep to let stacks arrive and be batched together
6987 try {
6988 Thread.sleep(5000); // 5 seconds
6989 } catch (InterruptedException e) {}
6990
6991 String errorReport;
6992 synchronized (mStrictModeBuffer) {
6993 errorReport = mStrictModeBuffer.toString();
6994 if (errorReport.length() == 0) {
6995 return;
6996 }
6997 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6998 mStrictModeBuffer.trimToSize();
6999 }
7000 dbox.addText(dropboxTag, errorReport);
7001 }
7002 }.start();
7003 }
7004
Dan Egnor60d87622009-12-16 16:32:58 -08007005 /**
7006 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7007 * @param app object of the crashing app, null for the system server
7008 * @param tag reported by the caller
7009 * @param crashInfo describing the context of the error
7010 * @return true if the process should exit immediately (WTF is fatal)
7011 */
7012 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007013 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007014 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007015
7016 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7017 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007018 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007019 tag, crashInfo.exceptionMessage);
7020
Dan Egnor42471dd2010-01-07 17:25:22 -08007021 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007022
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007023 if (r != null && r.pid != Process.myPid() &&
7024 Settings.Secure.getInt(mContext.getContentResolver(),
7025 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007026 crashApplication(r, crashInfo);
7027 return true;
7028 } else {
7029 return false;
7030 }
7031 }
7032
7033 /**
7034 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7035 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7036 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007037 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007038 if (app == null) {
7039 return null;
7040 }
7041
7042 synchronized (this) {
7043 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7044 final int NA = apps.size();
7045 for (int ia=0; ia<NA; ia++) {
7046 ProcessRecord p = apps.valueAt(ia);
7047 if (p.thread != null && p.thread.asBinder() == app) {
7048 return p;
7049 }
7050 }
7051 }
7052
Dianne Hackborncb44d962011-03-10 17:02:27 -08007053 Slog.w(TAG, "Can't find mystery application for " + reason
7054 + " from pid=" + Binder.getCallingPid()
7055 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007056 return null;
7057 }
7058 }
7059
7060 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007061 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7062 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007063 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007064 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
7065 // Note: ProcessRecord 'process' is guarded by the service
7066 // instance. (notably process.pkgList, which could otherwise change
7067 // concurrently during execution of this method)
7068 synchronized (this) {
7069 if (process == null || process.pid == MY_PID) {
7070 sb.append("Process: system_server\n");
7071 } else {
7072 sb.append("Process: ").append(process.processName).append("\n");
7073 }
7074 if (process == null) {
7075 return;
7076 }
Dan Egnora455d192010-03-12 08:52:28 -08007077 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007078 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007079 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7080 for (String pkg : process.pkgList) {
7081 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007082 try {
Dan Egnora455d192010-03-12 08:52:28 -08007083 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7084 if (pi != null) {
7085 sb.append(" v").append(pi.versionCode);
7086 if (pi.versionName != null) {
7087 sb.append(" (").append(pi.versionName).append(")");
7088 }
7089 }
7090 } catch (RemoteException e) {
7091 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007092 }
Dan Egnora455d192010-03-12 08:52:28 -08007093 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007094 }
Dan Egnora455d192010-03-12 08:52:28 -08007095 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007096 }
7097
7098 private static String processClass(ProcessRecord process) {
7099 if (process == null || process.pid == MY_PID) {
7100 return "system_server";
7101 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7102 return "system_app";
7103 } else {
7104 return "data_app";
7105 }
7106 }
7107
7108 /**
7109 * Write a description of an error (crash, WTF, ANR) to the drop box.
7110 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7111 * @param process which caused the error, null means the system server
7112 * @param activity which triggered the error, null if unknown
7113 * @param parent activity related to the error, null if unknown
7114 * @param subject line related to the error, null if absent
7115 * @param report in long form describing the error, null if absent
7116 * @param logFile to include in the report, null if none
7117 * @param crashInfo giving an application stack trace, null if absent
7118 */
7119 public void addErrorToDropBox(String eventType,
7120 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7121 final String report, final File logFile,
7122 final ApplicationErrorReport.CrashInfo crashInfo) {
7123 // NOTE -- this must never acquire the ActivityManagerService lock,
7124 // otherwise the watchdog may be prevented from resetting the system.
7125
7126 final String dropboxTag = processClass(process) + "_" + eventType;
7127 final DropBoxManager dbox = (DropBoxManager)
7128 mContext.getSystemService(Context.DROPBOX_SERVICE);
7129
7130 // Exit early if the dropbox isn't configured to accept this report type.
7131 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7132
7133 final StringBuilder sb = new StringBuilder(1024);
7134 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007135 if (activity != null) {
7136 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7137 }
7138 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7139 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7140 }
7141 if (parent != null && parent != activity) {
7142 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7143 }
7144 if (subject != null) {
7145 sb.append("Subject: ").append(subject).append("\n");
7146 }
7147 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007148 if (Debug.isDebuggerConnected()) {
7149 sb.append("Debugger: Connected\n");
7150 }
Dan Egnora455d192010-03-12 08:52:28 -08007151 sb.append("\n");
7152
7153 // Do the rest in a worker thread to avoid blocking the caller on I/O
7154 // (After this point, we shouldn't access AMS internal data structures.)
7155 Thread worker = new Thread("Error dump: " + dropboxTag) {
7156 @Override
7157 public void run() {
7158 if (report != null) {
7159 sb.append(report);
7160 }
7161 if (logFile != null) {
7162 try {
7163 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7164 } catch (IOException e) {
7165 Slog.e(TAG, "Error reading " + logFile, e);
7166 }
7167 }
7168 if (crashInfo != null && crashInfo.stackTrace != null) {
7169 sb.append(crashInfo.stackTrace);
7170 }
7171
7172 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7173 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7174 if (lines > 0) {
7175 sb.append("\n");
7176
7177 // Merge several logcat streams, and take the last N lines
7178 InputStreamReader input = null;
7179 try {
7180 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7181 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7182 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7183
7184 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7185 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7186 input = new InputStreamReader(logcat.getInputStream());
7187
7188 int num;
7189 char[] buf = new char[8192];
7190 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7191 } catch (IOException e) {
7192 Slog.e(TAG, "Error running logcat", e);
7193 } finally {
7194 if (input != null) try { input.close(); } catch (IOException e) {}
7195 }
7196 }
7197
7198 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007199 }
Dan Egnora455d192010-03-12 08:52:28 -08007200 };
7201
7202 if (process == null || process.pid == MY_PID) {
7203 worker.run(); // We may be about to die -- need to run this synchronously
7204 } else {
7205 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007206 }
7207 }
7208
7209 /**
7210 * Bring up the "unexpected error" dialog box for a crashing app.
7211 * Deal with edge cases (intercepts from instrumented applications,
7212 * ActivityController, error intent receivers, that sort of thing).
7213 * @param r the application crashing
7214 * @param crashInfo describing the failure
7215 */
7216 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007217 long timeMillis = System.currentTimeMillis();
7218 String shortMsg = crashInfo.exceptionClassName;
7219 String longMsg = crashInfo.exceptionMessage;
7220 String stackTrace = crashInfo.stackTrace;
7221 if (shortMsg != null && longMsg != null) {
7222 longMsg = shortMsg + ": " + longMsg;
7223 } else if (shortMsg != null) {
7224 longMsg = shortMsg;
7225 }
7226
Dan Egnor60d87622009-12-16 16:32:58 -08007227 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007229 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007230 try {
7231 String name = r != null ? r.processName : null;
7232 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007233 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007234 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007235 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007236 + " at watcher's request");
7237 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007238 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007239 }
7240 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007241 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007242 }
7243 }
7244
7245 final long origId = Binder.clearCallingIdentity();
7246
7247 // If this process is running instrumentation, finish it.
7248 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007249 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007251 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7252 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007253 Bundle info = new Bundle();
7254 info.putString("shortMsg", shortMsg);
7255 info.putString("longMsg", longMsg);
7256 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7257 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007258 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007259 }
7260
Dan Egnor60d87622009-12-16 16:32:58 -08007261 // If we can't identify the process or it's already exceeded its crash quota,
7262 // quit right away without showing a crash dialog.
7263 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007264 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007265 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007266 }
7267
7268 Message msg = Message.obtain();
7269 msg.what = SHOW_ERROR_MSG;
7270 HashMap data = new HashMap();
7271 data.put("result", result);
7272 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273 msg.obj = data;
7274 mHandler.sendMessage(msg);
7275
7276 Binder.restoreCallingIdentity(origId);
7277 }
7278
7279 int res = result.get();
7280
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007281 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007282 synchronized (this) {
7283 if (r != null) {
7284 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7285 SystemClock.uptimeMillis());
7286 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007287 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007288 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007289 }
7290 }
7291
7292 if (appErrorIntent != null) {
7293 try {
7294 mContext.startActivity(appErrorIntent);
7295 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007296 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007297 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007299 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007300
7301 Intent createAppErrorIntentLocked(ProcessRecord r,
7302 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7303 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007304 if (report == null) {
7305 return null;
7306 }
7307 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7308 result.setComponent(r.errorReportReceiver);
7309 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7310 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7311 return result;
7312 }
7313
Dan Egnorb7f03672009-12-09 16:22:32 -08007314 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7315 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007316 if (r.errorReportReceiver == null) {
7317 return null;
7318 }
7319
7320 if (!r.crashing && !r.notResponding) {
7321 return null;
7322 }
7323
Dan Egnorb7f03672009-12-09 16:22:32 -08007324 ApplicationErrorReport report = new ApplicationErrorReport();
7325 report.packageName = r.info.packageName;
7326 report.installerPackageName = r.errorReportReceiver.getPackageName();
7327 report.processName = r.processName;
7328 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007329 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007330
Dan Egnorb7f03672009-12-09 16:22:32 -08007331 if (r.crashing) {
7332 report.type = ApplicationErrorReport.TYPE_CRASH;
7333 report.crashInfo = crashInfo;
7334 } else if (r.notResponding) {
7335 report.type = ApplicationErrorReport.TYPE_ANR;
7336 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007337
Dan Egnorb7f03672009-12-09 16:22:32 -08007338 report.anrInfo.activity = r.notRespondingReport.tag;
7339 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7340 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007341 }
7342
Dan Egnorb7f03672009-12-09 16:22:32 -08007343 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007344 }
7345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007346 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7347 // assume our apps are happy - lazy create the list
7348 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7349
7350 synchronized (this) {
7351
7352 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007353 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7354 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007355 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7356 // This one's in trouble, so we'll generate a report for it
7357 // crashes are higher priority (in case there's a crash *and* an anr)
7358 ActivityManager.ProcessErrorStateInfo report = null;
7359 if (app.crashing) {
7360 report = app.crashingReport;
7361 } else if (app.notResponding) {
7362 report = app.notRespondingReport;
7363 }
7364
7365 if (report != null) {
7366 if (errList == null) {
7367 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7368 }
7369 errList.add(report);
7370 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007371 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007372 " crashing = " + app.crashing +
7373 " notResponding = " + app.notResponding);
7374 }
7375 }
7376 }
7377 }
7378
7379 return errList;
7380 }
7381
7382 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7383 // Lazy instantiation of list
7384 List<ActivityManager.RunningAppProcessInfo> runList = null;
7385 synchronized (this) {
7386 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007387 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7388 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007389 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7390 // Generate process state info for running application
7391 ActivityManager.RunningAppProcessInfo currApp =
7392 new ActivityManager.RunningAppProcessInfo(app.processName,
7393 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007394 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007395 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007396 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007397 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007398 if (app.persistent) {
7399 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007402 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007403 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7404 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7405 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007406 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7407 } else if (adj >= HOME_APP_ADJ) {
7408 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7409 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007410 } else if (adj >= SECONDARY_SERVER_ADJ) {
7411 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007412 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007413 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007414 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7415 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007416 } else if (adj >= VISIBLE_APP_ADJ) {
7417 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7418 } else {
7419 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7420 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007421 currApp.importanceReasonCode = app.adjTypeCode;
7422 if (app.adjSource instanceof ProcessRecord) {
7423 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007424 } else if (app.adjSource instanceof ActivityRecord) {
7425 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007426 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7427 }
7428 if (app.adjTarget instanceof ComponentName) {
7429 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7430 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007431 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007432 // + " lru=" + currApp.lru);
7433 if (runList == null) {
7434 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7435 }
7436 runList.add(currApp);
7437 }
7438 }
7439 }
7440 return runList;
7441 }
7442
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007443 public List<ApplicationInfo> getRunningExternalApplications() {
7444 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7445 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7446 if (runningApps != null && runningApps.size() > 0) {
7447 Set<String> extList = new HashSet<String>();
7448 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7449 if (app.pkgList != null) {
7450 for (String pkg : app.pkgList) {
7451 extList.add(pkg);
7452 }
7453 }
7454 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007455 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007456 for (String pkg : extList) {
7457 try {
7458 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7459 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7460 retList.add(info);
7461 }
7462 } catch (RemoteException e) {
7463 }
7464 }
7465 }
7466 return retList;
7467 }
7468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007469 @Override
7470 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007471 if (checkCallingPermission(android.Manifest.permission.DUMP)
7472 != PackageManager.PERMISSION_GRANTED) {
7473 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7474 + Binder.getCallingPid()
7475 + ", uid=" + Binder.getCallingUid()
7476 + " without permission "
7477 + android.Manifest.permission.DUMP);
7478 return;
7479 }
7480
7481 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007482 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007483
7484 int opti = 0;
7485 while (opti < args.length) {
7486 String opt = args[opti];
7487 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7488 break;
7489 }
7490 opti++;
7491 if ("-a".equals(opt)) {
7492 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007493 } else if ("-c".equals(opt)) {
7494 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007495 } else if ("-h".equals(opt)) {
7496 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007497 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007498 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007499 pw.println(" a[ctivities]: activity stack state");
7500 pw.println(" b[roadcasts]: broadcast state");
7501 pw.println(" i[ntents]: pending intent state");
7502 pw.println(" p[rocesses]: process state");
7503 pw.println(" o[om]: out of memory management");
7504 pw.println(" prov[iders]: content provider state");
7505 pw.println(" s[ervices]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007506 pw.println(" service [COMP_SPEC]: service client-side state");
7507 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
7508 pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),");
7509 pw.println(" a partial substring in a component name, an");
7510 pw.println(" ActivityRecord hex object identifier, or");
7511 pw.println(" \"all\" for all objects");
7512 pw.println(" -a: include all available server state.");
7513 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007514 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007515 } else {
7516 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007517 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007518 }
7519
7520 // Is the caller requesting to dump a particular piece of data?
7521 if (opti < args.length) {
7522 String cmd = args[opti];
7523 opti++;
7524 if ("activities".equals(cmd) || "a".equals(cmd)) {
7525 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007526 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007527 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007528 return;
7529 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7530 synchronized (this) {
7531 dumpBroadcastsLocked(fd, pw, args, opti, true);
7532 }
7533 return;
7534 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7535 synchronized (this) {
7536 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7537 }
7538 return;
7539 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7540 synchronized (this) {
7541 dumpProcessesLocked(fd, pw, args, opti, true);
7542 }
7543 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007544 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7545 synchronized (this) {
7546 dumpOomLocked(fd, pw, args, opti, true);
7547 }
7548 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007549 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7550 synchronized (this) {
7551 dumpProvidersLocked(fd, pw, args, opti, true);
7552 }
7553 return;
7554 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007555 String[] newArgs;
7556 String name;
7557 if (opti >= args.length) {
7558 name = null;
7559 newArgs = EMPTY_STRING_ARRAY;
7560 } else {
7561 name = args[opti];
7562 opti++;
7563 newArgs = new String[args.length - opti];
7564 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7565 }
7566 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7567 pw.println("No services match: " + name);
7568 pw.println("Use -h for help.");
7569 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007570 return;
7571 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7572 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007573 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007574 }
7575 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007576 } else {
7577 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007578 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7579 pw.println("Bad activity command, or no activities match: " + cmd);
7580 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007581 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007582 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007584 }
7585
7586 // No piece of data specified, dump everything.
7587 synchronized (this) {
7588 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007589 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007590 if (needSep) {
7591 pw.println(" ");
7592 }
7593 if (dumpAll) {
7594 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007595 }
7596 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7597 if (needSep) {
7598 pw.println(" ");
7599 }
7600 if (dumpAll) {
7601 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007602 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007603 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007604 if (needSep) {
7605 pw.println(" ");
7606 }
7607 if (dumpAll) {
7608 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007609 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007610 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007611 if (needSep) {
7612 pw.println(" ");
7613 }
7614 if (dumpAll) {
7615 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007616 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007617 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007618 if (needSep) {
7619 pw.println(" ");
7620 }
7621 if (dumpAll) {
7622 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007623 }
7624 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7625 }
7626 }
7627
7628 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007629 int opti, boolean dumpAll, boolean dumpClient) {
7630 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7631 pw.println(" Main stack:");
7632 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007633 pw.println(" ");
7634 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007635 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007636 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007637 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007638 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007639 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7640 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007641 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007642 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007643 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007644 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007645 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7646 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007647 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007648 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7649 pw.println(" ");
7650 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007651 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7652 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007653 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007654 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007655 pw.println(" ");
7656 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007657 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7658 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007660
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007661 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007662 if (mMainStack.mPausingActivity != null) {
7663 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7664 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007665 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007666 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007667 if (dumpAll) {
7668 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7669 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
7670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007671
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007672 if (mRecentTasks.size() > 0) {
7673 pw.println();
7674 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007675
7676 final int N = mRecentTasks.size();
7677 for (int i=0; i<N; i++) {
7678 TaskRecord tr = mRecentTasks.get(i);
7679 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7680 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007681 if (dumpAll) {
7682 mRecentTasks.get(i).dump(pw, " ");
7683 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007684 }
7685 }
7686
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007687 if (dumpAll) {
7688 pw.println(" ");
7689 pw.println(" mCurTask: " + mCurTask);
7690 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007691
7692 return true;
7693 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007694
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007695 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7696 int opti, boolean dumpAll) {
7697 boolean needSep = false;
7698 int numPers = 0;
7699
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007700 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7701
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007702 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007703 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7704 final int NA = procs.size();
7705 for (int ia=0; ia<NA; ia++) {
7706 if (!needSep) {
7707 pw.println(" All known processes:");
7708 needSep = true;
7709 }
7710 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007711 pw.print(r.persistent ? " *PERS*" : " *APP*");
7712 pw.print(" UID "); pw.print(procs.keyAt(ia));
7713 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007714 r.dump(pw, " ");
7715 if (r.persistent) {
7716 numPers++;
7717 }
7718 }
7719 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007720 }
7721
7722 if (mLruProcesses.size() > 0) {
7723 if (needSep) pw.println(" ");
7724 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007725 pw.println(" Process LRU list (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007726 dumpProcessOomList(pw, this, mLruProcesses, " ",
7727 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007728 needSep = true;
7729 }
7730
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007731 if (dumpAll) {
7732 synchronized (mPidsSelfLocked) {
7733 if (mPidsSelfLocked.size() > 0) {
7734 if (needSep) pw.println(" ");
7735 needSep = true;
7736 pw.println(" PID mappings:");
7737 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7738 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7739 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
7740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007741 }
7742 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007743 }
7744
7745 if (mForegroundProcesses.size() > 0) {
7746 if (needSep) pw.println(" ");
7747 needSep = true;
7748 pw.println(" Foreground Processes:");
7749 for (int i=0; i<mForegroundProcesses.size(); i++) {
7750 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7751 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007752 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007753 }
7754
7755 if (mPersistentStartingProcesses.size() > 0) {
7756 if (needSep) pw.println(" ");
7757 needSep = true;
7758 pw.println(" Persisent processes that are starting:");
7759 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007760 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007762
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007763 if (mStartingProcesses.size() > 0) {
7764 if (needSep) pw.println(" ");
7765 needSep = true;
7766 pw.println(" Processes that are starting:");
7767 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007768 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007770
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007771 if (mRemovedProcesses.size() > 0) {
7772 if (needSep) pw.println(" ");
7773 needSep = true;
7774 pw.println(" Processes that are being removed:");
7775 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007776 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007777 }
7778
7779 if (mProcessesOnHold.size() > 0) {
7780 if (needSep) pw.println(" ");
7781 needSep = true;
7782 pw.println(" Processes that are on old until the system is ready:");
7783 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007784 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007785 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007786
Dianne Hackborn287952c2010-09-22 22:34:31 -07007787 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007788
7789 if (mProcessCrashTimes.getMap().size() > 0) {
7790 if (needSep) pw.println(" ");
7791 needSep = true;
7792 pw.println(" Time since processes crashed:");
7793 long now = SystemClock.uptimeMillis();
7794 for (Map.Entry<String, SparseArray<Long>> procs
7795 : mProcessCrashTimes.getMap().entrySet()) {
7796 SparseArray<Long> uids = procs.getValue();
7797 final int N = uids.size();
7798 for (int i=0; i<N; i++) {
7799 pw.print(" Process "); pw.print(procs.getKey());
7800 pw.print(" uid "); pw.print(uids.keyAt(i));
7801 pw.print(": last crashed ");
7802 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007803 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007804 }
7805 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007807
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007808 if (mBadProcesses.getMap().size() > 0) {
7809 if (needSep) pw.println(" ");
7810 needSep = true;
7811 pw.println(" Bad processes:");
7812 for (Map.Entry<String, SparseArray<Long>> procs
7813 : mBadProcesses.getMap().entrySet()) {
7814 SparseArray<Long> uids = procs.getValue();
7815 final int N = uids.size();
7816 for (int i=0; i<N; i++) {
7817 pw.print(" Bad process "); pw.print(procs.getKey());
7818 pw.print(" uid "); pw.print(uids.keyAt(i));
7819 pw.print(": crashed at time ");
7820 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007821 }
7822 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007824
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007825 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007826 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007827 if (mHeavyWeightProcess != null) {
7828 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7829 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007830 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007831 if (dumpAll) {
7832 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
7833 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007834 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7835 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7836 || mOrigWaitForDebugger) {
7837 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7838 + " mDebugTransient=" + mDebugTransient
7839 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7840 }
7841 if (mAlwaysFinishActivities || mController != null) {
7842 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7843 + " mController=" + mController);
7844 }
7845 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007846 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007847 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007848 + " mProcessesReady=" + mProcessesReady
7849 + " mSystemReady=" + mSystemReady);
7850 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007851 + " mBooted=" + mBooted
7852 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007853 pw.print(" mLastPowerCheckRealtime=");
7854 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7855 pw.println("");
7856 pw.print(" mLastPowerCheckUptime=");
7857 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7858 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007859 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7860 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007861 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007863
7864 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007865 }
7866
Dianne Hackborn287952c2010-09-22 22:34:31 -07007867 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7868 int opti, boolean needSep, boolean dumpAll) {
7869 if (mProcessesToGc.size() > 0) {
7870 if (needSep) pw.println(" ");
7871 needSep = true;
7872 pw.println(" Processes that are waiting to GC:");
7873 long now = SystemClock.uptimeMillis();
7874 for (int i=0; i<mProcessesToGc.size(); i++) {
7875 ProcessRecord proc = mProcessesToGc.get(i);
7876 pw.print(" Process "); pw.println(proc);
7877 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7878 pw.print(", last gced=");
7879 pw.print(now-proc.lastRequestedGc);
7880 pw.print(" ms ago, last lowMem=");
7881 pw.print(now-proc.lastLowMemory);
7882 pw.println(" ms ago");
7883
7884 }
7885 }
7886 return needSep;
7887 }
7888
7889 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7890 int opti, boolean dumpAll) {
7891 boolean needSep = false;
7892
7893 if (mLruProcesses.size() > 0) {
7894 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7895
7896 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7897 @Override
7898 public int compare(ProcessRecord object1, ProcessRecord object2) {
7899 if (object1.setAdj != object2.setAdj) {
7900 return object1.setAdj > object2.setAdj ? -1 : 1;
7901 }
7902 if (object1.setSchedGroup != object2.setSchedGroup) {
7903 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7904 }
7905 if (object1.keeping != object2.keeping) {
7906 return object1.keeping ? -1 : 1;
7907 }
7908 if (object1.pid != object2.pid) {
7909 return object1.pid > object2.pid ? -1 : 1;
7910 }
7911 return 0;
7912 }
7913 };
7914
7915 Collections.sort(procs, comparator);
7916
7917 if (needSep) pw.println(" ");
7918 needSep = true;
7919 pw.println(" Process OOM control:");
7920 dumpProcessOomList(pw, this, procs, " ",
7921 "Proc", "PERS", true);
7922 needSep = true;
7923 }
7924
7925 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7926
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007927 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07007928 pw.println(" mHomeProcess: " + mHomeProcess);
7929 if (mHeavyWeightProcess != null) {
7930 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7931 }
7932
7933 return true;
7934 }
7935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936 /**
7937 * There are three ways to call this:
7938 * - no service specified: dump all the services
7939 * - a flattened component name that matched an existing service was specified as the
7940 * first arg: dump that one service
7941 * - the first arg isn't the flattened component name of an existing service:
7942 * dump all services whose component contains the first arg as a substring
7943 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007944 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7945 int opti, boolean dumpAll) {
7946 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007947
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007948 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007949 synchronized (this) {
7950 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007951 services.add(r1);
7952 }
7953 }
7954 } else {
7955 ComponentName componentName = name != null
7956 ? ComponentName.unflattenFromString(name) : null;
7957 int objectId = 0;
7958 if (componentName == null) {
7959 // Not a '/' separated full component name; maybe an object ID?
7960 try {
7961 objectId = Integer.parseInt(name, 16);
7962 name = null;
7963 componentName = null;
7964 } catch (RuntimeException e) {
7965 }
7966 }
7967
7968 synchronized (this) {
7969 for (ServiceRecord r1 : mServices.values()) {
7970 if (componentName != null) {
7971 if (r1.name.equals(componentName)) {
7972 services.add(r1);
7973 }
7974 } else if (name != null) {
7975 if (r1.name.flattenToString().contains(name)) {
7976 services.add(r1);
7977 }
7978 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007979 services.add(r1);
7980 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007981 }
7982 }
7983 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007984
7985 if (services.size() <= 0) {
7986 return false;
7987 }
7988
7989 boolean needSep = false;
7990 for (int i=0; i<services.size(); i++) {
7991 if (needSep) {
7992 pw.println();
7993 }
7994 needSep = true;
7995 dumpService("", fd, pw, services.get(i), args, dumpAll);
7996 }
7997 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007998 }
7999
8000 /**
8001 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8002 * there is a thread associated with the service.
8003 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008004 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8005 final ServiceRecord r, String[] args, boolean dumpAll) {
8006 String innerPrefix = prefix + " ";
8007 synchronized (this) {
8008 pw.print(prefix); pw.print("SERVICE ");
8009 pw.print(r.shortName); pw.print(" ");
8010 pw.print(Integer.toHexString(System.identityHashCode(r)));
8011 pw.print(" pid=");
8012 if (r.app != null) pw.println(r.app.pid);
8013 else pw.println("(not running)");
8014 if (dumpAll) {
8015 r.dump(pw, innerPrefix);
8016 }
8017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008018 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008019 pw.print(prefix); pw.println(" Client:");
8020 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008022 TransferPipe tp = new TransferPipe();
8023 try {
8024 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8025 tp.setBufferPrefix(prefix + " ");
8026 tp.go(fd);
8027 } finally {
8028 tp.kill();
8029 }
8030 } catch (IOException e) {
8031 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008033 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008034 }
8035 }
8036 }
8037
Dianne Hackborn625ac272010-09-17 18:29:22 -07008038 /**
8039 * There are three things that cmd can be:
8040 * - a flattened component name that matched an existing activity
8041 * - the cmd arg isn't the flattened component name of an existing activity:
8042 * dump all activity whose component contains the cmd as a substring
8043 * - A hex number of the ActivityRecord object instance.
8044 */
8045 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8046 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008047 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008048
8049 if ("all".equals(name)) {
8050 synchronized (this) {
8051 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008052 activities.add(r1);
8053 }
8054 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008055 } else {
8056 ComponentName componentName = ComponentName.unflattenFromString(name);
8057 int objectId = 0;
8058 if (componentName == null) {
8059 // Not a '/' separated full component name; maybe an object ID?
8060 try {
8061 objectId = Integer.parseInt(name, 16);
8062 name = null;
8063 componentName = null;
8064 } catch (RuntimeException e) {
8065 }
8066 }
8067
8068 synchronized (this) {
8069 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
8070 if (componentName != null) {
8071 if (r1.intent.getComponent().equals(componentName)) {
8072 activities.add(r1);
8073 }
8074 } else if (name != null) {
8075 if (r1.intent.getComponent().flattenToString().contains(name)) {
8076 activities.add(r1);
8077 }
8078 } else if (System.identityHashCode(r1) == objectId) {
8079 activities.add(r1);
8080 }
8081 }
8082 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008083 }
8084
8085 if (activities.size() <= 0) {
8086 return false;
8087 }
8088
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008089 String[] newArgs = new String[args.length - opti];
8090 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8091
Dianne Hackborn30d71892010-12-11 10:37:55 -08008092 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008093 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008094 for (int i=activities.size()-1; i>=0; i--) {
8095 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008096 if (needSep) {
8097 pw.println();
8098 }
8099 needSep = true;
8100 synchronized (this) {
8101 if (lastTask != r.task) {
8102 lastTask = r.task;
8103 pw.print("TASK "); pw.print(lastTask.affinity);
8104 pw.print(" id="); pw.println(lastTask.taskId);
8105 if (dumpAll) {
8106 lastTask.dump(pw, " ");
8107 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008108 }
8109 }
8110 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008111 }
8112 return true;
8113 }
8114
8115 /**
8116 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8117 * there is a thread associated with the activity.
8118 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008119 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008120 final ActivityRecord r, String[] args, boolean dumpAll) {
8121 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008122 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008123 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8124 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8125 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008126 if (r.app != null) pw.println(r.app.pid);
8127 else pw.println("(not running)");
8128 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008129 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008130 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008131 }
8132 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008133 // flush anything that is already in the PrintWriter since the thread is going
8134 // to write to the file descriptor directly
8135 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008136 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008137 TransferPipe tp = new TransferPipe();
8138 try {
8139 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8140 innerPrefix, args);
8141 tp.go(fd);
8142 } finally {
8143 tp.kill();
8144 }
8145 } catch (IOException e) {
8146 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008147 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008148 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008149 }
8150 }
8151 }
8152
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008153 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8154 int opti, boolean dumpAll) {
8155 boolean needSep = false;
8156
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008157 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008158 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008159 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008160 pw.println(" Registered Receivers:");
8161 Iterator it = mRegisteredReceivers.values().iterator();
8162 while (it.hasNext()) {
8163 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008164 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165 r.dump(pw, " ");
8166 }
8167 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008168
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008169 pw.println();
8170 pw.println(" Receiver Resolver Table:");
8171 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008172 needSep = true;
8173 }
8174
8175 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8176 || mPendingBroadcast != null) {
8177 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008178 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008179 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008180 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008181 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8182 pw.println(" Broadcast #" + i + ":");
8183 mParallelBroadcasts.get(i).dump(pw, " ");
8184 }
8185 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008186 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008187 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008188 }
8189 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8190 pw.println(" Serialized Broadcast #" + i + ":");
8191 mOrderedBroadcasts.get(i).dump(pw, " ");
8192 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008193 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008194 pw.println(" Pending broadcast:");
8195 if (mPendingBroadcast != null) {
8196 mPendingBroadcast.dump(pw, " ");
8197 } else {
8198 pw.println(" (null)");
8199 }
8200 needSep = true;
8201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008202
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008203 if (needSep) {
8204 pw.println();
8205 }
8206 pw.println(" Historical broadcasts:");
8207 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8208 BroadcastRecord r = mBroadcastHistory[i];
8209 if (r == null) {
8210 break;
8211 }
8212 if (dumpAll) {
8213 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8214 r.dump(pw, " ");
8215 } else {
8216 if (i >= 50) {
8217 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008218 break;
8219 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008220 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008221 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008222 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008223 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008224
8225 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008226 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008227 pw.println(" Sticky broadcasts:");
8228 StringBuilder sb = new StringBuilder(128);
8229 for (Map.Entry<String, ArrayList<Intent>> ent
8230 : mStickyBroadcasts.entrySet()) {
8231 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008232 if (dumpAll) {
8233 pw.println(":");
8234 ArrayList<Intent> intents = ent.getValue();
8235 final int N = intents.size();
8236 for (int i=0; i<N; i++) {
8237 sb.setLength(0);
8238 sb.append(" Intent: ");
8239 intents.get(i).toShortString(sb, true, false);
8240 pw.println(sb.toString());
8241 Bundle bundle = intents.get(i).getExtras();
8242 if (bundle != null) {
8243 pw.print(" ");
8244 pw.println(bundle.toString());
8245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008246 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008247 } else {
8248 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008249 }
8250 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008251 needSep = true;
8252 }
8253
8254 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008255 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008256 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008257 pw.println(" mHandler:");
8258 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008259 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008261
8262 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008263 }
8264
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008265 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008266 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008267 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008268
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008269 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8270 if (mServices.size() > 0) {
8271 pw.println(" Active services:");
8272 long nowReal = SystemClock.elapsedRealtime();
8273 Iterator<ServiceRecord> it = mServices.values().iterator();
8274 needSep = false;
8275 while (it.hasNext()) {
8276 ServiceRecord r = it.next();
8277 if (needSep) {
8278 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008279 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008280 pw.print(" * "); pw.println(r);
8281 if (dumpAll) {
8282 r.dump(pw, " ");
8283 needSep = true;
8284 } else {
8285 pw.print(" app="); pw.println(r.app);
8286 pw.print(" created=");
8287 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8288 pw.print(" started="); pw.print(r.startRequested);
8289 pw.print(" connections="); pw.println(r.connections.size());
8290 }
8291 if (dumpClient && r.app != null && r.app.thread != null) {
8292 pw.println(" Client:");
8293 pw.flush();
8294 try {
8295 TransferPipe tp = new TransferPipe();
8296 try {
8297 r.app.thread.dumpService(
8298 tp.getWriteFd().getFileDescriptor(), r, args);
8299 tp.setBufferPrefix(" ");
8300 // Short timeout, since blocking here can
8301 // deadlock with the application.
8302 tp.go(fd, 2000);
8303 } finally {
8304 tp.kill();
8305 }
8306 } catch (IOException e) {
8307 pw.println(" Failure while dumping the service: " + e);
8308 } catch (RemoteException e) {
8309 pw.println(" Got a RemoteException while dumping the service");
8310 }
8311 needSep = true;
8312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008313 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008314 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008316
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008317 if (mPendingServices.size() > 0) {
8318 if (needSep) pw.println(" ");
8319 pw.println(" Pending services:");
8320 for (int i=0; i<mPendingServices.size(); i++) {
8321 ServiceRecord r = mPendingServices.get(i);
8322 pw.print(" * Pending "); pw.println(r);
8323 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008324 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008325 needSep = true;
8326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008327
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008328 if (mRestartingServices.size() > 0) {
8329 if (needSep) pw.println(" ");
8330 pw.println(" Restarting services:");
8331 for (int i=0; i<mRestartingServices.size(); i++) {
8332 ServiceRecord r = mRestartingServices.get(i);
8333 pw.print(" * Restarting "); pw.println(r);
8334 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008336 needSep = true;
8337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008338
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008339 if (mStoppingServices.size() > 0) {
8340 if (needSep) pw.println(" ");
8341 pw.println(" Stopping services:");
8342 for (int i=0; i<mStoppingServices.size(); i++) {
8343 ServiceRecord r = mStoppingServices.get(i);
8344 pw.print(" * Stopping "); pw.println(r);
8345 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008347 needSep = true;
8348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008349
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008350 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008351 if (mServiceConnections.size() > 0) {
8352 if (needSep) pw.println(" ");
8353 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008354 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008355 = mServiceConnections.values().iterator();
8356 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008357 ArrayList<ConnectionRecord> r = it.next();
8358 for (int i=0; i<r.size(); i++) {
8359 pw.print(" * "); pw.println(r.get(i));
8360 r.get(i).dump(pw, " ");
8361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008362 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008363 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008364 }
8365 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008366
8367 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008368 }
8369
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008370 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8371 int opti, boolean dumpAll) {
8372 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008373
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008374 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8375 if (mProvidersByClass.size() > 0) {
8376 if (needSep) pw.println(" ");
8377 pw.println(" Published content providers (by class):");
8378 Iterator<Map.Entry<String, ContentProviderRecord>> it
8379 = mProvidersByClass.entrySet().iterator();
8380 while (it.hasNext()) {
8381 Map.Entry<String, ContentProviderRecord> e = it.next();
8382 ContentProviderRecord r = e.getValue();
8383 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008384 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008386 } else {
8387 pw.print(" * "); pw.print(r.name.toShortString());
8388 if (r.app != null) {
8389 pw.println(":");
8390 pw.print(" "); pw.println(r.app);
8391 } else {
8392 pw.println();
8393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008394 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008395 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008396 needSep = true;
8397 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008398
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008399 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008400 if (mProvidersByName.size() > 0) {
8401 pw.println(" ");
8402 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008403 Iterator<Map.Entry<String, ContentProviderRecord>> it
8404 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008405 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008406 Map.Entry<String, ContentProviderRecord> e = it.next();
8407 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008408 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8409 pw.println(r);
8410 }
8411 needSep = true;
8412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008413 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008414
8415 if (mLaunchingProviders.size() > 0) {
8416 if (needSep) pw.println(" ");
8417 pw.println(" Launching content providers:");
8418 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8419 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8420 pw.println(mLaunchingProviders.get(i));
8421 }
8422 needSep = true;
8423 }
8424
8425 if (mGrantedUriPermissions.size() > 0) {
8426 pw.println();
8427 pw.println("Granted Uri Permissions:");
8428 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8429 int uid = mGrantedUriPermissions.keyAt(i);
8430 HashMap<Uri, UriPermission> perms
8431 = mGrantedUriPermissions.valueAt(i);
8432 pw.print(" * UID "); pw.print(uid);
8433 pw.println(" holds:");
8434 for (UriPermission perm : perms.values()) {
8435 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008436 if (dumpAll) {
8437 perm.dump(pw, " ");
8438 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008439 }
8440 }
8441 needSep = true;
8442 }
8443
8444 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008445 }
8446
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008447 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8448 int opti, boolean dumpAll) {
8449 boolean needSep = false;
8450
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008451 if (this.mIntentSenderRecords.size() > 0) {
8452 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8453 Iterator<WeakReference<PendingIntentRecord>> it
8454 = mIntentSenderRecords.values().iterator();
8455 while (it.hasNext()) {
8456 WeakReference<PendingIntentRecord> ref = it.next();
8457 PendingIntentRecord rec = ref != null ? ref.get(): null;
8458 needSep = true;
8459 if (rec != null) {
8460 pw.print(" * "); pw.println(rec);
8461 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008462 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008464 } else {
8465 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008466 }
8467 }
8468 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008469
8470 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 }
8472
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008473 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8474 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008476 boolean needNL = false;
8477 final String innerPrefix = prefix + " ";
8478 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008479 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008480 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008481 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008482 if (needNL) {
8483 pw.println(" ");
8484 needNL = false;
8485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486 if (lastTask != r.task) {
8487 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008488 pw.print(prefix);
8489 pw.print(full ? "* " : " ");
8490 pw.println(lastTask);
8491 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008492 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008493 } else if (complete) {
8494 // Complete + brief == give a summary. Isn't that obvious?!?
8495 if (lastTask.intent != null) {
8496 pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
8497 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008498 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008499 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008500 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8501 pw.print(" #"); pw.print(i); pw.print(": ");
8502 pw.println(r);
8503 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008504 r.dump(pw, innerPrefix);
8505 } else if (complete) {
8506 // Complete + brief == give a summary. Isn't that obvious?!?
8507 pw.print(innerPrefix); pw.println(r.intent);
8508 if (r.app != null) {
8509 pw.print(innerPrefix); pw.println(r.app);
8510 }
8511 }
8512 if (client && r.app != null && r.app.thread != null) {
8513 // flush anything that is already in the PrintWriter since the thread is going
8514 // to write to the file descriptor directly
8515 pw.flush();
8516 try {
8517 TransferPipe tp = new TransferPipe();
8518 try {
8519 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8520 innerPrefix, args);
8521 // Short timeout, since blocking here can
8522 // deadlock with the application.
8523 tp.go(fd, 2000);
8524 } finally {
8525 tp.kill();
8526 }
8527 } catch (IOException e) {
8528 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8529 } catch (RemoteException e) {
8530 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8531 }
8532 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008534 }
8535 }
8536
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008537 private static String buildOomTag(String prefix, String space, int val, int base) {
8538 if (val == base) {
8539 if (space == null) return prefix;
8540 return prefix + " ";
8541 }
8542 return prefix + "+" + Integer.toString(val-base);
8543 }
8544
8545 private static final int dumpProcessList(PrintWriter pw,
8546 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008547 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008548 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008549 final int N = list.size()-1;
8550 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008551 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008552 pw.println(String.format("%s%s #%2d: %s",
8553 prefix, (r.persistent ? persistentLabel : normalLabel),
8554 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555 if (r.persistent) {
8556 numPers++;
8557 }
8558 }
8559 return numPers;
8560 }
8561
Dianne Hackborn287952c2010-09-22 22:34:31 -07008562 private static final void dumpProcessOomList(PrintWriter pw,
8563 ActivityManagerService service, List<ProcessRecord> list,
8564 String prefix, String normalLabel, String persistentLabel,
8565 boolean inclDetails) {
8566
8567 final long curRealtime = SystemClock.elapsedRealtime();
8568 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8569 final long curUptime = SystemClock.uptimeMillis();
8570 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8571
8572 final int N = list.size()-1;
8573 for (int i=N; i>=0; i--) {
8574 ProcessRecord r = list.get(i);
8575 String oomAdj;
8576 if (r.setAdj >= EMPTY_APP_ADJ) {
8577 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8578 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8579 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8580 } else if (r.setAdj >= HOME_APP_ADJ) {
8581 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8582 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8583 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8584 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8585 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8586 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8587 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8588 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8589 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8590 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8591 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8592 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8593 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8594 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8595 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8596 } else if (r.setAdj >= SYSTEM_ADJ) {
8597 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8598 } else {
8599 oomAdj = Integer.toString(r.setAdj);
8600 }
8601 String schedGroup;
8602 switch (r.setSchedGroup) {
8603 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8604 schedGroup = "B";
8605 break;
8606 case Process.THREAD_GROUP_DEFAULT:
8607 schedGroup = "F";
8608 break;
8609 default:
8610 schedGroup = Integer.toString(r.setSchedGroup);
8611 break;
8612 }
8613 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8614 prefix, (r.persistent ? persistentLabel : normalLabel),
8615 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8616 if (r.adjSource != null || r.adjTarget != null) {
8617 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008618 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008619 if (r.adjTarget instanceof ComponentName) {
8620 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8621 } else if (r.adjTarget != null) {
8622 pw.print(r.adjTarget.toString());
8623 } else {
8624 pw.print("{null}");
8625 }
8626 pw.print("<=");
8627 if (r.adjSource instanceof ProcessRecord) {
8628 pw.print("Proc{");
8629 pw.print(((ProcessRecord)r.adjSource).toShortString());
8630 pw.println("}");
8631 } else if (r.adjSource != null) {
8632 pw.println(r.adjSource.toString());
8633 } else {
8634 pw.println("{null}");
8635 }
8636 }
8637 if (inclDetails) {
8638 pw.print(prefix);
8639 pw.print(" ");
8640 pw.print("oom: max="); pw.print(r.maxAdj);
8641 pw.print(" hidden="); pw.print(r.hiddenAdj);
8642 pw.print(" curRaw="); pw.print(r.curRawAdj);
8643 pw.print(" setRaw="); pw.print(r.setRawAdj);
8644 pw.print(" cur="); pw.print(r.curAdj);
8645 pw.print(" set="); pw.println(r.setAdj);
8646 pw.print(prefix);
8647 pw.print(" ");
8648 pw.print("keeping="); pw.print(r.keeping);
8649 pw.print(" hidden="); pw.print(r.hidden);
8650 pw.print(" empty="); pw.println(r.empty);
8651
8652 if (!r.keeping) {
8653 if (r.lastWakeTime != 0) {
8654 long wtime;
8655 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8656 synchronized (stats) {
8657 wtime = stats.getProcessWakeTime(r.info.uid,
8658 r.pid, curRealtime);
8659 }
8660 long timeUsed = wtime - r.lastWakeTime;
8661 pw.print(prefix);
8662 pw.print(" ");
8663 pw.print("keep awake over ");
8664 TimeUtils.formatDuration(realtimeSince, pw);
8665 pw.print(" used ");
8666 TimeUtils.formatDuration(timeUsed, pw);
8667 pw.print(" (");
8668 pw.print((timeUsed*100)/realtimeSince);
8669 pw.println("%)");
8670 }
8671 if (r.lastCpuTime != 0) {
8672 long timeUsed = r.curCpuTime - r.lastCpuTime;
8673 pw.print(prefix);
8674 pw.print(" ");
8675 pw.print("run cpu over ");
8676 TimeUtils.formatDuration(uptimeSince, pw);
8677 pw.print(" used ");
8678 TimeUtils.formatDuration(timeUsed, pw);
8679 pw.print(" (");
8680 pw.print((timeUsed*100)/uptimeSince);
8681 pw.println("%)");
8682 }
8683 }
8684 }
8685 }
8686 }
8687
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008688 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
8689 ArrayList<ProcessRecord> procs;
8690 synchronized (this) {
8691 if (args != null && args.length > 0
8692 && args[0].charAt(0) != '-') {
8693 procs = new ArrayList<ProcessRecord>();
8694 int pid = -1;
8695 try {
8696 pid = Integer.parseInt(args[0]);
8697 } catch (NumberFormatException e) {
8698
8699 }
8700 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8701 ProcessRecord proc = mLruProcesses.get(i);
8702 if (proc.pid == pid) {
8703 procs.add(proc);
8704 } else if (proc.processName.equals(args[0])) {
8705 procs.add(proc);
8706 }
8707 }
8708 if (procs.size() <= 0) {
8709 pw.println("No process found for: " + args[0]);
8710 return null;
8711 }
8712 } else {
8713 procs = new ArrayList<ProcessRecord>(mLruProcesses);
8714 }
8715 }
8716 return procs;
8717 }
8718
8719 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
8720 PrintWriter pw, String[] args) {
8721 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8722 if (procs == null) {
8723 return;
8724 }
8725
8726 long uptime = SystemClock.uptimeMillis();
8727 long realtime = SystemClock.elapsedRealtime();
8728 pw.println("Applications Graphics Acceleration Info:");
8729 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8730
8731 String callArgs[] = {"graphics"};
8732 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8733 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008734 if (r.thread != null) {
8735 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
8736 pw.flush();
8737 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008738 TransferPipe.goDump(r.thread.asBinder(), fd, callArgs);
8739 } catch (IOException e) {
8740 pw.println("Failure: " + e);
8741 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07008742 } catch (RemoteException e) {
8743 pw.println("Got RemoteException!");
8744 pw.flush();
8745 }
8746 }
8747 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07008748 }
8749
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008750 final void dumpApplicationMemoryUsage(FileDescriptor fd,
8751 PrintWriter pw, String prefix, String[] args) {
8752 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8753 if (procs == null) {
8754 return;
8755 }
8756
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008757 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008758 long uptime = SystemClock.uptimeMillis();
8759 long realtime = SystemClock.elapsedRealtime();
8760
8761 if (isCheckinRequest) {
8762 // short checkin version
8763 pw.println(uptime + "," + realtime);
8764 pw.flush();
8765 } else {
8766 pw.println("Applications Memory Usage (kB):");
8767 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8768 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008769 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8770 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008771 if (r.thread != null) {
8772 if (!isCheckinRequest) {
8773 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8774 pw.flush();
8775 }
8776 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008777 TransferPipe.goDump(r.thread.asBinder(), fd, args);
8778 } catch (IOException e) {
8779 pw.println("Failure: " + e);
8780 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008781 } catch (RemoteException e) {
8782 if (!isCheckinRequest) {
8783 pw.println("Got RemoteException!");
8784 pw.flush();
8785 }
8786 }
8787 }
8788 }
8789 }
8790
8791 /**
8792 * Searches array of arguments for the specified string
8793 * @param args array of argument strings
8794 * @param value value to search for
8795 * @return true if the value is contained in the array
8796 */
8797 private static boolean scanArgs(String[] args, String value) {
8798 if (args != null) {
8799 for (String arg : args) {
8800 if (value.equals(arg)) {
8801 return true;
8802 }
8803 }
8804 }
8805 return false;
8806 }
8807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008808 private final void killServicesLocked(ProcessRecord app,
8809 boolean allowRestart) {
8810 // Report disconnected services.
8811 if (false) {
8812 // XXX we are letting the client link to the service for
8813 // death notifications.
8814 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008815 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008817 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008818 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008819 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008820 = r.connections.values().iterator();
8821 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008822 ArrayList<ConnectionRecord> cl = jt.next();
8823 for (int i=0; i<cl.size(); i++) {
8824 ConnectionRecord c = cl.get(i);
8825 if (c.binding.client != app) {
8826 try {
8827 //c.conn.connected(r.className, null);
8828 } catch (Exception e) {
8829 // todo: this should be asynchronous!
8830 Slog.w(TAG, "Exception thrown disconnected servce "
8831 + r.shortName
8832 + " from app " + app.processName, e);
8833 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008834 }
8835 }
8836 }
8837 }
8838 }
8839 }
8840 }
8841
8842 // Clean up any connections this application has to other services.
8843 if (app.connections.size() > 0) {
8844 Iterator<ConnectionRecord> it = app.connections.iterator();
8845 while (it.hasNext()) {
8846 ConnectionRecord r = it.next();
8847 removeConnectionLocked(r, app, null);
8848 }
8849 }
8850 app.connections.clear();
8851
8852 if (app.services.size() != 0) {
8853 // Any services running in the application need to be placed
8854 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008855 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008856 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008857 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008858 synchronized (sr.stats.getBatteryStats()) {
8859 sr.stats.stopLaunchedLocked();
8860 }
8861 sr.app = null;
8862 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008863 if (mStoppingServices.remove(sr)) {
8864 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8865 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008866
8867 boolean hasClients = sr.bindings.size() > 0;
8868 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008869 Iterator<IntentBindRecord> bindings
8870 = sr.bindings.values().iterator();
8871 while (bindings.hasNext()) {
8872 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008873 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008874 + ": shouldUnbind=" + b.hasBound);
8875 b.binder = null;
8876 b.requested = b.received = b.hasBound = false;
8877 }
8878 }
8879
Dianne Hackborn070783f2010-12-29 16:46:28 -08008880 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
8881 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008882 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008883 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008884 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008885 sr.crashCount, sr.shortName, app.pid);
8886 bringDownServiceLocked(sr, true);
8887 } else if (!allowRestart) {
8888 bringDownServiceLocked(sr, true);
8889 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008890 boolean canceled = scheduleServiceRestartLocked(sr, true);
8891
8892 // Should the service remain running? Note that in the
8893 // extreme case of so many attempts to deliver a command
8894 // that it failed, that we also will stop it here.
8895 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8896 if (sr.pendingStarts.size() == 0) {
8897 sr.startRequested = false;
8898 if (!hasClients) {
8899 // Whoops, no reason to restart!
8900 bringDownServiceLocked(sr, true);
8901 }
8902 }
8903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008904 }
8905 }
8906
8907 if (!allowRestart) {
8908 app.services.clear();
8909 }
8910 }
8911
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008912 // Make sure we have no more records on the stopping list.
8913 int i = mStoppingServices.size();
8914 while (i > 0) {
8915 i--;
8916 ServiceRecord sr = mStoppingServices.get(i);
8917 if (sr.app == app) {
8918 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008919 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008920 }
8921 }
8922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008923 app.executingServices.clear();
8924 }
8925
8926 private final void removeDyingProviderLocked(ProcessRecord proc,
8927 ContentProviderRecord cpr) {
8928 synchronized (cpr) {
8929 cpr.launchingApp = null;
8930 cpr.notifyAll();
8931 }
8932
8933 mProvidersByClass.remove(cpr.info.name);
8934 String names[] = cpr.info.authority.split(";");
8935 for (int j = 0; j < names.length; j++) {
8936 mProvidersByName.remove(names[j]);
8937 }
8938
8939 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8940 while (cit.hasNext()) {
8941 ProcessRecord capp = cit.next();
8942 if (!capp.persistent && capp.thread != null
8943 && capp.pid != 0
8944 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008945 Slog.i(TAG, "Kill " + capp.processName
8946 + " (pid " + capp.pid + "): provider " + cpr.info.name
8947 + " in dying process " + proc.processName);
8948 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8949 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008950 Process.killProcess(capp.pid);
8951 }
8952 }
8953
8954 mLaunchingProviders.remove(cpr);
8955 }
8956
8957 /**
8958 * Main code for cleaning up a process when it has gone away. This is
8959 * called both as a result of the process dying, or directly when stopping
8960 * a process when running in single process mode.
8961 */
8962 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8963 boolean restarting, int index) {
8964 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008965 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008966 }
8967
Dianne Hackborn36124872009-10-08 16:22:03 -07008968 mProcessesToGc.remove(app);
8969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970 // Dismiss any open dialogs.
8971 if (app.crashDialog != null) {
8972 app.crashDialog.dismiss();
8973 app.crashDialog = null;
8974 }
8975 if (app.anrDialog != null) {
8976 app.anrDialog.dismiss();
8977 app.anrDialog = null;
8978 }
8979 if (app.waitDialog != null) {
8980 app.waitDialog.dismiss();
8981 app.waitDialog = null;
8982 }
8983
8984 app.crashing = false;
8985 app.notResponding = false;
8986
8987 app.resetPackageList();
8988 app.thread = null;
8989 app.forcingToForeground = null;
8990 app.foregroundServices = false;
8991
8992 killServicesLocked(app, true);
8993
8994 boolean restart = false;
8995
8996 int NL = mLaunchingProviders.size();
8997
8998 // Remove published content providers.
8999 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009000 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009001 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009002 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009003 cpr.provider = null;
9004 cpr.app = null;
9005
9006 // See if someone is waiting for this provider... in which
9007 // case we don't remove it, but just let it restart.
9008 int i = 0;
9009 if (!app.bad) {
9010 for (; i<NL; i++) {
9011 if (mLaunchingProviders.get(i) == cpr) {
9012 restart = true;
9013 break;
9014 }
9015 }
9016 } else {
9017 i = NL;
9018 }
9019
9020 if (i >= NL) {
9021 removeDyingProviderLocked(app, cpr);
9022 NL = mLaunchingProviders.size();
9023 }
9024 }
9025 app.pubProviders.clear();
9026 }
9027
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009028 // Take care of any launching providers waiting for this process.
9029 if (checkAppInLaunchingProvidersLocked(app, false)) {
9030 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009031 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009033 // Unregister from connected content providers.
9034 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009035 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009036 while (it.hasNext()) {
9037 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9038 cpr.clients.remove(app);
9039 }
9040 app.conProviders.clear();
9041 }
9042
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009043 // At this point there may be remaining entries in mLaunchingProviders
9044 // where we were the only one waiting, so they are no longer of use.
9045 // Look for these and clean up if found.
9046 // XXX Commented out for now. Trying to figure out a way to reproduce
9047 // the actual situation to identify what is actually going on.
9048 if (false) {
9049 for (int i=0; i<NL; i++) {
9050 ContentProviderRecord cpr = (ContentProviderRecord)
9051 mLaunchingProviders.get(i);
9052 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9053 synchronized (cpr) {
9054 cpr.launchingApp = null;
9055 cpr.notifyAll();
9056 }
9057 }
9058 }
9059 }
9060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009061 skipCurrentReceiverLocked(app);
9062
9063 // Unregister any receivers.
9064 if (app.receivers.size() > 0) {
9065 Iterator<ReceiverList> it = app.receivers.iterator();
9066 while (it.hasNext()) {
9067 removeReceiverLocked(it.next());
9068 }
9069 app.receivers.clear();
9070 }
9071
Christopher Tate181fafa2009-05-14 11:12:14 -07009072 // If the app is undergoing backup, tell the backup manager about it
9073 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009074 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009075 try {
9076 IBackupManager bm = IBackupManager.Stub.asInterface(
9077 ServiceManager.getService(Context.BACKUP_SERVICE));
9078 bm.agentDisconnected(app.info.packageName);
9079 } catch (RemoteException e) {
9080 // can't happen; backup manager is local
9081 }
9082 }
9083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009084 // If the caller is restarting this app, then leave it in its
9085 // current lists and let the caller take care of it.
9086 if (restarting) {
9087 return;
9088 }
9089
9090 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009091 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009092 "Removing non-persistent process during cleanup: " + app);
9093 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009094 if (mHeavyWeightProcess == app) {
9095 mHeavyWeightProcess = null;
9096 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009098 } else if (!app.removed) {
9099 // This app is persistent, so we need to keep its record around.
9100 // If it is not already on the pending app list, add it there
9101 // and start a new process for it.
9102 app.thread = null;
9103 app.forcingToForeground = null;
9104 app.foregroundServices = false;
9105 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9106 mPersistentStartingProcesses.add(app);
9107 restart = true;
9108 }
9109 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009110 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9111 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009112 mProcessesOnHold.remove(app);
9113
The Android Open Source Project4df24232009-03-05 14:34:35 -08009114 if (app == mHomeProcess) {
9115 mHomeProcess = null;
9116 }
9117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009118 if (restart) {
9119 // We have components that still need to be running in the
9120 // process, so re-launch it.
9121 mProcessNames.put(app.processName, app.info.uid, app);
9122 startProcessLocked(app, "restart", app.processName);
9123 } else if (app.pid > 0 && app.pid != MY_PID) {
9124 // Goodbye!
9125 synchronized (mPidsSelfLocked) {
9126 mPidsSelfLocked.remove(app.pid);
9127 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9128 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009129 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009130 }
9131 }
9132
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009133 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9134 // Look through the content providers we are waiting to have launched,
9135 // and if any run in this process then either schedule a restart of
9136 // the process or kill the client waiting for it if this process has
9137 // gone bad.
9138 int NL = mLaunchingProviders.size();
9139 boolean restart = false;
9140 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009141 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009142 if (cpr.launchingApp == app) {
9143 if (!alwaysBad && !app.bad) {
9144 restart = true;
9145 } else {
9146 removeDyingProviderLocked(app, cpr);
9147 NL = mLaunchingProviders.size();
9148 }
9149 }
9150 }
9151 return restart;
9152 }
9153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009154 // =========================================================
9155 // SERVICES
9156 // =========================================================
9157
9158 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9159 ActivityManager.RunningServiceInfo info =
9160 new ActivityManager.RunningServiceInfo();
9161 info.service = r.name;
9162 if (r.app != null) {
9163 info.pid = r.app.pid;
9164 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009165 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009166 info.process = r.processName;
9167 info.foreground = r.isForeground;
9168 info.activeSince = r.createTime;
9169 info.started = r.startRequested;
9170 info.clientCount = r.connections.size();
9171 info.crashCount = r.crashCount;
9172 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009173 if (r.isForeground) {
9174 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9175 }
9176 if (r.startRequested) {
9177 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9178 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009179 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009180 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9181 }
9182 if (r.app != null && r.app.persistent) {
9183 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9184 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009185
9186 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9187 for (int i=0; i<connl.size(); i++) {
9188 ConnectionRecord conn = connl.get(i);
9189 if (conn.clientLabel != 0) {
9190 info.clientPackage = conn.binding.client.info.packageName;
9191 info.clientLabel = conn.clientLabel;
9192 return info;
9193 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009194 }
9195 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009196 return info;
9197 }
9198
9199 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9200 int flags) {
9201 synchronized (this) {
9202 ArrayList<ActivityManager.RunningServiceInfo> res
9203 = new ArrayList<ActivityManager.RunningServiceInfo>();
9204
9205 if (mServices.size() > 0) {
9206 Iterator<ServiceRecord> it = mServices.values().iterator();
9207 while (it.hasNext() && res.size() < maxNum) {
9208 res.add(makeRunningServiceInfoLocked(it.next()));
9209 }
9210 }
9211
9212 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9213 ServiceRecord r = mRestartingServices.get(i);
9214 ActivityManager.RunningServiceInfo info =
9215 makeRunningServiceInfoLocked(r);
9216 info.restarting = r.nextRestartTime;
9217 res.add(info);
9218 }
9219
9220 return res;
9221 }
9222 }
9223
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009224 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9225 synchronized (this) {
9226 ServiceRecord r = mServices.get(name);
9227 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009228 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9229 for (int i=0; i<conn.size(); i++) {
9230 if (conn.get(i).clientIntent != null) {
9231 return conn.get(i).clientIntent;
9232 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009233 }
9234 }
9235 }
9236 }
9237 return null;
9238 }
9239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 private final ServiceRecord findServiceLocked(ComponentName name,
9241 IBinder token) {
9242 ServiceRecord r = mServices.get(name);
9243 return r == token ? r : null;
9244 }
9245
9246 private final class ServiceLookupResult {
9247 final ServiceRecord record;
9248 final String permission;
9249
9250 ServiceLookupResult(ServiceRecord _record, String _permission) {
9251 record = _record;
9252 permission = _permission;
9253 }
9254 };
9255
9256 private ServiceLookupResult findServiceLocked(Intent service,
9257 String resolvedType) {
9258 ServiceRecord r = null;
9259 if (service.getComponent() != null) {
9260 r = mServices.get(service.getComponent());
9261 }
9262 if (r == null) {
9263 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9264 r = mServicesByIntent.get(filter);
9265 }
9266
9267 if (r == null) {
9268 try {
9269 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009270 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271 service, resolvedType, 0);
9272 ServiceInfo sInfo =
9273 rInfo != null ? rInfo.serviceInfo : null;
9274 if (sInfo == null) {
9275 return null;
9276 }
9277
9278 ComponentName name = new ComponentName(
9279 sInfo.applicationInfo.packageName, sInfo.name);
9280 r = mServices.get(name);
9281 } catch (RemoteException ex) {
9282 // pm is in same process, this will never happen.
9283 }
9284 }
9285 if (r != null) {
9286 int callingPid = Binder.getCallingPid();
9287 int callingUid = Binder.getCallingUid();
9288 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009289 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009290 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009291 if (!r.exported) {
9292 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9293 + " from pid=" + callingPid
9294 + ", uid=" + callingUid
9295 + " that is not exported from uid " + r.appInfo.uid);
9296 return new ServiceLookupResult(null, "not exported from uid "
9297 + r.appInfo.uid);
9298 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009299 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009300 + " from pid=" + callingPid
9301 + ", uid=" + callingUid
9302 + " requires " + r.permission);
9303 return new ServiceLookupResult(null, r.permission);
9304 }
9305 return new ServiceLookupResult(r, null);
9306 }
9307 return null;
9308 }
9309
9310 private class ServiceRestarter implements Runnable {
9311 private ServiceRecord mService;
9312
9313 void setService(ServiceRecord service) {
9314 mService = service;
9315 }
9316
9317 public void run() {
9318 synchronized(ActivityManagerService.this) {
9319 performServiceRestartLocked(mService);
9320 }
9321 }
9322 }
9323
9324 private ServiceLookupResult retrieveServiceLocked(Intent service,
9325 String resolvedType, int callingPid, int callingUid) {
9326 ServiceRecord r = null;
9327 if (service.getComponent() != null) {
9328 r = mServices.get(service.getComponent());
9329 }
9330 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9331 r = mServicesByIntent.get(filter);
9332 if (r == null) {
9333 try {
9334 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009335 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009336 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009337 ServiceInfo sInfo =
9338 rInfo != null ? rInfo.serviceInfo : null;
9339 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009340 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009341 ": not found");
9342 return null;
9343 }
9344
9345 ComponentName name = new ComponentName(
9346 sInfo.applicationInfo.packageName, sInfo.name);
9347 r = mServices.get(name);
9348 if (r == null) {
9349 filter = new Intent.FilterComparison(service.cloneFilter());
9350 ServiceRestarter res = new ServiceRestarter();
9351 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9352 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9353 synchronized (stats) {
9354 ss = stats.getServiceStatsLocked(
9355 sInfo.applicationInfo.uid, sInfo.packageName,
9356 sInfo.name);
9357 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009358 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009359 res.setService(r);
9360 mServices.put(name, r);
9361 mServicesByIntent.put(filter, r);
9362
9363 // Make sure this component isn't in the pending list.
9364 int N = mPendingServices.size();
9365 for (int i=0; i<N; i++) {
9366 ServiceRecord pr = mPendingServices.get(i);
9367 if (pr.name.equals(name)) {
9368 mPendingServices.remove(i);
9369 i--;
9370 N--;
9371 }
9372 }
9373 }
9374 } catch (RemoteException ex) {
9375 // pm is in same process, this will never happen.
9376 }
9377 }
9378 if (r != null) {
9379 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009380 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009381 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009382 if (!r.exported) {
9383 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9384 + " from pid=" + callingPid
9385 + ", uid=" + callingUid
9386 + " that is not exported from uid " + r.appInfo.uid);
9387 return new ServiceLookupResult(null, "not exported from uid "
9388 + r.appInfo.uid);
9389 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009390 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009391 + " from pid=" + callingPid
9392 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009393 + " requires " + r.permission);
9394 return new ServiceLookupResult(null, r.permission);
9395 }
9396 return new ServiceLookupResult(r, null);
9397 }
9398 return null;
9399 }
9400
Dianne Hackborn287952c2010-09-22 22:34:31 -07009401 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9402 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9403 + why + " of " + r + " in app " + r.app);
9404 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9405 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009406 long now = SystemClock.uptimeMillis();
9407 if (r.executeNesting == 0 && r.app != null) {
9408 if (r.app.executingServices.size() == 0) {
9409 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9410 msg.obj = r.app;
9411 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9412 }
9413 r.app.executingServices.add(r);
9414 }
9415 r.executeNesting++;
9416 r.executingStart = now;
9417 }
9418
9419 private final void sendServiceArgsLocked(ServiceRecord r,
9420 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009421 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009422 if (N == 0) {
9423 return;
9424 }
9425
Dianne Hackborn39792d22010-08-19 18:01:52 -07009426 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009427 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009428 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009429 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9430 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009431 if (si.intent == null && N > 1) {
9432 // If somehow we got a dummy null intent in the middle,
9433 // then skip it. DO NOT skip a null intent when it is
9434 // the only one in the list -- this is to support the
9435 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009436 continue;
9437 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009438 si.deliveredTime = SystemClock.uptimeMillis();
9439 r.deliveredStarts.add(si);
9440 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009441 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009442 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009443 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009444 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009445 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009446 if (!oomAdjusted) {
9447 oomAdjusted = true;
9448 updateOomAdjLocked(r.app);
9449 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009450 int flags = 0;
9451 if (si.deliveryCount > 0) {
9452 flags |= Service.START_FLAG_RETRY;
9453 }
9454 if (si.doneExecutingCount > 0) {
9455 flags |= Service.START_FLAG_REDELIVERY;
9456 }
9457 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009458 } catch (RemoteException e) {
9459 // Remote process gone... we'll let the normal cleanup take
9460 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009461 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009462 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009463 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009464 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009465 break;
9466 }
9467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009468 }
9469
9470 private final boolean requestServiceBindingLocked(ServiceRecord r,
9471 IntentBindRecord i, boolean rebind) {
9472 if (r.app == null || r.app.thread == null) {
9473 // If service is not currently running, can't yet bind.
9474 return false;
9475 }
9476 if ((!i.requested || rebind) && i.apps.size() > 0) {
9477 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009478 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9480 if (!rebind) {
9481 i.requested = true;
9482 }
9483 i.hasBound = true;
9484 i.doRebind = false;
9485 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009486 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009487 return false;
9488 }
9489 }
9490 return true;
9491 }
9492
9493 private final void requestServiceBindingsLocked(ServiceRecord r) {
9494 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9495 while (bindings.hasNext()) {
9496 IntentBindRecord i = bindings.next();
9497 if (!requestServiceBindingLocked(r, i, false)) {
9498 break;
9499 }
9500 }
9501 }
9502
9503 private final void realStartServiceLocked(ServiceRecord r,
9504 ProcessRecord app) throws RemoteException {
9505 if (app.thread == null) {
9506 throw new RemoteException();
9507 }
9508
9509 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009510 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009511
9512 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009513 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009514 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009515
9516 boolean created = false;
9517 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009518 mStringBuilder.setLength(0);
9519 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009520 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009521 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009522 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009523 synchronized (r.stats.getBatteryStats()) {
9524 r.stats.startLaunchedLocked();
9525 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009526 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009527 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009528 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009529 created = true;
9530 } finally {
9531 if (!created) {
9532 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009533 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009534 }
9535 }
9536
9537 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009538
9539 // If the service is in the started state, and there are no
9540 // pending arguments, then fake up one so its onStartCommand() will
9541 // be called.
9542 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9543 r.lastStartId++;
9544 if (r.lastStartId < 1) {
9545 r.lastStartId = 1;
9546 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009547 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009548 }
9549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 sendServiceArgsLocked(r, true);
9551 }
9552
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009553 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9554 boolean allowCancel) {
9555 boolean canceled = false;
9556
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009557 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009558 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009559 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009560
Dianne Hackborn070783f2010-12-29 16:46:28 -08009561 if ((r.serviceInfo.applicationInfo.flags
9562 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9563 minDuration /= 4;
9564 }
9565
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009566 // Any delivered but not yet finished starts should be put back
9567 // on the pending list.
9568 final int N = r.deliveredStarts.size();
9569 if (N > 0) {
9570 for (int i=N-1; i>=0; i--) {
9571 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009572 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009573 if (si.intent == null) {
9574 // We'll generate this again if needed.
9575 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9576 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9577 r.pendingStarts.add(0, si);
9578 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9579 dur *= 2;
9580 if (minDuration < dur) minDuration = dur;
9581 if (resetTime < dur) resetTime = dur;
9582 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009583 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009584 + r.name);
9585 canceled = true;
9586 }
9587 }
9588 r.deliveredStarts.clear();
9589 }
9590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009591 r.totalRestartCount++;
9592 if (r.restartDelay == 0) {
9593 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009594 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009595 } else {
9596 // If it has been a "reasonably long time" since the service
9597 // was started, then reset our restart duration back to
9598 // the beginning, so we don't infinitely increase the duration
9599 // on a service that just occasionally gets killed (which is
9600 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009601 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009602 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009603 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009604 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009605 if ((r.serviceInfo.applicationInfo.flags
9606 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9607 // Services in peristent processes will restart much more
9608 // quickly, since they are pretty important. (Think SystemUI).
9609 r.restartDelay += minDuration/2;
9610 } else {
9611 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9612 if (r.restartDelay < minDuration) {
9613 r.restartDelay = minDuration;
9614 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009616 }
9617 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009618
9619 r.nextRestartTime = now + r.restartDelay;
9620
9621 // Make sure that we don't end up restarting a bunch of services
9622 // all at the same time.
9623 boolean repeat;
9624 do {
9625 repeat = false;
9626 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9627 ServiceRecord r2 = mRestartingServices.get(i);
9628 if (r2 != r && r.nextRestartTime
9629 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9630 && r.nextRestartTime
9631 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9632 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9633 r.restartDelay = r.nextRestartTime - now;
9634 repeat = true;
9635 break;
9636 }
9637 }
9638 } while (repeat);
9639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009640 if (!mRestartingServices.contains(r)) {
9641 mRestartingServices.add(r);
9642 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009643
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009644 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009646 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009647 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009648 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009649 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009650 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009651 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652 r.shortName, r.restartDelay);
9653
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009654 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009655 }
9656
9657 final void performServiceRestartLocked(ServiceRecord r) {
9658 if (!mRestartingServices.contains(r)) {
9659 return;
9660 }
9661 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9662 }
9663
9664 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9665 if (r.restartDelay == 0) {
9666 return false;
9667 }
9668 r.resetRestartCounter();
9669 mRestartingServices.remove(r);
9670 mHandler.removeCallbacks(r.restarter);
9671 return true;
9672 }
9673
9674 private final boolean bringUpServiceLocked(ServiceRecord r,
9675 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009676 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009677 //r.dump(" ");
9678
Dianne Hackborn36124872009-10-08 16:22:03 -07009679 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009680 sendServiceArgsLocked(r, false);
9681 return true;
9682 }
9683
9684 if (!whileRestarting && r.restartDelay > 0) {
9685 // If waiting for a restart, then do nothing.
9686 return true;
9687 }
9688
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009689 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009690
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009691 // We are now bringing the service up, so no longer in the
9692 // restarting state.
9693 mRestartingServices.remove(r);
9694
Dianne Hackborne7f97212011-02-24 14:40:20 -08009695 // Service is now being launched, its package can't be stopped.
9696 try {
9697 AppGlobals.getPackageManager().setPackageStoppedState(
9698 r.packageName, false);
9699 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009700 } catch (IllegalArgumentException e) {
9701 Slog.w(TAG, "Failed trying to unstop package "
9702 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009703 }
9704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009705 final String appName = r.processName;
9706 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9707 if (app != null && app.thread != null) {
9708 try {
9709 realStartServiceLocked(r, app);
9710 return true;
9711 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009712 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009713 }
9714
9715 // If a dead object exception was thrown -- fall through to
9716 // restart the application.
9717 }
9718
Dianne Hackborn36124872009-10-08 16:22:03 -07009719 // Not running -- get it started, and enqueue this service record
9720 // to be executed when the app comes up.
9721 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9722 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009723 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009724 + r.appInfo.packageName + "/"
9725 + r.appInfo.uid + " for service "
9726 + r.intent.getIntent() + ": process is bad");
9727 bringDownServiceLocked(r, true);
9728 return false;
9729 }
9730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009731 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009732 mPendingServices.add(r);
9733 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009735 return true;
9736 }
9737
9738 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009739 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009740 //r.dump(" ");
9741
9742 // Does it still need to run?
9743 if (!force && r.startRequested) {
9744 return;
9745 }
9746 if (r.connections.size() > 0) {
9747 if (!force) {
9748 // XXX should probably keep a count of the number of auto-create
9749 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009750 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009751 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009752 ArrayList<ConnectionRecord> cr = it.next();
9753 for (int i=0; i<cr.size(); i++) {
9754 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9755 return;
9756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 }
9758 }
9759 }
9760
9761 // Report to all of the connections that the service is no longer
9762 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009763 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009764 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009765 ArrayList<ConnectionRecord> c = it.next();
9766 for (int i=0; i<c.size(); i++) {
9767 try {
9768 c.get(i).conn.connected(r.name, null);
9769 } catch (Exception e) {
9770 Slog.w(TAG, "Failure disconnecting service " + r.name +
9771 " to connection " + c.get(i).conn.asBinder() +
9772 " (in " + c.get(i).binding.client.processName + ")", e);
9773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009774 }
9775 }
9776 }
9777
9778 // Tell the service that it has been unbound.
9779 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9780 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9781 while (it.hasNext()) {
9782 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009783 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 + ": hasBound=" + ibr.hasBound);
9785 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9786 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009787 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788 updateOomAdjLocked(r.app);
9789 ibr.hasBound = false;
9790 r.app.thread.scheduleUnbindService(r,
9791 ibr.intent.getIntent());
9792 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009793 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794 + r.shortName, e);
9795 serviceDoneExecutingLocked(r, true);
9796 }
9797 }
9798 }
9799 }
9800
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009801 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009802 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009803 System.identityHashCode(r), r.shortName,
9804 (r.app != null) ? r.app.pid : -1);
9805
9806 mServices.remove(r.name);
9807 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009808 r.totalRestartCount = 0;
9809 unscheduleServiceRestartLocked(r);
9810
9811 // Also make sure it is not on the pending list.
9812 int N = mPendingServices.size();
9813 for (int i=0; i<N; i++) {
9814 if (mPendingServices.get(i) == r) {
9815 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009816 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009817 i--;
9818 N--;
9819 }
9820 }
9821
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009822 r.cancelNotification();
9823 r.isForeground = false;
9824 r.foregroundId = 0;
9825 r.foregroundNoti = null;
9826
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009827 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009828 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009829 r.pendingStarts.clear();
9830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009831 if (r.app != null) {
9832 synchronized (r.stats.getBatteryStats()) {
9833 r.stats.stopLaunchedLocked();
9834 }
9835 r.app.services.remove(r);
9836 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009837 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009838 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839 mStoppingServices.add(r);
9840 updateOomAdjLocked(r.app);
9841 r.app.thread.scheduleStopService(r);
9842 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009843 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009844 + r.shortName, e);
9845 serviceDoneExecutingLocked(r, true);
9846 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009847 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009848 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009849 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009850 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009851 }
9852 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009853 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009854 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009855 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -08009856
9857 if (r.bindings.size() > 0) {
9858 r.bindings.clear();
9859 }
9860
9861 if (r.restarter instanceof ServiceRestarter) {
9862 ((ServiceRestarter)r.restarter).setService(null);
9863 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009864 }
9865
9866 ComponentName startServiceLocked(IApplicationThread caller,
9867 Intent service, String resolvedType,
9868 int callingPid, int callingUid) {
9869 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009870 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009871 + " type=" + resolvedType + " args=" + service.getExtras());
9872
9873 if (caller != null) {
9874 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9875 if (callerApp == null) {
9876 throw new SecurityException(
9877 "Unable to find app for caller " + caller
9878 + " (pid=" + Binder.getCallingPid()
9879 + ") when starting service " + service);
9880 }
9881 }
9882
9883 ServiceLookupResult res =
9884 retrieveServiceLocked(service, resolvedType,
9885 callingPid, callingUid);
9886 if (res == null) {
9887 return null;
9888 }
9889 if (res.record == null) {
9890 return new ComponentName("!", res.permission != null
9891 ? res.permission : "private to package");
9892 }
9893 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009894 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9895 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009896 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009897 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009898 }
9899 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009900 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009901 r.lastStartId++;
9902 if (r.lastStartId < 1) {
9903 r.lastStartId = 1;
9904 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009905 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9906 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009907 r.lastActivity = SystemClock.uptimeMillis();
9908 synchronized (r.stats.getBatteryStats()) {
9909 r.stats.startRunningLocked();
9910 }
9911 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9912 return new ComponentName("!", "Service process is bad");
9913 }
9914 return r.name;
9915 }
9916 }
9917
9918 public ComponentName startService(IApplicationThread caller, Intent service,
9919 String resolvedType) {
9920 // Refuse possible leaked file descriptors
9921 if (service != null && service.hasFileDescriptors() == true) {
9922 throw new IllegalArgumentException("File descriptors passed in Intent");
9923 }
9924
9925 synchronized(this) {
9926 final int callingPid = Binder.getCallingPid();
9927 final int callingUid = Binder.getCallingUid();
9928 final long origId = Binder.clearCallingIdentity();
9929 ComponentName res = startServiceLocked(caller, service,
9930 resolvedType, callingPid, callingUid);
9931 Binder.restoreCallingIdentity(origId);
9932 return res;
9933 }
9934 }
9935
9936 ComponentName startServiceInPackage(int uid,
9937 Intent service, String resolvedType) {
9938 synchronized(this) {
9939 final long origId = Binder.clearCallingIdentity();
9940 ComponentName res = startServiceLocked(null, service,
9941 resolvedType, -1, uid);
9942 Binder.restoreCallingIdentity(origId);
9943 return res;
9944 }
9945 }
9946
9947 public int stopService(IApplicationThread caller, Intent service,
9948 String resolvedType) {
9949 // Refuse possible leaked file descriptors
9950 if (service != null && service.hasFileDescriptors() == true) {
9951 throw new IllegalArgumentException("File descriptors passed in Intent");
9952 }
9953
9954 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009955 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009956 + " type=" + resolvedType);
9957
9958 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9959 if (caller != null && callerApp == null) {
9960 throw new SecurityException(
9961 "Unable to find app for caller " + caller
9962 + " (pid=" + Binder.getCallingPid()
9963 + ") when stopping service " + service);
9964 }
9965
9966 // If this service is active, make sure it is stopped.
9967 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9968 if (r != null) {
9969 if (r.record != null) {
9970 synchronized (r.record.stats.getBatteryStats()) {
9971 r.record.stats.stopRunningLocked();
9972 }
9973 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009974 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009975 final long origId = Binder.clearCallingIdentity();
9976 bringDownServiceLocked(r.record, false);
9977 Binder.restoreCallingIdentity(origId);
9978 return 1;
9979 }
9980 return -1;
9981 }
9982 }
9983
9984 return 0;
9985 }
9986
9987 public IBinder peekService(Intent service, String resolvedType) {
9988 // Refuse possible leaked file descriptors
9989 if (service != null && service.hasFileDescriptors() == true) {
9990 throw new IllegalArgumentException("File descriptors passed in Intent");
9991 }
9992
9993 IBinder ret = null;
9994
9995 synchronized(this) {
9996 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9997
9998 if (r != null) {
9999 // r.record is null if findServiceLocked() failed the caller permission check
10000 if (r.record == null) {
10001 throw new SecurityException(
10002 "Permission Denial: Accessing service " + r.record.name
10003 + " from pid=" + Binder.getCallingPid()
10004 + ", uid=" + Binder.getCallingUid()
10005 + " requires " + r.permission);
10006 }
10007 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10008 if (ib != null) {
10009 ret = ib.binder;
10010 }
10011 }
10012 }
10013
10014 return ret;
10015 }
10016
10017 public boolean stopServiceToken(ComponentName className, IBinder token,
10018 int startId) {
10019 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010020 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010021 + " " + token + " startId=" + startId);
10022 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010023 if (r != null) {
10024 if (startId >= 0) {
10025 // Asked to only stop if done with all work. Note that
10026 // to avoid leaks, we will take this as dropping all
10027 // start items up to and including this one.
10028 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10029 if (si != null) {
10030 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010031 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10032 cur.removeUriPermissionsLocked();
10033 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010034 break;
10035 }
10036 }
10037 }
10038
10039 if (r.lastStartId != startId) {
10040 return false;
10041 }
10042
10043 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010044 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010045 + " is last, but have " + r.deliveredStarts.size()
10046 + " remaining args");
10047 }
10048 }
10049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010050 synchronized (r.stats.getBatteryStats()) {
10051 r.stats.stopRunningLocked();
10052 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010053 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010054 }
10055 final long origId = Binder.clearCallingIdentity();
10056 bringDownServiceLocked(r, false);
10057 Binder.restoreCallingIdentity(origId);
10058 return true;
10059 }
10060 }
10061 return false;
10062 }
10063
10064 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010065 int id, Notification notification, boolean removeNotification) {
10066 final long origId = Binder.clearCallingIdentity();
10067 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010068 synchronized(this) {
10069 ServiceRecord r = findServiceLocked(className, token);
10070 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010071 if (id != 0) {
10072 if (notification == null) {
10073 throw new IllegalArgumentException("null notification");
10074 }
10075 if (r.foregroundId != id) {
10076 r.cancelNotification();
10077 r.foregroundId = id;
10078 }
10079 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10080 r.foregroundNoti = notification;
10081 r.isForeground = true;
10082 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010083 if (r.app != null) {
10084 updateServiceForegroundLocked(r.app, true);
10085 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010086 } else {
10087 if (r.isForeground) {
10088 r.isForeground = false;
10089 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010090 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010091 updateServiceForegroundLocked(r.app, true);
10092 }
10093 }
10094 if (removeNotification) {
10095 r.cancelNotification();
10096 r.foregroundId = 0;
10097 r.foregroundNoti = null;
10098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010099 }
10100 }
10101 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010102 } finally {
10103 Binder.restoreCallingIdentity(origId);
10104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010105 }
10106
10107 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10108 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010109 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010110 if (sr.isForeground) {
10111 anyForeground = true;
10112 break;
10113 }
10114 }
10115 if (anyForeground != proc.foregroundServices) {
10116 proc.foregroundServices = anyForeground;
10117 if (oomAdj) {
10118 updateOomAdjLocked();
10119 }
10120 }
10121 }
10122
10123 public int bindService(IApplicationThread caller, IBinder token,
10124 Intent service, String resolvedType,
10125 IServiceConnection connection, int flags) {
10126 // Refuse possible leaked file descriptors
10127 if (service != null && service.hasFileDescriptors() == true) {
10128 throw new IllegalArgumentException("File descriptors passed in Intent");
10129 }
10130
10131 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010132 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010133 + " type=" + resolvedType + " conn=" + connection.asBinder()
10134 + " flags=0x" + Integer.toHexString(flags));
10135 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10136 if (callerApp == null) {
10137 throw new SecurityException(
10138 "Unable to find app for caller " + caller
10139 + " (pid=" + Binder.getCallingPid()
10140 + ") when binding service " + service);
10141 }
10142
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010143 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010144 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010145 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010146 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010147 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010148 return 0;
10149 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010150 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010151 }
10152
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010153 int clientLabel = 0;
10154 PendingIntent clientIntent = null;
10155
10156 if (callerApp.info.uid == Process.SYSTEM_UID) {
10157 // Hacky kind of thing -- allow system stuff to tell us
10158 // what they are, so we can report this elsewhere for
10159 // others to know why certain services are running.
10160 try {
10161 clientIntent = (PendingIntent)service.getParcelableExtra(
10162 Intent.EXTRA_CLIENT_INTENT);
10163 } catch (RuntimeException e) {
10164 }
10165 if (clientIntent != null) {
10166 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10167 if (clientLabel != 0) {
10168 // There are no useful extras in the intent, trash them.
10169 // System code calling with this stuff just needs to know
10170 // this will happen.
10171 service = service.cloneFilter();
10172 }
10173 }
10174 }
10175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010176 ServiceLookupResult res =
10177 retrieveServiceLocked(service, resolvedType,
10178 Binder.getCallingPid(), Binder.getCallingUid());
10179 if (res == null) {
10180 return 0;
10181 }
10182 if (res.record == null) {
10183 return -1;
10184 }
10185 ServiceRecord s = res.record;
10186
10187 final long origId = Binder.clearCallingIdentity();
10188
10189 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010190 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010191 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010192 }
10193
10194 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10195 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010196 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010197
10198 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010199 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10200 if (clist == null) {
10201 clist = new ArrayList<ConnectionRecord>();
10202 s.connections.put(binder, clist);
10203 }
10204 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010205 b.connections.add(c);
10206 if (activity != null) {
10207 if (activity.connections == null) {
10208 activity.connections = new HashSet<ConnectionRecord>();
10209 }
10210 activity.connections.add(c);
10211 }
10212 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010213 clist = mServiceConnections.get(binder);
10214 if (clist == null) {
10215 clist = new ArrayList<ConnectionRecord>();
10216 mServiceConnections.put(binder, clist);
10217 }
10218 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010219
10220 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10221 s.lastActivity = SystemClock.uptimeMillis();
10222 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10223 return 0;
10224 }
10225 }
10226
10227 if (s.app != null) {
10228 // This could have made the service more important.
10229 updateOomAdjLocked(s.app);
10230 }
10231
Joe Onorato8a9b2202010-02-26 18:56:32 -080010232 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010233 + ": received=" + b.intent.received
10234 + " apps=" + b.intent.apps.size()
10235 + " doRebind=" + b.intent.doRebind);
10236
10237 if (s.app != null && b.intent.received) {
10238 // Service is already running, so we can immediately
10239 // publish the connection.
10240 try {
10241 c.conn.connected(s.name, b.intent.binder);
10242 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010243 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010244 + " to connection " + c.conn.asBinder()
10245 + " (in " + c.binding.client.processName + ")", e);
10246 }
10247
10248 // If this is the first app connected back to this binding,
10249 // and the service had previously asked to be told when
10250 // rebound, then do so.
10251 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10252 requestServiceBindingLocked(s, b.intent, true);
10253 }
10254 } else if (!b.intent.requested) {
10255 requestServiceBindingLocked(s, b.intent, false);
10256 }
10257
10258 Binder.restoreCallingIdentity(origId);
10259 }
10260
10261 return 1;
10262 }
10263
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010264 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010265 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 IBinder binder = c.conn.asBinder();
10267 AppBindRecord b = c.binding;
10268 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010269 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10270 if (clist != null) {
10271 clist.remove(c);
10272 if (clist.size() == 0) {
10273 s.connections.remove(binder);
10274 }
10275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010276 b.connections.remove(c);
10277 if (c.activity != null && c.activity != skipAct) {
10278 if (c.activity.connections != null) {
10279 c.activity.connections.remove(c);
10280 }
10281 }
10282 if (b.client != skipApp) {
10283 b.client.connections.remove(c);
10284 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010285 clist = mServiceConnections.get(binder);
10286 if (clist != null) {
10287 clist.remove(c);
10288 if (clist.size() == 0) {
10289 mServiceConnections.remove(binder);
10290 }
10291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292
10293 if (b.connections.size() == 0) {
10294 b.intent.apps.remove(b.client);
10295 }
10296
Joe Onorato8a9b2202010-02-26 18:56:32 -080010297 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010298 + ": shouldUnbind=" + b.intent.hasBound);
10299 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10300 && b.intent.hasBound) {
10301 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010302 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010303 updateOomAdjLocked(s.app);
10304 b.intent.hasBound = false;
10305 // Assume the client doesn't want to know about a rebind;
10306 // we will deal with that later if it asks for one.
10307 b.intent.doRebind = false;
10308 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10309 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010310 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010311 serviceDoneExecutingLocked(s, true);
10312 }
10313 }
10314
10315 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10316 bringDownServiceLocked(s, false);
10317 }
10318 }
10319
10320 public boolean unbindService(IServiceConnection connection) {
10321 synchronized (this) {
10322 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010323 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010324 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10325 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010326 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327 + connection.asBinder());
10328 return false;
10329 }
10330
10331 final long origId = Binder.clearCallingIdentity();
10332
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010333 while (clist.size() > 0) {
10334 ConnectionRecord r = clist.get(0);
10335 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010336
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010337 if (r.binding.service.app != null) {
10338 // This could have made the service less important.
10339 updateOomAdjLocked(r.binding.service.app);
10340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010341 }
10342
10343 Binder.restoreCallingIdentity(origId);
10344 }
10345
10346 return true;
10347 }
10348
10349 public void publishService(IBinder token, Intent intent, IBinder service) {
10350 // Refuse possible leaked file descriptors
10351 if (intent != null && intent.hasFileDescriptors() == true) {
10352 throw new IllegalArgumentException("File descriptors passed in Intent");
10353 }
10354
10355 synchronized(this) {
10356 if (!(token instanceof ServiceRecord)) {
10357 throw new IllegalArgumentException("Invalid service token");
10358 }
10359 ServiceRecord r = (ServiceRecord)token;
10360
10361 final long origId = Binder.clearCallingIdentity();
10362
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010363 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010364 + " " + intent + ": " + service);
10365 if (r != null) {
10366 Intent.FilterComparison filter
10367 = new Intent.FilterComparison(intent);
10368 IntentBindRecord b = r.bindings.get(filter);
10369 if (b != null && !b.received) {
10370 b.binder = service;
10371 b.requested = true;
10372 b.received = true;
10373 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010374 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010375 = r.connections.values().iterator();
10376 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010377 ArrayList<ConnectionRecord> clist = it.next();
10378 for (int i=0; i<clist.size(); i++) {
10379 ConnectionRecord c = clist.get(i);
10380 if (!filter.equals(c.binding.intent.intent)) {
10381 if (DEBUG_SERVICE) Slog.v(
10382 TAG, "Not publishing to: " + c);
10383 if (DEBUG_SERVICE) Slog.v(
10384 TAG, "Bound intent: " + c.binding.intent.intent);
10385 if (DEBUG_SERVICE) Slog.v(
10386 TAG, "Published intent: " + intent);
10387 continue;
10388 }
10389 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10390 try {
10391 c.conn.connected(r.name, service);
10392 } catch (Exception e) {
10393 Slog.w(TAG, "Failure sending service " + r.name +
10394 " to connection " + c.conn.asBinder() +
10395 " (in " + c.binding.client.processName + ")", e);
10396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010397 }
10398 }
10399 }
10400 }
10401
10402 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10403
10404 Binder.restoreCallingIdentity(origId);
10405 }
10406 }
10407 }
10408
10409 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10410 // Refuse possible leaked file descriptors
10411 if (intent != null && intent.hasFileDescriptors() == true) {
10412 throw new IllegalArgumentException("File descriptors passed in Intent");
10413 }
10414
10415 synchronized(this) {
10416 if (!(token instanceof ServiceRecord)) {
10417 throw new IllegalArgumentException("Invalid service token");
10418 }
10419 ServiceRecord r = (ServiceRecord)token;
10420
10421 final long origId = Binder.clearCallingIdentity();
10422
10423 if (r != null) {
10424 Intent.FilterComparison filter
10425 = new Intent.FilterComparison(intent);
10426 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010427 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010428 + " at " + b + ": apps="
10429 + (b != null ? b.apps.size() : 0));
10430 if (b != null) {
10431 if (b.apps.size() > 0) {
10432 // Applications have already bound since the last
10433 // unbind, so just rebind right here.
10434 requestServiceBindingLocked(r, b, true);
10435 } else {
10436 // Note to tell the service the next time there is
10437 // a new client.
10438 b.doRebind = true;
10439 }
10440 }
10441
10442 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10443
10444 Binder.restoreCallingIdentity(origId);
10445 }
10446 }
10447 }
10448
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010449 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010450 synchronized(this) {
10451 if (!(token instanceof ServiceRecord)) {
10452 throw new IllegalArgumentException("Invalid service token");
10453 }
10454 ServiceRecord r = (ServiceRecord)token;
10455 boolean inStopping = mStoppingServices.contains(token);
10456 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010457 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010458 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010459 + " with incorrect token: given " + token
10460 + ", expected " + r);
10461 return;
10462 }
10463
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010464 if (type == 1) {
10465 // This is a call from a service start... take care of
10466 // book-keeping.
10467 r.callStart = true;
10468 switch (res) {
10469 case Service.START_STICKY_COMPATIBILITY:
10470 case Service.START_STICKY: {
10471 // We are done with the associated start arguments.
10472 r.findDeliveredStart(startId, true);
10473 // Don't stop if killed.
10474 r.stopIfKilled = false;
10475 break;
10476 }
10477 case Service.START_NOT_STICKY: {
10478 // We are done with the associated start arguments.
10479 r.findDeliveredStart(startId, true);
10480 if (r.lastStartId == startId) {
10481 // There is no more work, and this service
10482 // doesn't want to hang around if killed.
10483 r.stopIfKilled = true;
10484 }
10485 break;
10486 }
10487 case Service.START_REDELIVER_INTENT: {
10488 // We'll keep this item until they explicitly
10489 // call stop for it, but keep track of the fact
10490 // that it was delivered.
10491 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10492 if (si != null) {
10493 si.deliveryCount = 0;
10494 si.doneExecutingCount++;
10495 // Don't stop if killed.
10496 r.stopIfKilled = true;
10497 }
10498 break;
10499 }
10500 default:
10501 throw new IllegalArgumentException(
10502 "Unknown service start result: " + res);
10503 }
10504 if (res == Service.START_STICKY_COMPATIBILITY) {
10505 r.callStart = false;
10506 }
10507 }
10508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010509 final long origId = Binder.clearCallingIdentity();
10510 serviceDoneExecutingLocked(r, inStopping);
10511 Binder.restoreCallingIdentity(origId);
10512 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010513 Slog.w(TAG, "Done executing unknown service from pid "
10514 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010515 }
10516 }
10517 }
10518
10519 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010520 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10521 + ": nesting=" + r.executeNesting
10522 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010523 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010524 r.executeNesting--;
10525 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010526 if (DEBUG_SERVICE) Slog.v(TAG,
10527 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528 r.app.executingServices.remove(r);
10529 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010530 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10531 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010532 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10533 }
10534 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010535 if (DEBUG_SERVICE) Slog.v(TAG,
10536 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010537 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010538 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 }
10540 updateOomAdjLocked(r.app);
10541 }
10542 }
10543
10544 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010545 String anrMessage = null;
10546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010547 synchronized(this) {
10548 if (proc.executingServices.size() == 0 || proc.thread == null) {
10549 return;
10550 }
10551 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10552 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10553 ServiceRecord timeout = null;
10554 long nextTime = 0;
10555 while (it.hasNext()) {
10556 ServiceRecord sr = it.next();
10557 if (sr.executingStart < maxTime) {
10558 timeout = sr;
10559 break;
10560 }
10561 if (sr.executingStart > nextTime) {
10562 nextTime = sr.executingStart;
10563 }
10564 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010565 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010566 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010567 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568 } else {
10569 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10570 msg.obj = proc;
10571 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10572 }
10573 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010574
10575 if (anrMessage != null) {
10576 appNotResponding(proc, null, null, anrMessage);
10577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010578 }
10579
10580 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010581 // BACKUP AND RESTORE
10582 // =========================================================
10583
10584 // Cause the target app to be launched if necessary and its backup agent
10585 // instantiated. The backup agent will invoke backupAgentCreated() on the
10586 // activity manager to announce its creation.
10587 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010588 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010589 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10590
10591 synchronized(this) {
10592 // !!! TODO: currently no check here that we're already bound
10593 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10594 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10595 synchronized (stats) {
10596 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10597 }
10598
Dianne Hackborne7f97212011-02-24 14:40:20 -080010599 // Backup agent is now in use, its package can't be stopped.
10600 try {
10601 AppGlobals.getPackageManager().setPackageStoppedState(
10602 app.packageName, false);
10603 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010604 } catch (IllegalArgumentException e) {
10605 Slog.w(TAG, "Failed trying to unstop package "
10606 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010607 }
10608
Christopher Tate181fafa2009-05-14 11:12:14 -070010609 BackupRecord r = new BackupRecord(ss, app, backupMode);
10610 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10611 // startProcessLocked() returns existing proc's record if it's already running
10612 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010613 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010614 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010615 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010616 return false;
10617 }
10618
10619 r.app = proc;
10620 mBackupTarget = r;
10621 mBackupAppName = app.packageName;
10622
Christopher Tate6fa95972009-06-05 18:43:55 -070010623 // Try not to kill the process during backup
10624 updateOomAdjLocked(proc);
10625
Christopher Tate181fafa2009-05-14 11:12:14 -070010626 // If the process is already attached, schedule the creation of the backup agent now.
10627 // If it is not yet live, this will be done when it attaches to the framework.
10628 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010629 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010630 try {
10631 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10632 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010633 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010634 }
10635 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010636 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010637 }
10638 // Invariants: at this point, the target app process exists and the application
10639 // is either already running or in the process of coming up. mBackupTarget and
10640 // mBackupAppName describe the app, so that when it binds back to the AM we
10641 // know that it's scheduled for a backup-agent operation.
10642 }
10643
10644 return true;
10645 }
10646
10647 // A backup agent has just come up
10648 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010649 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010650 + " = " + agent);
10651
10652 synchronized(this) {
10653 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010654 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010655 return;
10656 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010657 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010658
Dianne Hackborn06740692010-09-22 22:46:21 -070010659 long oldIdent = Binder.clearCallingIdentity();
10660 try {
10661 IBackupManager bm = IBackupManager.Stub.asInterface(
10662 ServiceManager.getService(Context.BACKUP_SERVICE));
10663 bm.agentConnected(agentPackageName, agent);
10664 } catch (RemoteException e) {
10665 // can't happen; the backup manager service is local
10666 } catch (Exception e) {
10667 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10668 e.printStackTrace();
10669 } finally {
10670 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010671 }
10672 }
10673
10674 // done with this agent
10675 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010676 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010677 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010678 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010679 return;
10680 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010681
10682 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010683 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010684 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010685 return;
10686 }
10687
Christopher Tate181fafa2009-05-14 11:12:14 -070010688 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010689 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010690 return;
10691 }
10692
Christopher Tate6fa95972009-06-05 18:43:55 -070010693 ProcessRecord proc = mBackupTarget.app;
10694 mBackupTarget = null;
10695 mBackupAppName = null;
10696
10697 // Not backing this app up any more; reset its OOM adjustment
10698 updateOomAdjLocked(proc);
10699
Christopher Tatec7b31e32009-06-10 15:49:30 -070010700 // If the app crashed during backup, 'thread' will be null here
10701 if (proc.thread != null) {
10702 try {
10703 proc.thread.scheduleDestroyBackupAgent(appInfo);
10704 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010705 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010706 e.printStackTrace();
10707 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010708 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010709 }
10710 }
10711 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010712 // BROADCASTS
10713 // =========================================================
10714
Josh Bartel7f208742010-02-25 11:01:44 -060010715 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010716 List cur) {
10717 final ContentResolver resolver = mContext.getContentResolver();
10718 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10719 if (list == null) {
10720 return cur;
10721 }
10722 int N = list.size();
10723 for (int i=0; i<N; i++) {
10724 Intent intent = list.get(i);
10725 if (filter.match(resolver, intent, true, TAG) >= 0) {
10726 if (cur == null) {
10727 cur = new ArrayList<Intent>();
10728 }
10729 cur.add(intent);
10730 }
10731 }
10732 return cur;
10733 }
10734
10735 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010736 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010737 + mBroadcastsScheduled);
10738
10739 if (mBroadcastsScheduled) {
10740 return;
10741 }
10742 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10743 mBroadcastsScheduled = true;
10744 }
10745
10746 public Intent registerReceiver(IApplicationThread caller,
10747 IIntentReceiver receiver, IntentFilter filter, String permission) {
10748 synchronized(this) {
10749 ProcessRecord callerApp = null;
10750 if (caller != null) {
10751 callerApp = getRecordForAppLocked(caller);
10752 if (callerApp == null) {
10753 throw new SecurityException(
10754 "Unable to find app for caller " + caller
10755 + " (pid=" + Binder.getCallingPid()
10756 + ") when registering receiver " + receiver);
10757 }
10758 }
10759
10760 List allSticky = null;
10761
10762 // Look for any matching sticky broadcasts...
10763 Iterator actions = filter.actionsIterator();
10764 if (actions != null) {
10765 while (actions.hasNext()) {
10766 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010767 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010768 }
10769 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010770 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010771 }
10772
10773 // The first sticky in the list is returned directly back to
10774 // the client.
10775 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10776
Joe Onorato8a9b2202010-02-26 18:56:32 -080010777 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010778 + ": " + sticky);
10779
10780 if (receiver == null) {
10781 return sticky;
10782 }
10783
10784 ReceiverList rl
10785 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10786 if (rl == null) {
10787 rl = new ReceiverList(this, callerApp,
10788 Binder.getCallingPid(),
10789 Binder.getCallingUid(), receiver);
10790 if (rl.app != null) {
10791 rl.app.receivers.add(rl);
10792 } else {
10793 try {
10794 receiver.asBinder().linkToDeath(rl, 0);
10795 } catch (RemoteException e) {
10796 return sticky;
10797 }
10798 rl.linkedToDeath = true;
10799 }
10800 mRegisteredReceivers.put(receiver.asBinder(), rl);
10801 }
10802 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10803 rl.add(bf);
10804 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010805 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010806 }
10807 mReceiverResolver.addFilter(bf);
10808
10809 // Enqueue broadcasts for all existing stickies that match
10810 // this filter.
10811 if (allSticky != null) {
10812 ArrayList receivers = new ArrayList();
10813 receivers.add(bf);
10814
10815 int N = allSticky.size();
10816 for (int i=0; i<N; i++) {
10817 Intent intent = (Intent)allSticky.get(i);
10818 BroadcastRecord r = new BroadcastRecord(intent, null,
10819 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010820 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010821 if (mParallelBroadcasts.size() == 0) {
10822 scheduleBroadcastsLocked();
10823 }
10824 mParallelBroadcasts.add(r);
10825 }
10826 }
10827
10828 return sticky;
10829 }
10830 }
10831
10832 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010833 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010834
10835 boolean doNext = false;
10836
10837 synchronized(this) {
10838 ReceiverList rl
10839 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10840 if (rl != null) {
10841 if (rl.curBroadcast != null) {
10842 BroadcastRecord r = rl.curBroadcast;
10843 doNext = finishReceiverLocked(
10844 receiver.asBinder(), r.resultCode, r.resultData,
10845 r.resultExtras, r.resultAbort, true);
10846 }
10847
10848 if (rl.app != null) {
10849 rl.app.receivers.remove(rl);
10850 }
10851 removeReceiverLocked(rl);
10852 if (rl.linkedToDeath) {
10853 rl.linkedToDeath = false;
10854 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10855 }
10856 }
10857 }
10858
10859 if (!doNext) {
10860 return;
10861 }
10862
10863 final long origId = Binder.clearCallingIdentity();
10864 processNextBroadcast(false);
10865 trimApplications();
10866 Binder.restoreCallingIdentity(origId);
10867 }
10868
10869 void removeReceiverLocked(ReceiverList rl) {
10870 mRegisteredReceivers.remove(rl.receiver.asBinder());
10871 int N = rl.size();
10872 for (int i=0; i<N; i++) {
10873 mReceiverResolver.removeFilter(rl.get(i));
10874 }
10875 }
10876
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010877 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10878 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10879 ProcessRecord r = mLruProcesses.get(i);
10880 if (r.thread != null) {
10881 try {
10882 r.thread.dispatchPackageBroadcast(cmd, packages);
10883 } catch (RemoteException ex) {
10884 }
10885 }
10886 }
10887 }
10888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010889 private final int broadcastIntentLocked(ProcessRecord callerApp,
10890 String callerPackage, Intent intent, String resolvedType,
10891 IIntentReceiver resultTo, int resultCode, String resultData,
10892 Bundle map, String requiredPermission,
10893 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10894 intent = new Intent(intent);
10895
Dianne Hackborne7f97212011-02-24 14:40:20 -080010896 // By default broadcasts do not go to stopped apps.
10897 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
10898
Joe Onorato8a9b2202010-02-26 18:56:32 -080010899 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010900 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10901 + " ordered=" + ordered);
10902 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010903 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010904 }
10905
10906 // Handle special intents: if this broadcast is from the package
10907 // manager about a package being removed, we need to remove all of
10908 // its activities from the history stack.
10909 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10910 intent.getAction());
10911 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10912 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010913 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010914 || uidRemoved) {
10915 if (checkComponentPermission(
10916 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010917 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010918 == PackageManager.PERMISSION_GRANTED) {
10919 if (uidRemoved) {
10920 final Bundle intentExtras = intent.getExtras();
10921 final int uid = intentExtras != null
10922 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10923 if (uid >= 0) {
10924 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10925 synchronized (bs) {
10926 bs.removeUidStatsLocked(uid);
10927 }
10928 }
10929 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010930 // If resources are unvailble just force stop all
10931 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010932 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010933 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10934 if (list != null && (list.length > 0)) {
10935 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010936 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010937 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010938 sendPackageBroadcastLocked(
10939 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010940 }
10941 } else {
10942 Uri data = intent.getData();
10943 String ssp;
10944 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10945 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10946 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010947 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010948 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010949 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10950 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10951 new String[] {ssp});
10952 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010953 }
10954 }
10955 }
10956 } else {
10957 String msg = "Permission Denial: " + intent.getAction()
10958 + " broadcast from " + callerPackage + " (pid=" + callingPid
10959 + ", uid=" + callingUid + ")"
10960 + " requires "
10961 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010962 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 throw new SecurityException(msg);
10964 }
10965 }
10966
10967 /*
10968 * If this is the time zone changed action, queue up a message that will reset the timezone
10969 * of all currently running processes. This message will get queued up before the broadcast
10970 * happens.
10971 */
10972 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10973 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10974 }
10975
Robert Greenwalt03595d02010-11-02 14:08:23 -070010976 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10977 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10978 }
10979
Robert Greenwalt434203a2010-10-11 16:00:27 -070010980 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10981 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10982 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10983 }
10984
Dianne Hackborn854060af2009-07-09 18:14:31 -070010985 /*
10986 * Prevent non-system code (defined here to be non-persistent
10987 * processes) from sending protected broadcasts.
10988 */
10989 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10990 || callingUid == Process.SHELL_UID || callingUid == 0) {
10991 // Always okay.
10992 } else if (callerApp == null || !callerApp.persistent) {
10993 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010994 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010995 intent.getAction())) {
10996 String msg = "Permission Denial: not allowed to send broadcast "
10997 + intent.getAction() + " from pid="
10998 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010999 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011000 throw new SecurityException(msg);
11001 }
11002 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011003 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011004 return BROADCAST_SUCCESS;
11005 }
11006 }
11007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 // Add to the sticky list if requested.
11009 if (sticky) {
11010 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11011 callingPid, callingUid)
11012 != PackageManager.PERMISSION_GRANTED) {
11013 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11014 + callingPid + ", uid=" + callingUid
11015 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011016 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017 throw new SecurityException(msg);
11018 }
11019 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011020 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011021 + " and enforce permission " + requiredPermission);
11022 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11023 }
11024 if (intent.getComponent() != null) {
11025 throw new SecurityException(
11026 "Sticky broadcasts can't target a specific component");
11027 }
11028 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11029 if (list == null) {
11030 list = new ArrayList<Intent>();
11031 mStickyBroadcasts.put(intent.getAction(), list);
11032 }
11033 int N = list.size();
11034 int i;
11035 for (i=0; i<N; i++) {
11036 if (intent.filterEquals(list.get(i))) {
11037 // This sticky already exists, replace it.
11038 list.set(i, new Intent(intent));
11039 break;
11040 }
11041 }
11042 if (i >= N) {
11043 list.add(new Intent(intent));
11044 }
11045 }
11046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011047 // Figure out who all will receive this broadcast.
11048 List receivers = null;
11049 List<BroadcastFilter> registeredReceivers = null;
11050 try {
11051 if (intent.getComponent() != null) {
11052 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011053 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011054 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011055 if (ai != null) {
11056 receivers = new ArrayList();
11057 ResolveInfo ri = new ResolveInfo();
11058 ri.activityInfo = ai;
11059 receivers.add(ri);
11060 }
11061 } else {
11062 // Need to resolve the intent to interested receivers...
11063 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11064 == 0) {
11065 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011066 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011067 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011068 }
Mihai Preda074edef2009-05-18 17:13:31 +020011069 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 }
11071 } catch (RemoteException ex) {
11072 // pm is in same process, this will never happen.
11073 }
11074
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011075 final boolean replacePending =
11076 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11077
Joe Onorato8a9b2202010-02-26 18:56:32 -080011078 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011079 + " replacePending=" + replacePending);
11080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011081 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11082 if (!ordered && NR > 0) {
11083 // If we are not serializing this broadcast, then send the
11084 // registered receivers separately so they don't wait for the
11085 // components to be launched.
11086 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11087 callerPackage, callingPid, callingUid, requiredPermission,
11088 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011089 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011090 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 TAG, "Enqueueing parallel broadcast " + r
11092 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011093 boolean replaced = false;
11094 if (replacePending) {
11095 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11096 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011097 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011098 "***** DROPPING PARALLEL: " + intent);
11099 mParallelBroadcasts.set(i, r);
11100 replaced = true;
11101 break;
11102 }
11103 }
11104 }
11105 if (!replaced) {
11106 mParallelBroadcasts.add(r);
11107 scheduleBroadcastsLocked();
11108 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 registeredReceivers = null;
11110 NR = 0;
11111 }
11112
11113 // Merge into one list.
11114 int ir = 0;
11115 if (receivers != null) {
11116 // A special case for PACKAGE_ADDED: do not allow the package
11117 // being added to see this broadcast. This prevents them from
11118 // using this as a back door to get run as soon as they are
11119 // installed. Maybe in the future we want to have a special install
11120 // broadcast or such for apps, but we'd like to deliberately make
11121 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011122 String skipPackages[] = null;
11123 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11124 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11125 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
11126 Uri data = intent.getData();
11127 if (data != null) {
11128 String pkgName = data.getSchemeSpecificPart();
11129 if (pkgName != null) {
11130 skipPackages = new String[] { pkgName };
11131 }
11132 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011133 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011134 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011135 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011136 if (skipPackages != null && (skipPackages.length > 0)) {
11137 for (String skipPackage : skipPackages) {
11138 if (skipPackage != null) {
11139 int NT = receivers.size();
11140 for (int it=0; it<NT; it++) {
11141 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11142 if (curt.activityInfo.packageName.equals(skipPackage)) {
11143 receivers.remove(it);
11144 it--;
11145 NT--;
11146 }
11147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011148 }
11149 }
11150 }
11151
11152 int NT = receivers != null ? receivers.size() : 0;
11153 int it = 0;
11154 ResolveInfo curt = null;
11155 BroadcastFilter curr = null;
11156 while (it < NT && ir < NR) {
11157 if (curt == null) {
11158 curt = (ResolveInfo)receivers.get(it);
11159 }
11160 if (curr == null) {
11161 curr = registeredReceivers.get(ir);
11162 }
11163 if (curr.getPriority() >= curt.priority) {
11164 // Insert this broadcast record into the final list.
11165 receivers.add(it, curr);
11166 ir++;
11167 curr = null;
11168 it++;
11169 NT++;
11170 } else {
11171 // Skip to the next ResolveInfo in the final list.
11172 it++;
11173 curt = null;
11174 }
11175 }
11176 }
11177 while (ir < NR) {
11178 if (receivers == null) {
11179 receivers = new ArrayList();
11180 }
11181 receivers.add(registeredReceivers.get(ir));
11182 ir++;
11183 }
11184
11185 if ((receivers != null && receivers.size() > 0)
11186 || resultTo != null) {
11187 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11188 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011189 receivers, resultTo, resultCode, resultData, map, ordered,
11190 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011191 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192 TAG, "Enqueueing ordered broadcast " + r
11193 + ": prev had " + mOrderedBroadcasts.size());
11194 if (DEBUG_BROADCAST) {
11195 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011196 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011197 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011198 boolean replaced = false;
11199 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011200 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011201 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011202 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011203 "***** DROPPING ORDERED: " + intent);
11204 mOrderedBroadcasts.set(i, r);
11205 replaced = true;
11206 break;
11207 }
11208 }
11209 }
11210 if (!replaced) {
11211 mOrderedBroadcasts.add(r);
11212 scheduleBroadcastsLocked();
11213 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 }
11215
11216 return BROADCAST_SUCCESS;
11217 }
11218
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011219 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 // Refuse possible leaked file descriptors
11221 if (intent != null && intent.hasFileDescriptors() == true) {
11222 throw new IllegalArgumentException("File descriptors passed in Intent");
11223 }
11224
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011225 int flags = intent.getFlags();
11226
11227 if (!mProcessesReady) {
11228 // if the caller really truly claims to know what they're doing, go
11229 // ahead and allow the broadcast without launching any receivers
11230 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11231 intent = new Intent(intent);
11232 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11233 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11234 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11235 + " before boot completion");
11236 throw new IllegalStateException("Cannot broadcast before boot completed");
11237 }
11238 }
11239
11240 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11241 throw new IllegalArgumentException(
11242 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11243 }
11244
11245 return intent;
11246 }
11247
11248 public final int broadcastIntent(IApplicationThread caller,
11249 Intent intent, String resolvedType, IIntentReceiver resultTo,
11250 int resultCode, String resultData, Bundle map,
11251 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011252 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011253 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011255 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11256 final int callingPid = Binder.getCallingPid();
11257 final int callingUid = Binder.getCallingUid();
11258 final long origId = Binder.clearCallingIdentity();
11259 int res = broadcastIntentLocked(callerApp,
11260 callerApp != null ? callerApp.info.packageName : null,
11261 intent, resolvedType, resultTo,
11262 resultCode, resultData, map, requiredPermission, serialized,
11263 sticky, callingPid, callingUid);
11264 Binder.restoreCallingIdentity(origId);
11265 return res;
11266 }
11267 }
11268
11269 int broadcastIntentInPackage(String packageName, int uid,
11270 Intent intent, String resolvedType, IIntentReceiver resultTo,
11271 int resultCode, String resultData, Bundle map,
11272 String requiredPermission, boolean serialized, boolean sticky) {
11273 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011274 intent = verifyBroadcastLocked(intent);
11275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011276 final long origId = Binder.clearCallingIdentity();
11277 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11278 resultTo, resultCode, resultData, map, requiredPermission,
11279 serialized, sticky, -1, uid);
11280 Binder.restoreCallingIdentity(origId);
11281 return res;
11282 }
11283 }
11284
11285 public final void unbroadcastIntent(IApplicationThread caller,
11286 Intent intent) {
11287 // Refuse possible leaked file descriptors
11288 if (intent != null && intent.hasFileDescriptors() == true) {
11289 throw new IllegalArgumentException("File descriptors passed in Intent");
11290 }
11291
11292 synchronized(this) {
11293 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11294 != PackageManager.PERMISSION_GRANTED) {
11295 String msg = "Permission Denial: unbroadcastIntent() from pid="
11296 + Binder.getCallingPid()
11297 + ", uid=" + Binder.getCallingUid()
11298 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011299 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011300 throw new SecurityException(msg);
11301 }
11302 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11303 if (list != null) {
11304 int N = list.size();
11305 int i;
11306 for (i=0; i<N; i++) {
11307 if (intent.filterEquals(list.get(i))) {
11308 list.remove(i);
11309 break;
11310 }
11311 }
11312 }
11313 }
11314 }
11315
11316 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11317 String resultData, Bundle resultExtras, boolean resultAbort,
11318 boolean explicit) {
11319 if (mOrderedBroadcasts.size() == 0) {
11320 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011321 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011322 }
11323 return false;
11324 }
11325 BroadcastRecord r = mOrderedBroadcasts.get(0);
11326 if (r.receiver == null) {
11327 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011328 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 }
11330 return false;
11331 }
11332 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011333 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334 return false;
11335 }
11336 int state = r.state;
11337 r.state = r.IDLE;
11338 if (state == r.IDLE) {
11339 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011340 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 }
11342 }
11343 r.receiver = null;
11344 r.intent.setComponent(null);
11345 if (r.curApp != null) {
11346 r.curApp.curReceiver = null;
11347 }
11348 if (r.curFilter != null) {
11349 r.curFilter.receiverList.curBroadcast = null;
11350 }
11351 r.curFilter = null;
11352 r.curApp = null;
11353 r.curComponent = null;
11354 r.curReceiver = null;
11355 mPendingBroadcast = null;
11356
11357 r.resultCode = resultCode;
11358 r.resultData = resultData;
11359 r.resultExtras = resultExtras;
11360 r.resultAbort = resultAbort;
11361
11362 // We will process the next receiver right now if this is finishing
11363 // an app receiver (which is always asynchronous) or after we have
11364 // come back from calling a receiver.
11365 return state == BroadcastRecord.APP_RECEIVE
11366 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11367 }
11368
11369 public void finishReceiver(IBinder who, int resultCode, String resultData,
11370 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011371 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011372
11373 // Refuse possible leaked file descriptors
11374 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11375 throw new IllegalArgumentException("File descriptors passed in Bundle");
11376 }
11377
11378 boolean doNext;
11379
11380 final long origId = Binder.clearCallingIdentity();
11381
11382 synchronized(this) {
11383 doNext = finishReceiverLocked(
11384 who, resultCode, resultData, resultExtras, resultAbort, true);
11385 }
11386
11387 if (doNext) {
11388 processNextBroadcast(false);
11389 }
11390 trimApplications();
11391
11392 Binder.restoreCallingIdentity(origId);
11393 }
11394
Jeff Brown4d94a762010-09-23 11:33:28 -070011395 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011396 if (r.nextReceiver > 0) {
11397 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11398 if (curReceiver instanceof BroadcastFilter) {
11399 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011400 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011401 System.identityHashCode(r),
11402 r.intent.getAction(),
11403 r.nextReceiver - 1,
11404 System.identityHashCode(bf));
11405 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011406 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011407 System.identityHashCode(r),
11408 r.intent.getAction(),
11409 r.nextReceiver - 1,
11410 ((ResolveInfo)curReceiver).toString());
11411 }
11412 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011413 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011414 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011415 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011416 System.identityHashCode(r),
11417 r.intent.getAction(),
11418 r.nextReceiver,
11419 "NONE");
11420 }
11421 }
11422
Jeff Brown4d94a762010-09-23 11:33:28 -070011423 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11424 if (! mPendingBroadcastTimeoutMessage) {
11425 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11426 mHandler.sendMessageAtTime(msg, timeoutTime);
11427 mPendingBroadcastTimeoutMessage = true;
11428 }
11429 }
11430
11431 private final void cancelBroadcastTimeoutLocked() {
11432 if (mPendingBroadcastTimeoutMessage) {
11433 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11434 mPendingBroadcastTimeoutMessage = false;
11435 }
11436 }
11437
11438 private final void broadcastTimeoutLocked(boolean fromMsg) {
11439 if (fromMsg) {
11440 mPendingBroadcastTimeoutMessage = false;
11441 }
11442
11443 if (mOrderedBroadcasts.size() == 0) {
11444 return;
11445 }
11446
11447 long now = SystemClock.uptimeMillis();
11448 BroadcastRecord r = mOrderedBroadcasts.get(0);
11449 if (fromMsg) {
11450 if (mDidDexOpt) {
11451 // Delay timeouts until dexopt finishes.
11452 mDidDexOpt = false;
11453 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11454 setBroadcastTimeoutLocked(timeoutTime);
11455 return;
11456 }
11457 if (! mProcessesReady) {
11458 // Only process broadcast timeouts if the system is ready. That way
11459 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11460 // to do heavy lifting for system up.
11461 return;
11462 }
11463
11464 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11465 if (timeoutTime > now) {
11466 // We can observe premature timeouts because we do not cancel and reset the
11467 // broadcast timeout message after each receiver finishes. Instead, we set up
11468 // an initial timeout then kick it down the road a little further as needed
11469 // when it expires.
11470 if (DEBUG_BROADCAST) Slog.v(TAG,
11471 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11472 + timeoutTime);
11473 setBroadcastTimeoutLocked(timeoutTime);
11474 return;
11475 }
11476 }
11477
11478 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11479 + ", started " + (now - r.receiverTime) + "ms ago");
11480 r.receiverTime = now;
11481 r.anrCount++;
11482
11483 // Current receiver has passed its expiration date.
11484 if (r.nextReceiver <= 0) {
11485 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11486 return;
11487 }
11488
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011489 ProcessRecord app = null;
11490 String anrMessage = null;
11491
Jeff Brown4d94a762010-09-23 11:33:28 -070011492 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11493 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11494 logBroadcastReceiverDiscardLocked(r);
11495 if (curReceiver instanceof BroadcastFilter) {
11496 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11497 if (bf.receiverList.pid != 0
11498 && bf.receiverList.pid != MY_PID) {
11499 synchronized (this.mPidsSelfLocked) {
11500 app = this.mPidsSelfLocked.get(
11501 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011502 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011504 } else {
11505 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011506 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011507
Jeff Brown4d94a762010-09-23 11:33:28 -070011508 if (app != null) {
11509 anrMessage = "Broadcast of " + r.intent.toString();
11510 }
11511
11512 if (mPendingBroadcast == r) {
11513 mPendingBroadcast = null;
11514 }
11515
11516 // Move on to the next receiver.
11517 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11518 r.resultExtras, r.resultAbort, true);
11519 scheduleBroadcastsLocked();
11520
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011521 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011522 // Post the ANR to the handler since we do not want to process ANRs while
11523 // potentially holding our lock.
11524 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011525 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011526 }
11527
11528 private final void processCurBroadcastLocked(BroadcastRecord r,
11529 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011530 if (DEBUG_BROADCAST) Slog.v(TAG,
11531 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011532 if (app.thread == null) {
11533 throw new RemoteException();
11534 }
11535 r.receiver = app.thread.asBinder();
11536 r.curApp = app;
11537 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011538 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011539
11540 // Tell the application to launch this receiver.
11541 r.intent.setComponent(r.curComponent);
11542
11543 boolean started = false;
11544 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011545 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011546 "Delivering to component " + r.curComponent
11547 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011548 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011549 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11550 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011551 if (DEBUG_BROADCAST) Slog.v(TAG,
11552 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011553 started = true;
11554 } finally {
11555 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011556 if (DEBUG_BROADCAST) Slog.v(TAG,
11557 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011558 r.receiver = null;
11559 r.curApp = null;
11560 app.curReceiver = null;
11561 }
11562 }
11563
11564 }
11565
Jeff Brown4d94a762010-09-23 11:33:28 -070011566 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011567 Intent intent, int resultCode, String data, Bundle extras,
11568 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011569 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011570 if (app != null && app.thread != null) {
11571 // If we have an app thread, do the call through that so it is
11572 // correctly ordered with other one-way calls.
11573 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011574 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011575 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011576 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011577 }
11578 }
11579
Jeff Brown4d94a762010-09-23 11:33:28 -070011580 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011581 BroadcastFilter filter, boolean ordered) {
11582 boolean skip = false;
11583 if (filter.requiredPermission != null) {
11584 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011585 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011586 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011587 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011588 + r.intent.toString()
11589 + " from " + r.callerPackage + " (pid="
11590 + r.callingPid + ", uid=" + r.callingUid + ")"
11591 + " requires " + filter.requiredPermission
11592 + " due to registered receiver " + filter);
11593 skip = true;
11594 }
11595 }
11596 if (r.requiredPermission != null) {
11597 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011598 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011599 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011600 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011601 + r.intent.toString()
11602 + " to " + filter.receiverList.app
11603 + " (pid=" + filter.receiverList.pid
11604 + ", uid=" + filter.receiverList.uid + ")"
11605 + " requires " + r.requiredPermission
11606 + " due to sender " + r.callerPackage
11607 + " (uid " + r.callingUid + ")");
11608 skip = true;
11609 }
11610 }
11611
11612 if (!skip) {
11613 // If this is not being sent as an ordered broadcast, then we
11614 // don't want to touch the fields that keep track of the current
11615 // state of ordered broadcasts.
11616 if (ordered) {
11617 r.receiver = filter.receiverList.receiver.asBinder();
11618 r.curFilter = filter;
11619 filter.receiverList.curBroadcast = r;
11620 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011621 if (filter.receiverList.app != null) {
11622 // Bump hosting application to no longer be in background
11623 // scheduling class. Note that we can't do that if there
11624 // isn't an app... but we can only be in that case for
11625 // things that directly call the IActivityManager API, which
11626 // are already core system stuff so don't matter for this.
11627 r.curApp = filter.receiverList.app;
11628 filter.receiverList.app.curReceiver = r;
11629 updateOomAdjLocked();
11630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011631 }
11632 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011633 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011634 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011635 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011636 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011637 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011638 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011639 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011640 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011641 if (ordered) {
11642 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11643 }
11644 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011645 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011646 if (ordered) {
11647 r.receiver = null;
11648 r.curFilter = null;
11649 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011650 if (filter.receiverList.app != null) {
11651 filter.receiverList.app.curReceiver = null;
11652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011653 }
11654 }
11655 }
11656 }
11657
Dianne Hackborn12527f92009-11-11 17:39:50 -080011658 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11659 if (r.callingUid < 0) {
11660 // This was from a registerReceiver() call; ignore it.
11661 return;
11662 }
11663 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11664 MAX_BROADCAST_HISTORY-1);
11665 r.finishTime = SystemClock.uptimeMillis();
11666 mBroadcastHistory[0] = r;
11667 }
11668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011669 private final void processNextBroadcast(boolean fromMsg) {
11670 synchronized(this) {
11671 BroadcastRecord r;
11672
Joe Onorato8a9b2202010-02-26 18:56:32 -080011673 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011674 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011675 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011676
11677 updateCpuStats();
11678
11679 if (fromMsg) {
11680 mBroadcastsScheduled = false;
11681 }
11682
11683 // First, deliver any non-serialized broadcasts right away.
11684 while (mParallelBroadcasts.size() > 0) {
11685 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011686 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011687 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011688 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011689 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011690 for (int i=0; i<N; i++) {
11691 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011692 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011693 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011694 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011695 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011696 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011697 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011698 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011699 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011700 }
11701
11702 // Now take care of the next serialized one...
11703
11704 // If we are waiting for a process to come up to handle the next
11705 // broadcast, then do nothing at this point. Just in case, we
11706 // check that the process we're waiting for still exists.
11707 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011708 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011709 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011710 + mPendingBroadcast.curApp);
11711 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011712
11713 boolean isDead;
11714 synchronized (mPidsSelfLocked) {
11715 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11716 }
11717 if (!isDead) {
11718 // It's still alive, so keep waiting
11719 return;
11720 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011721 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011722 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011723 mPendingBroadcast.state = BroadcastRecord.IDLE;
11724 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011725 mPendingBroadcast = null;
11726 }
11727 }
11728
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011729 boolean looped = false;
11730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731 do {
11732 if (mOrderedBroadcasts.size() == 0) {
11733 // No more broadcasts pending, so all done!
11734 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011735 if (looped) {
11736 // If we had finished the last ordered broadcast, then
11737 // make sure all processes have correct oom and sched
11738 // adjustments.
11739 updateOomAdjLocked();
11740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011741 return;
11742 }
11743 r = mOrderedBroadcasts.get(0);
11744 boolean forceReceive = false;
11745
11746 // Ensure that even if something goes awry with the timeout
11747 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011748 // and continue to make progress.
11749 //
11750 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011751 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011752 // one time heavy lifting after system upgrades and can take
11753 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011754 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011755 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011756 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011757 if ((numReceivers > 0) &&
11758 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011759 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011760 + " now=" + now
11761 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011762 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763 + " intent=" + r.intent
11764 + " numReceivers=" + numReceivers
11765 + " nextReceiver=" + r.nextReceiver
11766 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011767 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011768 forceReceive = true;
11769 r.state = BroadcastRecord.IDLE;
11770 }
11771 }
11772
11773 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011774 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011775 "processNextBroadcast() called when not idle (state="
11776 + r.state + ")");
11777 return;
11778 }
11779
11780 if (r.receivers == null || r.nextReceiver >= numReceivers
11781 || r.resultAbort || forceReceive) {
11782 // No more receivers for this broadcast! Send the final
11783 // result if requested...
11784 if (r.resultTo != null) {
11785 try {
11786 if (DEBUG_BROADCAST) {
11787 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011788 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011789 + " seq=" + seq + " app=" + r.callerApp);
11790 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011791 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011792 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011793 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011794 // Set this to null so that the reference
11795 // (local and remote) isnt kept in the mBroadcastHistory.
11796 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011798 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011799 }
11800 }
11801
Joe Onorato8a9b2202010-02-26 18:56:32 -080011802 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011803 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804
Joe Onorato8a9b2202010-02-26 18:56:32 -080011805 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011806 + r);
11807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011808 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011809 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011810 mOrderedBroadcasts.remove(0);
11811 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011812 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011813 continue;
11814 }
11815 } while (r == null);
11816
11817 // Get the next receiver...
11818 int recIdx = r.nextReceiver++;
11819
11820 // Keep track of when this receiver started, and make sure there
11821 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011822 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011823 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011824 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011825
Joe Onorato8a9b2202010-02-26 18:56:32 -080011826 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011827 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011828 }
11829 if (! mPendingBroadcastTimeoutMessage) {
11830 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011831 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011832 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11833 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011834 }
11835
11836 Object nextReceiver = r.receivers.get(recIdx);
11837 if (nextReceiver instanceof BroadcastFilter) {
11838 // Simple case: this is a registered receiver who gets
11839 // a direct call.
11840 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011841 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011842 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011843 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011844 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011845 if (r.receiver == null || !r.ordered) {
11846 // The receiver has already finished, so schedule to
11847 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011848 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11849 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011850 r.state = BroadcastRecord.IDLE;
11851 scheduleBroadcastsLocked();
11852 }
11853 return;
11854 }
11855
11856 // Hard case: need to instantiate the receiver, possibly
11857 // starting its application process to host it.
11858
11859 ResolveInfo info =
11860 (ResolveInfo)nextReceiver;
11861
11862 boolean skip = false;
11863 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011864 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
11865 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011866 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011867 if (!info.activityInfo.exported) {
11868 Slog.w(TAG, "Permission Denial: broadcasting "
11869 + r.intent.toString()
11870 + " from " + r.callerPackage + " (pid=" + r.callingPid
11871 + ", uid=" + r.callingUid + ")"
11872 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
11873 + " due to receiver " + info.activityInfo.packageName
11874 + "/" + info.activityInfo.name);
11875 } else {
11876 Slog.w(TAG, "Permission Denial: broadcasting "
11877 + r.intent.toString()
11878 + " from " + r.callerPackage + " (pid=" + r.callingPid
11879 + ", uid=" + r.callingUid + ")"
11880 + " requires " + info.activityInfo.permission
11881 + " due to receiver " + info.activityInfo.packageName
11882 + "/" + info.activityInfo.name);
11883 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011884 skip = true;
11885 }
11886 if (r.callingUid != Process.SYSTEM_UID &&
11887 r.requiredPermission != null) {
11888 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011889 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011890 checkPermission(r.requiredPermission,
11891 info.activityInfo.applicationInfo.packageName);
11892 } catch (RemoteException e) {
11893 perm = PackageManager.PERMISSION_DENIED;
11894 }
11895 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011896 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011897 + r.intent + " to "
11898 + info.activityInfo.applicationInfo.packageName
11899 + " requires " + r.requiredPermission
11900 + " due to sender " + r.callerPackage
11901 + " (uid " + r.callingUid + ")");
11902 skip = true;
11903 }
11904 }
11905 if (r.curApp != null && r.curApp.crashing) {
11906 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011907 if (DEBUG_BROADCAST) Slog.v(TAG,
11908 "Skipping deliver ordered " + r + " to " + r.curApp
11909 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011910 skip = true;
11911 }
11912
11913 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011914 if (DEBUG_BROADCAST) Slog.v(TAG,
11915 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011916 r.receiver = null;
11917 r.curFilter = null;
11918 r.state = BroadcastRecord.IDLE;
11919 scheduleBroadcastsLocked();
11920 return;
11921 }
11922
11923 r.state = BroadcastRecord.APP_RECEIVE;
11924 String targetProcess = info.activityInfo.processName;
11925 r.curComponent = new ComponentName(
11926 info.activityInfo.applicationInfo.packageName,
11927 info.activityInfo.name);
11928 r.curReceiver = info.activityInfo;
11929
Dianne Hackborne7f97212011-02-24 14:40:20 -080011930 // Broadcast is being executed, its package can't be stopped.
11931 try {
11932 AppGlobals.getPackageManager().setPackageStoppedState(
11933 r.curComponent.getPackageName(), false);
11934 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080011935 } catch (IllegalArgumentException e) {
11936 Slog.w(TAG, "Failed trying to unstop package "
11937 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080011938 }
11939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011940 // Is this receiver's application already running?
11941 ProcessRecord app = getProcessRecordLocked(targetProcess,
11942 info.activityInfo.applicationInfo.uid);
11943 if (app != null && app.thread != null) {
11944 try {
11945 processCurBroadcastLocked(r, app);
11946 return;
11947 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011948 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011949 + r.curComponent, e);
11950 }
11951
11952 // If a dead object exception was thrown -- fall through to
11953 // restart the application.
11954 }
11955
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011956 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011957 if (DEBUG_BROADCAST) Slog.v(TAG,
11958 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011959 if ((r.curApp=startProcessLocked(targetProcess,
11960 info.activityInfo.applicationInfo, true,
11961 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011962 "broadcast", r.curComponent,
11963 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11964 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011965 // Ah, this recipient is unavailable. Finish it if necessary,
11966 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011967 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011968 + info.activityInfo.applicationInfo.packageName + "/"
11969 + info.activityInfo.applicationInfo.uid + " for broadcast "
11970 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011971 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011972 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11973 r.resultExtras, r.resultAbort, true);
11974 scheduleBroadcastsLocked();
11975 r.state = BroadcastRecord.IDLE;
11976 return;
11977 }
11978
11979 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011980 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011981 }
11982 }
11983
11984 // =========================================================
11985 // INSTRUMENTATION
11986 // =========================================================
11987
11988 public boolean startInstrumentation(ComponentName className,
11989 String profileFile, int flags, Bundle arguments,
11990 IInstrumentationWatcher watcher) {
11991 // Refuse possible leaked file descriptors
11992 if (arguments != null && arguments.hasFileDescriptors()) {
11993 throw new IllegalArgumentException("File descriptors passed in Bundle");
11994 }
11995
11996 synchronized(this) {
11997 InstrumentationInfo ii = null;
11998 ApplicationInfo ai = null;
11999 try {
12000 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012001 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012002 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012003 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012004 } catch (PackageManager.NameNotFoundException e) {
12005 }
12006 if (ii == null) {
12007 reportStartInstrumentationFailure(watcher, className,
12008 "Unable to find instrumentation info for: " + className);
12009 return false;
12010 }
12011 if (ai == null) {
12012 reportStartInstrumentationFailure(watcher, className,
12013 "Unable to find instrumentation target package: " + ii.targetPackage);
12014 return false;
12015 }
12016
12017 int match = mContext.getPackageManager().checkSignatures(
12018 ii.targetPackage, ii.packageName);
12019 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12020 String msg = "Permission Denial: starting instrumentation "
12021 + className + " from pid="
12022 + Binder.getCallingPid()
12023 + ", uid=" + Binder.getCallingPid()
12024 + " not allowed because package " + ii.packageName
12025 + " does not have a signature matching the target "
12026 + ii.targetPackage;
12027 reportStartInstrumentationFailure(watcher, className, msg);
12028 throw new SecurityException(msg);
12029 }
12030
12031 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012032 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012033 ProcessRecord app = addAppLocked(ai);
12034 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012035 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012036 app.instrumentationProfileFile = profileFile;
12037 app.instrumentationArguments = arguments;
12038 app.instrumentationWatcher = watcher;
12039 app.instrumentationResultClass = className;
12040 Binder.restoreCallingIdentity(origId);
12041 }
12042
12043 return true;
12044 }
12045
12046 /**
12047 * Report errors that occur while attempting to start Instrumentation. Always writes the
12048 * error to the logs, but if somebody is watching, send the report there too. This enables
12049 * the "am" command to report errors with more information.
12050 *
12051 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12052 * @param cn The component name of the instrumentation.
12053 * @param report The error report.
12054 */
12055 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12056 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012057 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012058 try {
12059 if (watcher != null) {
12060 Bundle results = new Bundle();
12061 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12062 results.putString("Error", report);
12063 watcher.instrumentationStatus(cn, -1, results);
12064 }
12065 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012066 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012067 }
12068 }
12069
12070 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12071 if (app.instrumentationWatcher != null) {
12072 try {
12073 // NOTE: IInstrumentationWatcher *must* be oneway here
12074 app.instrumentationWatcher.instrumentationFinished(
12075 app.instrumentationClass,
12076 resultCode,
12077 results);
12078 } catch (RemoteException e) {
12079 }
12080 }
12081 app.instrumentationWatcher = null;
12082 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012083 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012084 app.instrumentationProfileFile = null;
12085 app.instrumentationArguments = null;
12086
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012087 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012088 }
12089
12090 public void finishInstrumentation(IApplicationThread target,
12091 int resultCode, Bundle results) {
12092 // Refuse possible leaked file descriptors
12093 if (results != null && results.hasFileDescriptors()) {
12094 throw new IllegalArgumentException("File descriptors passed in Intent");
12095 }
12096
12097 synchronized(this) {
12098 ProcessRecord app = getRecordForAppLocked(target);
12099 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012100 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012101 return;
12102 }
12103 final long origId = Binder.clearCallingIdentity();
12104 finishInstrumentationLocked(app, resultCode, results);
12105 Binder.restoreCallingIdentity(origId);
12106 }
12107 }
12108
12109 // =========================================================
12110 // CONFIGURATION
12111 // =========================================================
12112
12113 public ConfigurationInfo getDeviceConfigurationInfo() {
12114 ConfigurationInfo config = new ConfigurationInfo();
12115 synchronized (this) {
12116 config.reqTouchScreen = mConfiguration.touchscreen;
12117 config.reqKeyboardType = mConfiguration.keyboard;
12118 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012119 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12120 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012121 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12122 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012123 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12124 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012125 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12126 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012127 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012128 }
12129 return config;
12130 }
12131
12132 public Configuration getConfiguration() {
12133 Configuration ci;
12134 synchronized(this) {
12135 ci = new Configuration(mConfiguration);
12136 }
12137 return ci;
12138 }
12139
12140 public void updateConfiguration(Configuration values) {
12141 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12142 "updateConfiguration()");
12143
12144 synchronized(this) {
12145 if (values == null && mWindowManager != null) {
12146 // sentinel: fetch the current configuration from the window manager
12147 values = mWindowManager.computeNewConfiguration();
12148 }
12149
12150 final long origId = Binder.clearCallingIdentity();
12151 updateConfigurationLocked(values, null);
12152 Binder.restoreCallingIdentity(origId);
12153 }
12154 }
12155
12156 /**
12157 * Do either or both things: (1) change the current configuration, and (2)
12158 * make sure the given activity is running with the (now) current
12159 * configuration. Returns true if the activity has been left running, or
12160 * false if <var>starting</var> is being destroyed to match the new
12161 * configuration.
12162 */
12163 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012164 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012165 int changes = 0;
12166
12167 boolean kept = true;
12168
12169 if (values != null) {
12170 Configuration newConfig = new Configuration(mConfiguration);
12171 changes = newConfig.updateFrom(values);
12172 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012173 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012174 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012175 }
12176
Doug Zongker2bec3d42009-12-04 12:52:44 -080012177 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012178
12179 if (values.locale != null) {
12180 saveLocaleLocked(values.locale,
12181 !values.locale.equals(mConfiguration.locale),
12182 values.userSetLocale);
12183 }
12184
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012185 mConfigurationSeq++;
12186 if (mConfigurationSeq <= 0) {
12187 mConfigurationSeq = 1;
12188 }
12189 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012190 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012191 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012192
12193 AttributeCache ac = AttributeCache.instance();
12194 if (ac != null) {
12195 ac.updateConfiguration(mConfiguration);
12196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012197
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012198 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
12199 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12200 msg.obj = new Configuration(mConfiguration);
12201 mHandler.sendMessage(msg);
12202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012203
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012204 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12205 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012206 try {
12207 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012208 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012209 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012210 app.thread.scheduleConfigurationChanged(mConfiguration);
12211 }
12212 } catch (Exception e) {
12213 }
12214 }
12215 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012216 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12217 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012218 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12219 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012220 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12221 broadcastIntentLocked(null, null,
12222 new Intent(Intent.ACTION_LOCALE_CHANGED),
12223 null, null, 0, null, null,
12224 null, false, false, MY_PID, Process.SYSTEM_UID);
12225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226 }
12227 }
12228
12229 if (changes != 0 && starting == null) {
12230 // If the configuration changed, and the caller is not already
12231 // in the process of starting an activity, then find the top
12232 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012233 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012234 }
12235
12236 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012237 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012238 // And we need to make sure at this point that all other activities
12239 // are made visible with the correct configuration.
12240 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012241 }
12242
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012243 if (values != null && mWindowManager != null) {
12244 mWindowManager.setNewConfiguration(mConfiguration);
12245 }
12246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012247 return kept;
12248 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012249
12250 /**
12251 * Save the locale. You must be inside a synchronized (this) block.
12252 */
12253 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12254 if(isDiff) {
12255 SystemProperties.set("user.language", l.getLanguage());
12256 SystemProperties.set("user.region", l.getCountry());
12257 }
12258
12259 if(isPersist) {
12260 SystemProperties.set("persist.sys.language", l.getLanguage());
12261 SystemProperties.set("persist.sys.country", l.getCountry());
12262 SystemProperties.set("persist.sys.localevar", l.getVariant());
12263 }
12264 }
12265
12266 // =========================================================
12267 // LIFETIME MANAGEMENT
12268 // =========================================================
12269
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012270 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12271 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012272 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012273 // This adjustment has already been computed. If we are calling
12274 // from the top, we may have already computed our adjustment with
12275 // an earlier hidden adjustment that isn't really for us... if
12276 // so, use the new hidden adjustment.
12277 if (!recursed && app.hidden) {
12278 app.curAdj = hiddenAdj;
12279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012280 return app.curAdj;
12281 }
12282
12283 if (app.thread == null) {
12284 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012285 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012286 return (app.curAdj=EMPTY_APP_ADJ);
12287 }
12288
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012289 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12290 // The max adjustment doesn't allow this app to be anything
12291 // below foreground, so it is not worth doing work for it.
12292 app.adjType = "fixed";
12293 app.adjSeq = mAdjSeq;
12294 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012295 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012296 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12297 return (app.curAdj=app.maxAdj);
12298 }
12299
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012300 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012301 app.adjSource = null;
12302 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012303 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012304 app.empty = false;
12305 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012306
The Android Open Source Project4df24232009-03-05 14:34:35 -080012307 // Determine the importance of the process, starting with most
12308 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012309 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012310 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012311 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012312 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012313 // The last app on the list is the foreground app.
12314 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012315 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012316 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012317 } else if (app.instrumentationClass != null) {
12318 // Don't want to kill running instrumentation.
12319 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012320 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012321 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012322 } else if (app.curReceiver != null ||
12323 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12324 // An app that is currently receiving a broadcast also
12325 // counts as being in the foreground.
12326 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012327 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012328 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012329 } else if (app.executingServices.size() > 0) {
12330 // An app that is currently executing a service callback also
12331 // counts as being in the foreground.
12332 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012333 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012334 app.adjType = "exec-service";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012335 } else if ((N=app.activities.size()) != 0) {
12336 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012337 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012338 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012339 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012340 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012341 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012342 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012343 ActivityRecord r = app.activities.get(j);
12344 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012345 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012346 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012347 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012348 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012349 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012350 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012351 } else if (r.state == ActivityState.PAUSING
12352 || r.state == ActivityState.PAUSED
12353 || r.state == ActivityState.STOPPING) {
12354 adj = PERCEPTIBLE_APP_ADJ;
12355 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012356 }
12357 }
12358 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012359 // A very not-needed process. If this is lower in the lru list,
12360 // we will push it in to the empty bucket.
12361 app.hidden = true;
12362 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012363 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012364 adj = hiddenAdj;
12365 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012366 }
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012367
12368 if (adj > PERCEPTIBLE_APP_ADJ) {
12369 if (app.foregroundServices) {
12370 // The user is aware of this app, so make it visible.
12371 adj = PERCEPTIBLE_APP_ADJ;
12372 schedGroup = Process.THREAD_GROUP_DEFAULT;
12373 app.adjType = "foreground-service";
12374 } else if (app.forcingToForeground != null) {
12375 // The user is aware of this app, so make it visible.
12376 adj = PERCEPTIBLE_APP_ADJ;
12377 schedGroup = Process.THREAD_GROUP_DEFAULT;
12378 app.adjType = "force-foreground";
12379 app.adjSource = app.forcingToForeground;
12380 }
12381 }
12382
12383 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12384 // We don't want to kill the current heavy-weight process.
12385 adj = HEAVY_WEIGHT_APP_ADJ;
12386 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12387 app.adjType = "heavy";
12388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012389
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012390 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12391 // This process is hosting what we currently consider to be the
12392 // home app, so we don't want to let it go into the background.
12393 adj = HOME_APP_ADJ;
12394 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12395 app.adjType = "home";
12396 }
12397
Joe Onorato8a9b2202010-02-26 18:56:32 -080012398 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012399
The Android Open Source Project4df24232009-03-05 14:34:35 -080012400 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012401 // there are applications dependent on our services or providers, but
12402 // this gives us a baseline and makes sure we don't get into an
12403 // infinite recursion.
12404 app.adjSeq = mAdjSeq;
12405 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012406
Christopher Tate6fa95972009-06-05 18:43:55 -070012407 if (mBackupTarget != null && app == mBackupTarget.app) {
12408 // If possible we want to avoid killing apps while they're being backed up
12409 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012410 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012411 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012412 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012413 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012414 }
12415 }
12416
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012417 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12418 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012419 final long now = SystemClock.uptimeMillis();
12420 // This process is more important if the top activity is
12421 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012422 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012423 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012424 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012425 if (s.startRequested) {
12426 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12427 // This service has seen some activity within
12428 // recent memory, so we will keep its process ahead
12429 // of the background processes.
12430 if (adj > SECONDARY_SERVER_ADJ) {
12431 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012432 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012433 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012434 }
12435 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012436 // If we have let the service slide into the background
12437 // state, still have some text describing what it is doing
12438 // even though the service no longer has an impact.
12439 if (adj > SECONDARY_SERVER_ADJ) {
12440 app.adjType = "started-bg-services";
12441 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012442 // Don't kill this process because it is doing work; it
12443 // has said it is doing work.
12444 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012445 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012446 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12447 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012448 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012449 = s.connections.values().iterator();
12450 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012451 ArrayList<ConnectionRecord> clist = kt.next();
12452 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12453 // XXX should compute this based on the max of
12454 // all connected clients.
12455 ConnectionRecord cr = clist.get(i);
12456 if (cr.binding.client == app) {
12457 // Binding to ourself is not interesting.
12458 continue;
12459 }
12460 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12461 ProcessRecord client = cr.binding.client;
12462 int myHiddenAdj = hiddenAdj;
12463 if (myHiddenAdj > client.hiddenAdj) {
12464 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12465 myHiddenAdj = client.hiddenAdj;
12466 } else {
12467 myHiddenAdj = VISIBLE_APP_ADJ;
12468 }
12469 }
12470 int clientAdj = computeOomAdjLocked(
12471 client, myHiddenAdj, TOP_APP, true);
12472 if (adj > clientAdj) {
12473 adj = clientAdj >= VISIBLE_APP_ADJ
12474 ? clientAdj : VISIBLE_APP_ADJ;
12475 if (!client.hidden) {
12476 app.hidden = false;
12477 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012478 if (client.keeping) {
12479 app.keeping = true;
12480 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012481 app.adjType = "service";
12482 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12483 .REASON_SERVICE_IN_USE;
12484 app.adjSource = cr.binding.client;
12485 app.adjTarget = s.name;
12486 }
12487 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12488 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12489 schedGroup = Process.THREAD_GROUP_DEFAULT;
12490 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012491 }
12492 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012493 ActivityRecord a = cr.activity;
12494 //if (a != null) {
12495 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12496 //}
12497 if (a != null && adj > FOREGROUND_APP_ADJ &&
12498 (a.state == ActivityState.RESUMED
12499 || a.state == ActivityState.PAUSING)) {
12500 adj = FOREGROUND_APP_ADJ;
12501 schedGroup = Process.THREAD_GROUP_DEFAULT;
12502 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012503 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012504 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12505 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012506 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012507 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012509 }
12510 }
12511 }
12512 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012513
Dianne Hackborn287952c2010-09-22 22:34:31 -070012514 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012515 // would like to avoid killing it unless it would prevent the current
12516 // application from running. By default we put the process in
12517 // with the rest of the background processes; as we scan through
12518 // its services we may bump it up from there.
12519 if (adj > hiddenAdj) {
12520 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012521 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012522 app.adjType = "bg-services";
12523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012524 }
12525
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012526 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12527 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012528 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012529 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12530 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012531 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012532 if (cpr.clients.size() != 0) {
12533 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12534 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12535 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012536 if (client == app) {
12537 // Being our own client is not interesting.
12538 continue;
12539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012540 int myHiddenAdj = hiddenAdj;
12541 if (myHiddenAdj > client.hiddenAdj) {
12542 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12543 myHiddenAdj = client.hiddenAdj;
12544 } else {
12545 myHiddenAdj = FOREGROUND_APP_ADJ;
12546 }
12547 }
12548 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012549 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012550 if (adj > clientAdj) {
12551 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012552 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012553 if (!client.hidden) {
12554 app.hidden = false;
12555 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012556 if (client.keeping) {
12557 app.keeping = true;
12558 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012559 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012560 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12561 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012562 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012563 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012564 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012565 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12566 schedGroup = Process.THREAD_GROUP_DEFAULT;
12567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012568 }
12569 }
12570 // If the provider has external (non-framework) process
12571 // dependencies, ensure that its adjustment is at least
12572 // FOREGROUND_APP_ADJ.
12573 if (cpr.externals != 0) {
12574 if (adj > FOREGROUND_APP_ADJ) {
12575 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012576 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012577 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012578 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012579 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012580 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012581 }
12582 }
12583 }
12584 }
12585
12586 app.curRawAdj = adj;
12587
Joe Onorato8a9b2202010-02-26 18:56:32 -080012588 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012589 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12590 if (adj > app.maxAdj) {
12591 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012592 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012593 schedGroup = Process.THREAD_GROUP_DEFAULT;
12594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012595 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012596 if (adj < HIDDEN_APP_MIN_ADJ) {
12597 app.keeping = true;
12598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012599
12600 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012601 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012603 return adj;
12604 }
12605
12606 /**
12607 * Ask a given process to GC right now.
12608 */
12609 final void performAppGcLocked(ProcessRecord app) {
12610 try {
12611 app.lastRequestedGc = SystemClock.uptimeMillis();
12612 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012613 if (app.reportLowMemory) {
12614 app.reportLowMemory = false;
12615 app.thread.scheduleLowMemory();
12616 } else {
12617 app.thread.processInBackground();
12618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012619 }
12620 } catch (Exception e) {
12621 // whatever.
12622 }
12623 }
12624
12625 /**
12626 * Returns true if things are idle enough to perform GCs.
12627 */
Josh Bartel7f208742010-02-25 11:01:44 -060012628 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012629 return mParallelBroadcasts.size() == 0
12630 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012631 && (mSleeping || (mMainStack.mResumedActivity != null &&
12632 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012633 }
12634
12635 /**
12636 * Perform GCs on all processes that are waiting for it, but only
12637 * if things are idle.
12638 */
12639 final void performAppGcsLocked() {
12640 final int N = mProcessesToGc.size();
12641 if (N <= 0) {
12642 return;
12643 }
Josh Bartel7f208742010-02-25 11:01:44 -060012644 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012645 while (mProcessesToGc.size() > 0) {
12646 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012647 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012648 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12649 <= SystemClock.uptimeMillis()) {
12650 // To avoid spamming the system, we will GC processes one
12651 // at a time, waiting a few seconds between each.
12652 performAppGcLocked(proc);
12653 scheduleAppGcsLocked();
12654 return;
12655 } else {
12656 // It hasn't been long enough since we last GCed this
12657 // process... put it in the list to wait for its time.
12658 addProcessToGcListLocked(proc);
12659 break;
12660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012661 }
12662 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012663
12664 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012665 }
12666 }
12667
12668 /**
12669 * If all looks good, perform GCs on all processes waiting for them.
12670 */
12671 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012672 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012673 performAppGcsLocked();
12674 return;
12675 }
12676 // Still not idle, wait some more.
12677 scheduleAppGcsLocked();
12678 }
12679
12680 /**
12681 * Schedule the execution of all pending app GCs.
12682 */
12683 final void scheduleAppGcsLocked() {
12684 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012685
12686 if (mProcessesToGc.size() > 0) {
12687 // Schedule a GC for the time to the next process.
12688 ProcessRecord proc = mProcessesToGc.get(0);
12689 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12690
12691 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12692 long now = SystemClock.uptimeMillis();
12693 if (when < (now+GC_TIMEOUT)) {
12694 when = now + GC_TIMEOUT;
12695 }
12696 mHandler.sendMessageAtTime(msg, when);
12697 }
12698 }
12699
12700 /**
12701 * Add a process to the array of processes waiting to be GCed. Keeps the
12702 * list in sorted order by the last GC time. The process can't already be
12703 * on the list.
12704 */
12705 final void addProcessToGcListLocked(ProcessRecord proc) {
12706 boolean added = false;
12707 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12708 if (mProcessesToGc.get(i).lastRequestedGc <
12709 proc.lastRequestedGc) {
12710 added = true;
12711 mProcessesToGc.add(i+1, proc);
12712 break;
12713 }
12714 }
12715 if (!added) {
12716 mProcessesToGc.add(0, proc);
12717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012718 }
12719
12720 /**
12721 * Set up to ask a process to GC itself. This will either do it
12722 * immediately, or put it on the list of processes to gc the next
12723 * time things are idle.
12724 */
12725 final void scheduleAppGcLocked(ProcessRecord app) {
12726 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012727 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012728 return;
12729 }
12730 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012731 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012732 scheduleAppGcsLocked();
12733 }
12734 }
12735
Dianne Hackborn287952c2010-09-22 22:34:31 -070012736 final void checkExcessivePowerUsageLocked(boolean doKills) {
12737 updateCpuStatsNow();
12738
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012739 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012740 boolean doWakeKills = doKills;
12741 boolean doCpuKills = doKills;
12742 if (mLastPowerCheckRealtime == 0) {
12743 doWakeKills = false;
12744 }
12745 if (mLastPowerCheckUptime == 0) {
12746 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012747 }
12748 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012749 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012750 }
12751 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012752 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12753 final long curUptime = SystemClock.uptimeMillis();
12754 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12755 mLastPowerCheckRealtime = curRealtime;
12756 mLastPowerCheckUptime = curUptime;
12757 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12758 doWakeKills = false;
12759 }
12760 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12761 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012762 }
12763 int i = mLruProcesses.size();
12764 while (i > 0) {
12765 i--;
12766 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012767 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012768 long wtime;
12769 synchronized (stats) {
12770 wtime = stats.getProcessWakeTime(app.info.uid,
12771 app.pid, curRealtime);
12772 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012773 long wtimeUsed = wtime - app.lastWakeTime;
12774 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12775 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012776 StringBuilder sb = new StringBuilder(128);
12777 sb.append("Wake for ");
12778 app.toShortString(sb);
12779 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012780 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012781 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012782 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012783 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012784 sb.append((wtimeUsed*100)/realtimeSince);
12785 sb.append("%)");
12786 Slog.i(TAG, sb.toString());
12787 sb.setLength(0);
12788 sb.append("CPU for ");
12789 app.toShortString(sb);
12790 sb.append(": over ");
12791 TimeUtils.formatDuration(uptimeSince, sb);
12792 sb.append(" used ");
12793 TimeUtils.formatDuration(cputimeUsed, sb);
12794 sb.append(" (");
12795 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012796 sb.append("%)");
12797 Slog.i(TAG, sb.toString());
12798 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012799 // If a process has held a wake lock for more
12800 // than 50% of the time during this period,
12801 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012802 if (doWakeKills && realtimeSince > 0
12803 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12804 synchronized (stats) {
12805 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12806 realtimeSince, wtimeUsed);
12807 }
12808 Slog.w(TAG, "Excessive wake lock in " + app.processName
12809 + " (pid " + app.pid + "): held " + wtimeUsed
12810 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012811 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12812 app.processName, app.setAdj, "excessive wake lock");
12813 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012814 } else if (doCpuKills && uptimeSince > 0
12815 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12816 synchronized (stats) {
12817 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12818 uptimeSince, cputimeUsed);
12819 }
12820 Slog.w(TAG, "Excessive CPU in " + app.processName
12821 + " (pid " + app.pid + "): used " + cputimeUsed
12822 + " during " + uptimeSince);
12823 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12824 app.processName, app.setAdj, "excessive cpu");
12825 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012826 } else {
12827 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012828 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012829 }
12830 }
12831 }
12832 }
12833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012834 private final boolean updateOomAdjLocked(
12835 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12836 app.hiddenAdj = hiddenAdj;
12837
12838 if (app.thread == null) {
12839 return true;
12840 }
12841
Dianne Hackborn287952c2010-09-22 22:34:31 -070012842 final boolean wasKeeping = app.keeping;
12843
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012844 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012845
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012846 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012847 if (app.curRawAdj != app.setRawAdj) {
12848 if (app.curRawAdj > FOREGROUND_APP_ADJ
12849 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12850 // If this app is transitioning from foreground to
12851 // non-foreground, have it do a gc.
12852 scheduleAppGcLocked(app);
12853 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12854 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12855 // Likewise do a gc when an app is moving in to the
12856 // background (such as a service stopping).
12857 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012858 }
12859
12860 if (wasKeeping && !app.keeping) {
12861 // This app is no longer something we want to keep. Note
12862 // its current wake lock time to later know to kill it if
12863 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012864 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12865 synchronized (stats) {
12866 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12867 app.pid, SystemClock.elapsedRealtime());
12868 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012869 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012870 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012872 app.setRawAdj = app.curRawAdj;
12873 }
12874 if (adj != app.setAdj) {
12875 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012876 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012877 TAG, "Set app " + app.processName +
12878 " oom adj to " + adj);
12879 app.setAdj = adj;
12880 } else {
12881 return false;
12882 }
12883 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012884 if (app.setSchedGroup != app.curSchedGroup) {
12885 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012886 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012887 "Setting process group of " + app.processName
12888 + " to " + app.curSchedGroup);
12889 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012890 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012891 try {
12892 Process.setProcessGroup(app.pid, app.curSchedGroup);
12893 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012894 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012895 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012896 e.printStackTrace();
12897 } finally {
12898 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012899 }
12900 }
12901 if (false) {
12902 if (app.thread != null) {
12903 try {
12904 app.thread.setSchedulingGroup(app.curSchedGroup);
12905 } catch (RemoteException e) {
12906 }
12907 }
12908 }
12909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012910 }
12911
12912 return true;
12913 }
12914
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012915 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012916 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012917 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012918 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012919 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012920 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012921 }
12922 }
12923 return resumedActivity;
12924 }
12925
12926 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012927 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012928 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12929 int curAdj = app.curAdj;
12930 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12931 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12932
12933 mAdjSeq++;
12934
12935 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12936 if (res) {
12937 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12938 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12939 if (nowHidden != wasHidden) {
12940 // Changed to/from hidden state, so apps after it in the LRU
12941 // list may also be changed.
12942 updateOomAdjLocked();
12943 }
12944 }
12945 return res;
12946 }
12947
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012948 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012949 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012950 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012951 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12952
12953 if (false) {
12954 RuntimeException e = new RuntimeException();
12955 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012956 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012957 }
12958
12959 mAdjSeq++;
12960
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012961 // Let's determine how many processes we have running vs.
12962 // how many slots we have for background processes; we may want
12963 // to put multiple processes in a slot of there are enough of
12964 // them.
12965 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12966 int factor = (mLruProcesses.size()-4)/numSlots;
12967 if (factor < 1) factor = 1;
12968 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012969 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012971 // First try updating the OOM adjustment for each of the
12972 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012973 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012974 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12975 while (i > 0) {
12976 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012977 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012978 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012979 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012980 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012981 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012982 step++;
12983 if (step >= factor) {
12984 step = 0;
12985 curHiddenAdj++;
12986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012987 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012988 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012989 if (!app.killedBackground) {
12990 numHidden++;
12991 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012992 Slog.i(TAG, "No longer want " + app.processName
12993 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012994 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12995 app.processName, app.setAdj, "too many background");
12996 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012997 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012998 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012999 }
13000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013001 } else {
13002 didOomAdj = false;
13003 }
13004 }
13005
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013006 // If we return false, we will fall back on killing processes to
13007 // have a fixed limit. Do this if a limit has been requested; else
13008 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013009 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13010 }
13011
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013012 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013013 synchronized (this) {
13014 int i;
13015
13016 // First remove any unused application processes whose package
13017 // has been removed.
13018 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13019 final ProcessRecord app = mRemovedProcesses.get(i);
13020 if (app.activities.size() == 0
13021 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013022 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013023 TAG, "Exiting empty application process "
13024 + app.processName + " ("
13025 + (app.thread != null ? app.thread.asBinder() : null)
13026 + ")\n");
13027 if (app.pid > 0 && app.pid != MY_PID) {
13028 Process.killProcess(app.pid);
13029 } else {
13030 try {
13031 app.thread.scheduleExit();
13032 } catch (Exception e) {
13033 // Ignore exceptions.
13034 }
13035 }
13036 cleanUpApplicationRecordLocked(app, false, -1);
13037 mRemovedProcesses.remove(i);
13038
13039 if (app.persistent) {
13040 if (app.persistent) {
13041 addAppLocked(app.info);
13042 }
13043 }
13044 }
13045 }
13046
13047 // Now try updating the OOM adjustment for each of the
13048 // application processes based on their current state.
13049 // If the setOomAdj() API is not supported, then go with our
13050 // back-up plan...
13051 if (!updateOomAdjLocked()) {
13052
13053 // Count how many processes are running services.
13054 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013055 for (i=mLruProcesses.size()-1; i>=0; i--) {
13056 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013057
13058 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013059 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013060 // Don't count processes holding services against our
13061 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013062 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013063 TAG, "Not trimming app " + app + " with services: "
13064 + app.services);
13065 numServiceProcs++;
13066 }
13067 }
13068
13069 int curMaxProcs = mProcessLimit;
13070 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13071 if (mAlwaysFinishActivities) {
13072 curMaxProcs = 1;
13073 }
13074 curMaxProcs += numServiceProcs;
13075
13076 // Quit as many processes as we can to get down to the desired
13077 // process count. First remove any processes that no longer
13078 // have activites running in them.
13079 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013080 i<mLruProcesses.size()
13081 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013082 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013083 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013084 // Quit an application only if it is not currently
13085 // running any activities.
13086 if (!app.persistent && app.activities.size() == 0
13087 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013088 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013089 TAG, "Exiting empty application process "
13090 + app.processName + " ("
13091 + (app.thread != null ? app.thread.asBinder() : null)
13092 + ")\n");
13093 if (app.pid > 0 && app.pid != MY_PID) {
13094 Process.killProcess(app.pid);
13095 } else {
13096 try {
13097 app.thread.scheduleExit();
13098 } catch (Exception e) {
13099 // Ignore exceptions.
13100 }
13101 }
13102 // todo: For now we assume the application is not buggy
13103 // or evil, and will quit as a result of our request.
13104 // Eventually we need to drive this off of the death
13105 // notification, and kill the process if it takes too long.
13106 cleanUpApplicationRecordLocked(app, false, i);
13107 i--;
13108 }
13109 }
13110
13111 // If we still have too many processes, now from the least
13112 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013113 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013114 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013115 " of " + curMaxProcs + " processes");
13116 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013117 i<mLruProcesses.size()
13118 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013119 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013120 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013121 // Quit the application only if we have a state saved for
13122 // all of its activities.
13123 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013124 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013125 int NUMA = app.activities.size();
13126 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013127 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013128 TAG, "Looking to quit " + app.processName);
13129 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013130 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013131 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013132 TAG, " " + r.intent.getComponent().flattenToShortString()
13133 + ": frozen=" + r.haveState + ", visible=" + r.visible);
13134 canQuit = (r.haveState || !r.stateNotNeeded)
13135 && !r.visible && r.stopped;
13136 }
13137 if (canQuit) {
13138 // Finish all of the activities, and then the app itself.
13139 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013140 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013141 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013142 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013143 }
13144 r.resultTo = null;
13145 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013146 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013147 + app.processName + " ("
13148 + (app.thread != null ? app.thread.asBinder() : null)
13149 + ")\n");
13150 if (app.pid > 0 && app.pid != MY_PID) {
13151 Process.killProcess(app.pid);
13152 } else {
13153 try {
13154 app.thread.scheduleExit();
13155 } catch (Exception e) {
13156 // Ignore exceptions.
13157 }
13158 }
13159 // todo: For now we assume the application is not buggy
13160 // or evil, and will quit as a result of our request.
13161 // Eventually we need to drive this off of the death
13162 // notification, and kill the process if it takes too long.
13163 cleanUpApplicationRecordLocked(app, false, i);
13164 i--;
13165 //dump();
13166 }
13167 }
13168
13169 }
13170
13171 int curMaxActivities = MAX_ACTIVITIES;
13172 if (mAlwaysFinishActivities) {
13173 curMaxActivities = 1;
13174 }
13175
13176 // Finally, if there are too many activities now running, try to
13177 // finish as many as we can to get back down to the limit.
13178 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013179 i<mMainStack.mLRUActivities.size()
13180 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013181 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013182 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013183 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013184
13185 // We can finish this one if we have its icicle saved and
13186 // it is not persistent.
13187 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013188 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013189 final int origSize = mMainStack.mLRUActivities.size();
13190 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013191
13192 // This will remove it from the LRU list, so keep
13193 // our index at the same value. Note that this check to
13194 // see if the size changes is just paranoia -- if
13195 // something unexpected happens, we don't want to end up
13196 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013197 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013198 i--;
13199 }
13200 }
13201 }
13202 }
13203 }
13204
13205 /** This method sends the specified signal to each of the persistent apps */
13206 public void signalPersistentProcesses(int sig) throws RemoteException {
13207 if (sig != Process.SIGNAL_USR1) {
13208 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13209 }
13210
13211 synchronized (this) {
13212 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13213 != PackageManager.PERMISSION_GRANTED) {
13214 throw new SecurityException("Requires permission "
13215 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13216 }
13217
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013218 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13219 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013220 if (r.thread != null && r.persistent) {
13221 Process.sendSignal(r.pid, sig);
13222 }
13223 }
13224 }
13225 }
13226
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013227 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013228 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013229
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013230 try {
13231 synchronized (this) {
13232 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13233 // its own permission.
13234 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13235 != PackageManager.PERMISSION_GRANTED) {
13236 throw new SecurityException("Requires permission "
13237 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013238 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013239
13240 if (start && fd == null) {
13241 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013242 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013243
13244 ProcessRecord proc = null;
13245 try {
13246 int pid = Integer.parseInt(process);
13247 synchronized (mPidsSelfLocked) {
13248 proc = mPidsSelfLocked.get(pid);
13249 }
13250 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013251 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013252
13253 if (proc == null) {
13254 HashMap<String, SparseArray<ProcessRecord>> all
13255 = mProcessNames.getMap();
13256 SparseArray<ProcessRecord> procs = all.get(process);
13257 if (procs != null && procs.size() > 0) {
13258 proc = procs.valueAt(0);
13259 }
13260 }
13261
13262 if (proc == null || proc.thread == null) {
13263 throw new IllegalArgumentException("Unknown process: " + process);
13264 }
13265
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013266 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13267 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013268 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13269 throw new SecurityException("Process not debuggable: " + proc);
13270 }
13271 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013272
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013273 proc.thread.profilerControl(start, path, fd);
13274 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013275 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013276 }
13277 } catch (RemoteException e) {
13278 throw new IllegalStateException("Process disappeared");
13279 } finally {
13280 if (fd != null) {
13281 try {
13282 fd.close();
13283 } catch (IOException e) {
13284 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013285 }
13286 }
13287 }
Andy McFadden824c5102010-07-09 16:26:57 -070013288
13289 public boolean dumpHeap(String process, boolean managed,
13290 String path, ParcelFileDescriptor fd) throws RemoteException {
13291
13292 try {
13293 synchronized (this) {
13294 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13295 // its own permission (same as profileControl).
13296 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13297 != PackageManager.PERMISSION_GRANTED) {
13298 throw new SecurityException("Requires permission "
13299 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13300 }
13301
13302 if (fd == null) {
13303 throw new IllegalArgumentException("null fd");
13304 }
13305
13306 ProcessRecord proc = null;
13307 try {
13308 int pid = Integer.parseInt(process);
13309 synchronized (mPidsSelfLocked) {
13310 proc = mPidsSelfLocked.get(pid);
13311 }
13312 } catch (NumberFormatException e) {
13313 }
13314
13315 if (proc == null) {
13316 HashMap<String, SparseArray<ProcessRecord>> all
13317 = mProcessNames.getMap();
13318 SparseArray<ProcessRecord> procs = all.get(process);
13319 if (procs != null && procs.size() > 0) {
13320 proc = procs.valueAt(0);
13321 }
13322 }
13323
13324 if (proc == null || proc.thread == null) {
13325 throw new IllegalArgumentException("Unknown process: " + process);
13326 }
13327
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013328 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13329 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013330 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13331 throw new SecurityException("Process not debuggable: " + proc);
13332 }
13333 }
13334
13335 proc.thread.dumpHeap(managed, path, fd);
13336 fd = null;
13337 return true;
13338 }
13339 } catch (RemoteException e) {
13340 throw new IllegalStateException("Process disappeared");
13341 } finally {
13342 if (fd != null) {
13343 try {
13344 fd.close();
13345 } catch (IOException e) {
13346 }
13347 }
13348 }
13349 }
13350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013351 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13352 public void monitor() {
13353 synchronized (this) { }
13354 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013355
13356 public void onCoreSettingsChange(Bundle settings) {
13357 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13358 ProcessRecord processRecord = mLruProcesses.get(i);
13359 try {
13360 if (processRecord.thread != null) {
13361 processRecord.thread.setCoreSettings(settings);
13362 }
13363 } catch (RemoteException re) {
13364 /* ignore */
13365 }
13366 }
13367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013368}