blob: c896c94adb54eacccb73d7b0c2749853c55163e6 [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;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
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;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020058import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.Intent;
60import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070061import android.content.IIntentReceiver;
62import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070063import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.pm.ActivityInfo;
65import android.content.pm.ApplicationInfo;
66import android.content.pm.ConfigurationInfo;
67import android.content.pm.IPackageDataObserver;
68import android.content.pm.IPackageManager;
69import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080070import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070072import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.ProviderInfo;
74import android.content.pm.ResolveInfo;
75import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070076import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.content.res.Configuration;
78import android.graphics.Bitmap;
79import android.net.Uri;
80import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080081import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080082import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070083import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080084import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080086import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.FileUtils;
88import android.os.Handler;
89import android.os.IBinder;
90import android.os.IPermissionController;
91import android.os.Looper;
92import android.os.Message;
93import android.os.Parcel;
94import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070096import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.RemoteException;
98import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070099import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.SystemClock;
101import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.util.Config;
104import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800105import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800106import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.util.PrintWriterPrinter;
108import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700109import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.view.Gravity;
111import android.view.LayoutInflater;
112import android.view.View;
113import android.view.WindowManager;
114import android.view.WindowManagerPolicy;
115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116import java.io.File;
117import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200119import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800120import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121import java.io.PrintWriter;
122import java.lang.IllegalStateException;
123import java.lang.ref.WeakReference;
124import java.util.ArrayList;
125import java.util.HashMap;
126import java.util.HashSet;
127import java.util.Iterator;
128import java.util.List;
129import java.util.Locale;
130import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700131import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700132import java.util.concurrent.atomic.AtomicBoolean;
133import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700135public final class ActivityManagerService extends ActivityManagerNative
136 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 static final String TAG = "ActivityManager";
138 static final boolean DEBUG = false;
139 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
140 static final boolean DEBUG_SWITCH = localLOGV || false;
141 static final boolean DEBUG_TASKS = localLOGV || false;
142 static final boolean DEBUG_PAUSE = localLOGV || false;
143 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
144 static final boolean DEBUG_TRANSITION = localLOGV || false;
145 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700146 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 static final boolean DEBUG_SERVICE = localLOGV || false;
148 static final boolean DEBUG_VISBILITY = localLOGV || false;
149 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700150 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800151 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700153 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700154 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700155 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 static final boolean VALIDATE_TOKENS = false;
157 static final boolean SHOW_ACTIVITY_START_TIME = true;
158
159 // Control over CPU and battery monitoring.
160 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
161 static final boolean MONITOR_CPU_USAGE = true;
162 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
163 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
164 static final boolean MONITOR_THREAD_CPU_USAGE = false;
165
Dianne Hackborn1655be42009-05-08 14:29:01 -0700166 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700167 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 private static final String SYSTEM_SECURE = "ro.secure";
170
171 // This is the maximum number of application processes we would like
172 // to have running. Due to the asynchronous nature of things, we can
173 // temporarily go beyond this limit.
174 static final int MAX_PROCESSES = 2;
175
176 // Set to false to leave processes running indefinitely, relying on
177 // the kernel killing them as resources are required.
178 static final boolean ENFORCE_PROCESS_LIMIT = false;
179
180 // This is the maximum number of activities that we would like to have
181 // running at a given time.
182 static final int MAX_ACTIVITIES = 20;
183
184 // Maximum number of recent tasks that we can remember.
185 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700186
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700187 // Amount of time after a call to stopAppSwitches() during which we will
188 // prevent further untrusted switches from happening.
189 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190
191 // How long we wait for a launched process to attach to the activity manager
192 // before we decide it's never going to come up for real.
193 static final int PROC_START_TIMEOUT = 10*1000;
194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 // How long to wait after going idle before forcing apps to GC.
196 static final int GC_TIMEOUT = 5*1000;
197
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700198 // The minimum amount of time between successive GC requests for a process.
199 static final int GC_MIN_INTERVAL = 60*1000;
200
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700201 // The rate at which we check for apps using excessive wake locks -- 15 mins.
202 static final int WAKE_LOCK_CHECK_DELAY = 15*60*1000;
203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 // How long we allow a receiver to run before giving up on it.
205 static final int BROADCAST_TIMEOUT = 10*1000;
206
207 // How long we wait for a service to finish executing.
208 static final int SERVICE_TIMEOUT = 20*1000;
209
210 // How long a service needs to be running until restarting its process
211 // is no longer considered to be a relaunch of the service.
212 static final int SERVICE_RESTART_DURATION = 5*1000;
213
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700214 // How long a service needs to be running until it will start back at
215 // SERVICE_RESTART_DURATION after being killed.
216 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
217
218 // Multiplying factor to increase restart duration time by, for each time
219 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
220 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
221
222 // The minimum amount of time between restarting services that we allow.
223 // That is, when multiple services are restarting, we won't allow each
224 // to restart less than this amount of time from the last one.
225 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 // Maximum amount of time for there to be no activity on a service before
228 // we consider it non-essential and allow its process to go on the
229 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700230 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231
232 // How long we wait until we timeout on key dispatching.
233 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
234
235 // The minimum time we allow between crashes, for us to consider this
236 // application to be bad and stop and its services and reject broadcasts.
237 static final int MIN_CRASH_INTERVAL = 60*1000;
238
239 // How long we wait until we timeout on key dispatching during instrumentation.
240 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
241
242 // OOM adjustments for processes in various states:
243
244 // This is a process without anything currently running in it. Definitely
245 // the first to go! Value set in system/rootdir/init.rc on startup.
246 // This value is initalized in the constructor, careful when refering to
247 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800248 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249
250 // This is a process only hosting activities that are not visible,
251 // so it can be killed without any disruption. Value set in
252 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800253 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 static int HIDDEN_APP_MIN_ADJ;
255
The Android Open Source Project4df24232009-03-05 14:34:35 -0800256 // This is a process holding the home application -- we want to try
257 // avoiding killing it, even if it would normally be in the background,
258 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800259 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800260
Christopher Tate6fa95972009-06-05 18:43:55 -0700261 // This is a process currently hosting a backup operation. Killing it
262 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800263 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 // This is a process holding a secondary server -- killing it will not
266 // have much of an impact as far as the user is concerned. Value set in
267 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800268 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700270 // This is a process with a heavy-weight application. It is in the
271 // background, but we want to try to avoid killing it. Value set in
272 // system/rootdir/init.rc on startup.
273 static final int HEAVY_WEIGHT_APP_ADJ;
274
275 // This is a process only hosting components that are perceptible to the
276 // user, and we really want to avoid killing them, but they are not
277 // immediately visible. An example is background music playback. Value set in
278 // system/rootdir/init.rc on startup.
279 static final int PERCEPTIBLE_APP_ADJ;
280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 // This is a process only hosting activities that are visible to the
282 // user, so we'd prefer they don't disappear. Value set in
283 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285
286 // This is the process running the current foreground app. We'd really
287 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800288 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289
290 // This is a process running a core server, such as telephony. Definitely
291 // don't want to kill it, but doing so is not completely fatal.
292 static final int CORE_SERVER_ADJ = -12;
293
294 // The system process runs at the default adjustment.
295 static final int SYSTEM_ADJ = -16;
296
297 // Memory pages are 4K.
298 static final int PAGE_SIZE = 4*1024;
299
300 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800301 static final int EMPTY_APP_MEM;
302 static final int HIDDEN_APP_MEM;
303 static final int HOME_APP_MEM;
304 static final int BACKUP_APP_MEM;
305 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700306 static final int HEAVY_WEIGHT_APP_MEM;
307 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800308 static final int VISIBLE_APP_MEM;
309 static final int FOREGROUND_APP_MEM;
310
311 // The minimum number of hidden apps we want to be able to keep around,
312 // without empty apps being able to push them out of memory.
313 static final int MIN_HIDDEN_APPS = 2;
314
Dianne Hackborn8633e682010-04-22 16:03:41 -0700315 // The maximum number of hidden processes we will keep around before
316 // killing them; this is just a control to not let us go too crazy with
317 // keeping around processes on devices with large amounts of RAM.
318 static final int MAX_HIDDEN_APPS = 15;
319
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800320 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700321 // been idle for less than 15 seconds.
322 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800323
324 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700325 // been idle for less than 120 seconds.
326 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800327
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700328 static int getIntProp(String name, boolean allowZero) {
329 String str = SystemProperties.get(name);
330 if (str == null) {
331 throw new IllegalArgumentException("Property not defined: " + name);
332 }
333 int val = Integer.valueOf(str);
334 if (val == 0 && !allowZero) {
335 throw new IllegalArgumentException("Property must not be zero: " + name);
336 }
337 return val;
338 }
339
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800340 static {
341 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700342 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
343 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
344 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
345 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
346 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
347 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
348 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
349 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
350 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
351 // These days we use the last empty slot for hidden apps as well.
352 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
353 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
354 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
355 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
356 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
357 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
358 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
359 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
360 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
361 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363
Dan Egnor42471dd2010-01-07 17:25:22 -0800364 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365
366 static final String[] EMPTY_STRING_ARRAY = new String[0];
367
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700368 public ActivityStack mMainStack;
369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700371 * Description of a request to start a new activity, which has been held
372 * due to app switches being disabled.
373 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700374 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700375 ActivityRecord r;
376 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700377 Uri[] grantedUriPermissions;
378 int grantedMode;
379 boolean onlyIfNeeded;
380 }
381
382 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
383 = new ArrayList<PendingActivityLaunch>();
384
385 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 * List of all active broadcasts that are to be executed immediately
387 * (without waiting for another broadcast to finish). Currently this only
388 * contains broadcasts to registered receivers, to avoid spinning up
389 * a bunch of processes to execute IntentReceiver components.
390 */
391 final ArrayList<BroadcastRecord> mParallelBroadcasts
392 = new ArrayList<BroadcastRecord>();
393
394 /**
395 * List of all active broadcasts that are to be executed one at a time.
396 * The object at the top of the list is the currently activity broadcasts;
397 * those after it are waiting for the top to finish..
398 */
399 final ArrayList<BroadcastRecord> mOrderedBroadcasts
400 = new ArrayList<BroadcastRecord>();
401
402 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800403 * Historical data of past broadcasts, for debugging.
404 */
405 static final int MAX_BROADCAST_HISTORY = 100;
406 final BroadcastRecord[] mBroadcastHistory
407 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
408
409 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 * Set when we current have a BROADCAST_INTENT_MSG in flight.
411 */
412 boolean mBroadcastsScheduled = false;
413
414 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 * Activity we have told the window manager to have key focus.
416 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700417 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700418 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 * List of intents that were used to start the most recent tasks.
420 */
421 final ArrayList<TaskRecord> mRecentTasks
422 = new ArrayList<TaskRecord>();
423
424 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 * All of the applications we currently have running organized by name.
426 * The keys are strings of the application package name (as
427 * returned by the package manager), and the keys are ApplicationRecord
428 * objects.
429 */
430 final ProcessMap<ProcessRecord> mProcessNames
431 = new ProcessMap<ProcessRecord>();
432
433 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700434 * The currently running heavy-weight process, if any.
435 */
436 ProcessRecord mHeavyWeightProcess = null;
437
438 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 * The last time that various processes have crashed.
440 */
441 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
442
443 /**
444 * Set of applications that we consider to be bad, and will reject
445 * incoming broadcasts from (which the user has no control over).
446 * Processes are added to this set when they have crashed twice within
447 * a minimum amount of time; they are removed from it when they are
448 * later restarted (hopefully due to some user action). The value is the
449 * time it was added to the list.
450 */
451 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
452
453 /**
454 * All of the processes we currently have running organized by pid.
455 * The keys are the pid running the application.
456 *
457 * <p>NOTE: This object is protected by its own lock, NOT the global
458 * activity manager lock!
459 */
460 final SparseArray<ProcessRecord> mPidsSelfLocked
461 = new SparseArray<ProcessRecord>();
462
463 /**
464 * All of the processes that have been forced to be foreground. The key
465 * is the pid of the caller who requested it (we hold a death
466 * link on it).
467 */
468 abstract class ForegroundToken implements IBinder.DeathRecipient {
469 int pid;
470 IBinder token;
471 }
472 final SparseArray<ForegroundToken> mForegroundProcesses
473 = new SparseArray<ForegroundToken>();
474
475 /**
476 * List of records for processes that someone had tried to start before the
477 * system was ready. We don't start them at that point, but ensure they
478 * are started by the time booting is complete.
479 */
480 final ArrayList<ProcessRecord> mProcessesOnHold
481 = new ArrayList<ProcessRecord>();
482
483 /**
484 * List of records for processes that we have started and are waiting
485 * for them to call back. This is really only needed when running in
486 * single processes mode, in which case we do not have a unique pid for
487 * each process.
488 */
489 final ArrayList<ProcessRecord> mStartingProcesses
490 = new ArrayList<ProcessRecord>();
491
492 /**
493 * List of persistent applications that are in the process
494 * of being started.
495 */
496 final ArrayList<ProcessRecord> mPersistentStartingProcesses
497 = new ArrayList<ProcessRecord>();
498
499 /**
500 * Processes that are being forcibly torn down.
501 */
502 final ArrayList<ProcessRecord> mRemovedProcesses
503 = new ArrayList<ProcessRecord>();
504
505 /**
506 * List of running applications, sorted by recent usage.
507 * The first entry in the list is the least recently used.
508 * It contains ApplicationRecord objects. This list does NOT include
509 * any persistent application records (since we never want to exit them).
510 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800511 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 = new ArrayList<ProcessRecord>();
513
514 /**
515 * List of processes that should gc as soon as things are idle.
516 */
517 final ArrayList<ProcessRecord> mProcessesToGc
518 = new ArrayList<ProcessRecord>();
519
520 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800521 * This is the process holding what we currently consider to be
522 * the "home" activity.
523 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700524 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800525
526 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527 * Set of PendingResultRecord objects that are currently active.
528 */
529 final HashSet mPendingResultRecords = new HashSet();
530
531 /**
532 * Set of IntentSenderRecord objects that are currently active.
533 */
534 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
535 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
536
537 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700538 * Fingerprints (String.hashCode()) of stack traces that we've
539 * already logged DropBox entries for. Guarded by itself. If
540 * something (rogue user app) forces this over
541 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
542 */
543 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
544 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
545
546 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700547 * Strict Mode background batched logging state.
548 *
549 * The string buffer is guarded by itself, and its lock is also
550 * used to determine if another batched write is already
551 * in-flight.
552 */
553 private final StringBuilder mStrictModeBuffer = new StringBuilder();
554
555 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 * Intent broadcast that we have tried to start, but are
557 * waiting for its application's process to be created. We only
558 * need one (instead of a list) because we always process broadcasts
559 * one at a time, so no others can be started while waiting for this
560 * one.
561 */
562 BroadcastRecord mPendingBroadcast = null;
563
564 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700565 * The receiver index that is pending, to restart the broadcast if needed.
566 */
567 int mPendingBroadcastRecvIndex;
568
569 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 * Keeps track of all IIntentReceivers that have been registered for
571 * broadcasts. Hash keys are the receiver IBinder, hash value is
572 * a ReceiverList.
573 */
574 final HashMap mRegisteredReceivers = new HashMap();
575
576 /**
577 * Resolver for broadcast intents to registered receivers.
578 * Holds BroadcastFilter (subclass of IntentFilter).
579 */
580 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
581 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
582 @Override
583 protected boolean allowFilterResult(
584 BroadcastFilter filter, List<BroadcastFilter> dest) {
585 IBinder target = filter.receiverList.receiver.asBinder();
586 for (int i=dest.size()-1; i>=0; i--) {
587 if (dest.get(i).receiverList.receiver.asBinder() == target) {
588 return false;
589 }
590 }
591 return true;
592 }
593 };
594
595 /**
596 * State of all active sticky broadcasts. Keys are the action of the
597 * sticky Intent, values are an ArrayList of all broadcasted intents with
598 * that action (which should usually be one).
599 */
600 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
601 new HashMap<String, ArrayList<Intent>>();
602
603 /**
604 * All currently running services.
605 */
606 final HashMap<ComponentName, ServiceRecord> mServices =
607 new HashMap<ComponentName, ServiceRecord>();
608
609 /**
610 * All currently running services indexed by the Intent used to start them.
611 */
612 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
613 new HashMap<Intent.FilterComparison, ServiceRecord>();
614
615 /**
616 * All currently bound service connections. Keys are the IBinder of
617 * the client's IServiceConnection.
618 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700619 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
620 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621
622 /**
623 * List of services that we have been asked to start,
624 * but haven't yet been able to. It is used to hold start requests
625 * while waiting for their corresponding application thread to get
626 * going.
627 */
628 final ArrayList<ServiceRecord> mPendingServices
629 = new ArrayList<ServiceRecord>();
630
631 /**
632 * List of services that are scheduled to restart following a crash.
633 */
634 final ArrayList<ServiceRecord> mRestartingServices
635 = new ArrayList<ServiceRecord>();
636
637 /**
638 * List of services that are in the process of being stopped.
639 */
640 final ArrayList<ServiceRecord> mStoppingServices
641 = new ArrayList<ServiceRecord>();
642
643 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700644 * Backup/restore process management
645 */
646 String mBackupAppName = null;
647 BackupRecord mBackupTarget = null;
648
649 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650 * List of PendingThumbnailsRecord objects of clients who are still
651 * waiting to receive all of the thumbnails for a task.
652 */
653 final ArrayList mPendingThumbnails = new ArrayList();
654
655 /**
656 * List of HistoryRecord objects that have been finished and must
657 * still report back to a pending thumbnail receiver.
658 */
659 final ArrayList mCancelledThumbnails = new ArrayList();
660
661 /**
662 * All of the currently running global content providers. Keys are a
663 * string containing the provider name and values are a
664 * ContentProviderRecord object containing the data about it. Note
665 * that a single provider may be published under multiple names, so
666 * there may be multiple entries here for a single one in mProvidersByClass.
667 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700668 final HashMap<String, ContentProviderRecord> mProvidersByName
669 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670
671 /**
672 * All of the currently running global content providers. Keys are a
673 * string containing the provider's implementation class and values are a
674 * ContentProviderRecord object containing the data about it.
675 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700676 final HashMap<String, ContentProviderRecord> mProvidersByClass
677 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678
679 /**
680 * List of content providers who have clients waiting for them. The
681 * application is currently being launched and the provider will be
682 * removed from this list once it is published.
683 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700684 final ArrayList<ContentProviderRecord> mLaunchingProviders
685 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686
687 /**
688 * Global set of specific Uri permissions that have been granted.
689 */
690 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
691 = new SparseArray<HashMap<Uri, UriPermission>>();
692
693 /**
694 * Thread-local storage used to carry caller permissions over through
695 * indirect content-provider access.
696 * @see #ActivityManagerService.openContentUri()
697 */
698 private class Identity {
699 public int pid;
700 public int uid;
701
702 Identity(int _pid, int _uid) {
703 pid = _pid;
704 uid = _uid;
705 }
706 }
707 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
708
709 /**
710 * All information we have collected about the runtime performance of
711 * any user id that can impact battery performance.
712 */
713 final BatteryStatsService mBatteryStatsService;
714
715 /**
716 * information about component usage
717 */
718 final UsageStatsService mUsageStatsService;
719
720 /**
721 * Current configuration information. HistoryRecord objects are given
722 * a reference to this object to indicate which configuration they are
723 * currently running in, so this object must be kept immutable.
724 */
725 Configuration mConfiguration = new Configuration();
726
727 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800728 * Current sequencing integer of the configuration, for skipping old
729 * configurations.
730 */
731 int mConfigurationSeq = 0;
732
733 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700734 * Hardware-reported OpenGLES version.
735 */
736 final int GL_ES_VERSION;
737
738 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 * List of initialization arguments to pass to all processes when binding applications to them.
740 * For example, references to the commonly used services.
741 */
742 HashMap<String, IBinder> mAppBindArgs;
743
744 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700745 * Temporary to avoid allocations. Protected by main lock.
746 */
747 final StringBuilder mStringBuilder = new StringBuilder(256);
748
749 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 * Used to control how we initialize the service.
751 */
752 boolean mStartRunning = false;
753 ComponentName mTopComponent;
754 String mTopAction;
755 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700756 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 boolean mSystemReady = false;
758 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700759 boolean mWaitingUpdate = false;
760 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700761 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700762 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763
764 Context mContext;
765
766 int mFactoryTest;
767
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700768 boolean mCheckedForSetup;
769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700771 * The time at which we will allow normal application switches again,
772 * after a call to {@link #stopAppSwitches()}.
773 */
774 long mAppSwitchesAllowedTime;
775
776 /**
777 * This is set to true after the first switch after mAppSwitchesAllowedTime
778 * is set; any switches after that will clear the time.
779 */
780 boolean mDidAppSwitch;
781
782 /**
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700783 * Last time (in realtime) at which we checked for wake lock usage.
784 */
785 long mLastWakeLockCheckTime;
786
787 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 * Set while we are wanting to sleep, to prevent any
789 * activities from being started/resumed.
790 */
791 boolean mSleeping = false;
792
793 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700794 * Set if we are shutting down the system, similar to sleeping.
795 */
796 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797
798 /**
799 * Task identifier that activities are currently being started
800 * in. Incremented each time a new task is created.
801 * todo: Replace this with a TokenSpace class that generates non-repeating
802 * integers that won't wrap.
803 */
804 int mCurTask = 1;
805
806 /**
807 * Current sequence id for oom_adj computation traversal.
808 */
809 int mAdjSeq = 0;
810
811 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700812 * Current sequence id for process LRU updating.
813 */
814 int mLruSeq = 0;
815
816 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
818 * is set, indicating the user wants processes started in such a way
819 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
820 * running in each process (thus no pre-initialized process, etc).
821 */
822 boolean mSimpleProcessManagement = false;
823
824 /**
825 * System monitoring: number of processes that died since the last
826 * N procs were started.
827 */
828 int[] mProcDeaths = new int[20];
829
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700830 /**
831 * This is set if we had to do a delayed dexopt of an app before launching
832 * it, to increasing the ANR timeouts in that case.
833 */
834 boolean mDidDexOpt;
835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 String mDebugApp = null;
837 boolean mWaitForDebugger = false;
838 boolean mDebugTransient = false;
839 String mOrigDebugApp = null;
840 boolean mOrigWaitForDebugger = false;
841 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700842 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700844 final RemoteCallbackList<IActivityWatcher> mWatchers
845 = new RemoteCallbackList<IActivityWatcher>();
846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 /**
848 * Callback of last caller to {@link #requestPss}.
849 */
850 Runnable mRequestPssCallback;
851
852 /**
853 * Remaining processes for which we are waiting results from the last
854 * call to {@link #requestPss}.
855 */
856 final ArrayList<ProcessRecord> mRequestPssList
857 = new ArrayList<ProcessRecord>();
858
859 /**
860 * Runtime statistics collection thread. This object's lock is used to
861 * protect all related state.
862 */
863 final Thread mProcessStatsThread;
864
865 /**
866 * Used to collect process stats when showing not responding dialog.
867 * Protected by mProcessStatsThread.
868 */
869 final ProcessStats mProcessStats = new ProcessStats(
870 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700871 final AtomicLong mLastCpuTime = new AtomicLong(0);
872 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 long mLastWriteTime = 0;
875
876 /**
877 * Set to true after the system has finished booting.
878 */
879 boolean mBooted = false;
880
881 int mProcessLimit = 0;
882
883 WindowManagerService mWindowManager;
884
885 static ActivityManagerService mSelf;
886 static ActivityThread mSystemThread;
887
888 private final class AppDeathRecipient implements IBinder.DeathRecipient {
889 final ProcessRecord mApp;
890 final int mPid;
891 final IApplicationThread mAppThread;
892
893 AppDeathRecipient(ProcessRecord app, int pid,
894 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800895 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800896 TAG, "New death recipient " + this
897 + " for thread " + thread.asBinder());
898 mApp = app;
899 mPid = pid;
900 mAppThread = thread;
901 }
902
903 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800904 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 TAG, "Death received in " + this
906 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 synchronized(ActivityManagerService.this) {
908 appDiedLocked(mApp, mPid, mAppThread);
909 }
910 }
911 }
912
913 static final int SHOW_ERROR_MSG = 1;
914 static final int SHOW_NOT_RESPONDING_MSG = 2;
915 static final int SHOW_FACTORY_ERROR_MSG = 3;
916 static final int UPDATE_CONFIGURATION_MSG = 4;
917 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
918 static final int WAIT_FOR_DEBUGGER_MSG = 6;
919 static final int BROADCAST_INTENT_MSG = 7;
920 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 static final int SERVICE_TIMEOUT_MSG = 12;
922 static final int UPDATE_TIME_ZONE = 13;
923 static final int SHOW_UID_ERROR_MSG = 14;
924 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700926 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700927 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800928 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700929 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
930 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700931 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700932 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933
934 AlertDialog mUidAlert;
935
936 final Handler mHandler = new Handler() {
937 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800938 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 //}
940
941 public void handleMessage(Message msg) {
942 switch (msg.what) {
943 case SHOW_ERROR_MSG: {
944 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 synchronized (ActivityManagerService.this) {
946 ProcessRecord proc = (ProcessRecord)data.get("app");
947 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800948 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 return;
950 }
951 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700952 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800953 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 d.show();
955 proc.crashDialog = d;
956 } else {
957 // The device is asleep, so just pretend that the user
958 // saw a crash dialog and hit "force quit".
959 res.set(0);
960 }
961 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700962
963 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 } break;
965 case SHOW_NOT_RESPONDING_MSG: {
966 synchronized (ActivityManagerService.this) {
967 HashMap data = (HashMap) msg.obj;
968 ProcessRecord proc = (ProcessRecord)data.get("app");
969 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800970 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 return;
972 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800973
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700974 Intent intent = new Intent("android.intent.action.ANR");
975 if (!mProcessesReady) {
976 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
977 }
978 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -0800979 null, null, 0, null, null, null,
980 false, false, MY_PID, Process.SYSTEM_UID);
981
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700983 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 d.show();
985 proc.anrDialog = d;
986 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700987
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700988 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700990 case SHOW_STRICT_MODE_VIOLATION_MSG: {
991 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
992 synchronized (ActivityManagerService.this) {
993 ProcessRecord proc = (ProcessRecord) data.get("app");
994 if (proc == null) {
995 Slog.e(TAG, "App not found when showing strict mode dialog.");
996 break;
997 }
998 if (proc.crashDialog != null) {
999 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1000 return;
1001 }
1002 AppErrorResult res = (AppErrorResult) data.get("result");
1003 if (!mSleeping && !mShuttingDown) {
1004 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1005 d.show();
1006 proc.crashDialog = d;
1007 } else {
1008 // The device is asleep, so just pretend that the user
1009 // saw a crash dialog and hit "force quit".
1010 res.set(0);
1011 }
1012 }
1013 ensureBootCompleted();
1014 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 case SHOW_FACTORY_ERROR_MSG: {
1016 Dialog d = new FactoryErrorDialog(
1017 mContext, msg.getData().getCharSequence("msg"));
1018 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001019 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 } break;
1021 case UPDATE_CONFIGURATION_MSG: {
1022 final ContentResolver resolver = mContext.getContentResolver();
1023 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1024 } break;
1025 case GC_BACKGROUND_PROCESSES_MSG: {
1026 synchronized (ActivityManagerService.this) {
1027 performAppGcsIfAppropriateLocked();
1028 }
1029 } break;
1030 case WAIT_FOR_DEBUGGER_MSG: {
1031 synchronized (ActivityManagerService.this) {
1032 ProcessRecord app = (ProcessRecord)msg.obj;
1033 if (msg.arg1 != 0) {
1034 if (!app.waitedForDebugger) {
1035 Dialog d = new AppWaitingForDebuggerDialog(
1036 ActivityManagerService.this,
1037 mContext, app);
1038 app.waitDialog = d;
1039 app.waitedForDebugger = true;
1040 d.show();
1041 }
1042 } else {
1043 if (app.waitDialog != null) {
1044 app.waitDialog.dismiss();
1045 app.waitDialog = null;
1046 }
1047 }
1048 }
1049 } break;
1050 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001051 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 TAG, "Received BROADCAST_INTENT_MSG");
1053 processNextBroadcast(true);
1054 } break;
1055 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001056 if (mDidDexOpt) {
1057 mDidDexOpt = false;
1058 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1059 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1060 return;
1061 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001062 // Only process broadcast timeouts if the system is ready. That way
1063 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1064 // to do heavy lifting for system up
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001065 if (mProcessesReady) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001066 broadcastTimeout();
1067 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001070 if (mDidDexOpt) {
1071 mDidDexOpt = false;
1072 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1073 nmsg.obj = msg.obj;
1074 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1075 return;
1076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 serviceTimeout((ProcessRecord)msg.obj);
1078 } break;
1079 case UPDATE_TIME_ZONE: {
1080 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001081 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1082 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083 if (r.thread != null) {
1084 try {
1085 r.thread.updateTimeZone();
1086 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001087 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 }
1089 }
1090 }
1091 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001092 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 case SHOW_UID_ERROR_MSG: {
1094 // XXX This is a temporary dialog, no need to localize.
1095 AlertDialog d = new BaseErrorDialog(mContext);
1096 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1097 d.setCancelable(false);
1098 d.setTitle("System UIDs Inconsistent");
1099 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 +02001100 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1102 mUidAlert = d;
1103 d.show();
1104 } break;
1105 case IM_FEELING_LUCKY_MSG: {
1106 if (mUidAlert != null) {
1107 mUidAlert.dismiss();
1108 mUidAlert = null;
1109 }
1110 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001112 if (mDidDexOpt) {
1113 mDidDexOpt = false;
1114 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1115 nmsg.obj = msg.obj;
1116 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1117 return;
1118 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 ProcessRecord app = (ProcessRecord)msg.obj;
1120 synchronized (ActivityManagerService.this) {
1121 processStartTimedOutLocked(app);
1122 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001123 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001124 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1125 synchronized (ActivityManagerService.this) {
1126 doPendingActivityLaunchesLocked(true);
1127 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001128 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001129 case KILL_APPLICATION_MSG: {
1130 synchronized (ActivityManagerService.this) {
1131 int uid = msg.arg1;
1132 boolean restart = (msg.arg2 == 1);
1133 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001134 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001135 }
1136 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001137 case FINALIZE_PENDING_INTENT_MSG: {
1138 ((PendingIntentRecord)msg.obj).completeFinalize();
1139 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001140 case POST_HEAVY_NOTIFICATION_MSG: {
1141 INotificationManager inm = NotificationManager.getService();
1142 if (inm == null) {
1143 return;
1144 }
1145
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001146 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001147 ProcessRecord process = root.app;
1148 if (process == null) {
1149 return;
1150 }
1151
1152 try {
1153 Context context = mContext.createPackageContext(process.info.packageName, 0);
1154 String text = mContext.getString(R.string.heavy_weight_notification,
1155 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1156 Notification notification = new Notification();
1157 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1158 notification.when = 0;
1159 notification.flags = Notification.FLAG_ONGOING_EVENT;
1160 notification.tickerText = text;
1161 notification.defaults = 0; // please be quiet
1162 notification.sound = null;
1163 notification.vibrate = null;
1164 notification.setLatestEventInfo(context, text,
1165 mContext.getText(R.string.heavy_weight_notification_detail),
1166 PendingIntent.getActivity(mContext, 0, root.intent,
1167 PendingIntent.FLAG_CANCEL_CURRENT));
1168
1169 try {
1170 int[] outId = new int[1];
1171 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1172 notification, outId);
1173 } catch (RuntimeException e) {
1174 Slog.w(ActivityManagerService.TAG,
1175 "Error showing notification for heavy-weight app", e);
1176 } catch (RemoteException e) {
1177 }
1178 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001179 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001180 }
1181 } break;
1182 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1183 INotificationManager inm = NotificationManager.getService();
1184 if (inm == null) {
1185 return;
1186 }
1187 try {
1188 inm.cancelNotification("android",
1189 R.string.heavy_weight_notification);
1190 } catch (RuntimeException e) {
1191 Slog.w(ActivityManagerService.TAG,
1192 "Error canceling notification for service", e);
1193 } catch (RemoteException e) {
1194 }
1195 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001196 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1197 synchronized (ActivityManagerService.this) {
1198 checkExcessiveWakeLocksLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001199 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001200 if (mSleeping) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001201 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1202 sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001203 }
1204 }
1205 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 }
1207 }
1208 };
1209
1210 public static void setSystemProcess() {
1211 try {
1212 ActivityManagerService m = mSelf;
1213
1214 ServiceManager.addService("activity", m);
1215 ServiceManager.addService("meminfo", new MemBinder(m));
1216 if (MONITOR_CPU_USAGE) {
1217 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001219 ServiceManager.addService("permission", new PermissionController(m));
1220
1221 ApplicationInfo info =
1222 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001223 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001224 mSystemThread.installSystemApplicationInfo(info);
1225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 synchronized (mSelf) {
1227 ProcessRecord app = mSelf.newProcessRecordLocked(
1228 mSystemThread.getApplicationThread(), info,
1229 info.processName);
1230 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001231 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232 app.maxAdj = SYSTEM_ADJ;
1233 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1234 synchronized (mSelf.mPidsSelfLocked) {
1235 mSelf.mPidsSelfLocked.put(app.pid, app);
1236 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001237 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 }
1239 } catch (PackageManager.NameNotFoundException e) {
1240 throw new RuntimeException(
1241 "Unable to find android system package", e);
1242 }
1243 }
1244
1245 public void setWindowManager(WindowManagerService wm) {
1246 mWindowManager = wm;
1247 }
1248
1249 public static final Context main(int factoryTest) {
1250 AThread thr = new AThread();
1251 thr.start();
1252
1253 synchronized (thr) {
1254 while (thr.mService == null) {
1255 try {
1256 thr.wait();
1257 } catch (InterruptedException e) {
1258 }
1259 }
1260 }
1261
1262 ActivityManagerService m = thr.mService;
1263 mSelf = m;
1264 ActivityThread at = ActivityThread.systemMain();
1265 mSystemThread = at;
1266 Context context = at.getSystemContext();
1267 m.mContext = context;
1268 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001269 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270
1271 m.mBatteryStatsService.publish(context);
1272 m.mUsageStatsService.publish(context);
1273
1274 synchronized (thr) {
1275 thr.mReady = true;
1276 thr.notifyAll();
1277 }
1278
1279 m.startRunning(null, null, null, null);
1280
1281 return context;
1282 }
1283
1284 public static ActivityManagerService self() {
1285 return mSelf;
1286 }
1287
1288 static class AThread extends Thread {
1289 ActivityManagerService mService;
1290 boolean mReady = false;
1291
1292 public AThread() {
1293 super("ActivityManager");
1294 }
1295
1296 public void run() {
1297 Looper.prepare();
1298
1299 android.os.Process.setThreadPriority(
1300 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001301 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001302
1303 ActivityManagerService m = new ActivityManagerService();
1304
1305 synchronized (this) {
1306 mService = m;
1307 notifyAll();
1308 }
1309
1310 synchronized (this) {
1311 while (!mReady) {
1312 try {
1313 wait();
1314 } catch (InterruptedException e) {
1315 }
1316 }
1317 }
1318
1319 Looper.loop();
1320 }
1321 }
1322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001323 static class MemBinder extends Binder {
1324 ActivityManagerService mActivityManagerService;
1325 MemBinder(ActivityManagerService activityManagerService) {
1326 mActivityManagerService = activityManagerService;
1327 }
1328
1329 @Override
1330 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1331 ActivityManagerService service = mActivityManagerService;
1332 ArrayList<ProcessRecord> procs;
1333 synchronized (mActivityManagerService) {
1334 if (args != null && args.length > 0
1335 && args[0].charAt(0) != '-') {
1336 procs = new ArrayList<ProcessRecord>();
1337 int pid = -1;
1338 try {
1339 pid = Integer.parseInt(args[0]);
1340 } catch (NumberFormatException e) {
1341
1342 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001343 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1344 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345 if (proc.pid == pid) {
1346 procs.add(proc);
1347 } else if (proc.processName.equals(args[0])) {
1348 procs.add(proc);
1349 }
1350 }
1351 if (procs.size() <= 0) {
1352 pw.println("No process found for: " + args[0]);
1353 return;
1354 }
1355 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001356 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 }
1358 }
1359 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1360 }
1361 }
1362
1363 static class CpuBinder extends Binder {
1364 ActivityManagerService mActivityManagerService;
1365 CpuBinder(ActivityManagerService activityManagerService) {
1366 mActivityManagerService = activityManagerService;
1367 }
1368
1369 @Override
1370 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1371 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001372 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1373 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1374 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 }
1376 }
1377 }
1378
1379 private ActivityManagerService() {
1380 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1381 if (v != null && Integer.getInteger(v) != 0) {
1382 mSimpleProcessManagement = true;
1383 }
1384 v = System.getenv("ANDROID_DEBUG_APP");
1385 if (v != null) {
1386 mSimpleProcessManagement = true;
1387 }
1388
Joe Onorato8a9b2202010-02-26 18:56:32 -08001389 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 File dataDir = Environment.getDataDirectory();
1392 File systemDir = new File(dataDir, "system");
1393 systemDir.mkdirs();
1394 mBatteryStatsService = new BatteryStatsService(new File(
1395 systemDir, "batterystats.bin").toString());
1396 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001397 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001398 mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
1399 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001401 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001402 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403
Jack Palevichb90d28c2009-07-22 15:35:24 -07001404 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1405 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1406
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001407 mConfiguration.setToDefaults();
1408 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 mProcessStats.init();
1410
1411 // Add ourself to the Watchdog monitors.
1412 Watchdog.getInstance().addMonitor(this);
1413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 mProcessStatsThread = new Thread("ProcessStats") {
1415 public void run() {
1416 while (true) {
1417 try {
1418 try {
1419 synchronized(this) {
1420 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001421 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001423 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 // + ", write delay=" + nextWriteDelay);
1425 if (nextWriteDelay < nextCpuDelay) {
1426 nextCpuDelay = nextWriteDelay;
1427 }
1428 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001429 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 this.wait(nextCpuDelay);
1431 }
1432 }
1433 } catch (InterruptedException e) {
1434 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 updateCpuStatsNow();
1436 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001437 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 }
1439 }
1440 }
1441 };
1442 mProcessStatsThread.start();
1443 }
1444
1445 @Override
1446 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1447 throws RemoteException {
1448 try {
1449 return super.onTransact(code, data, reply, flags);
1450 } catch (RuntimeException e) {
1451 // The activity manager only throws security exceptions, so let's
1452 // log all others.
1453 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001454 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 }
1456 throw e;
1457 }
1458 }
1459
1460 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001461 final long now = SystemClock.uptimeMillis();
1462 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1463 return;
1464 }
1465 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1466 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 mProcessStatsThread.notify();
1468 }
1469 }
1470 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 void updateCpuStatsNow() {
1473 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001474 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 final long now = SystemClock.uptimeMillis();
1476 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001479 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1480 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 haveNewCpuStats = true;
1482 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001483 //Slog.i(TAG, mProcessStats.printCurrentState());
1484 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 // + mProcessStats.getTotalCpuPercent() + "%");
1486
Joe Onorato8a9b2202010-02-26 18:56:32 -08001487 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 if ("true".equals(SystemProperties.get("events.cpu"))) {
1489 int user = mProcessStats.getLastUserTime();
1490 int system = mProcessStats.getLastSystemTime();
1491 int iowait = mProcessStats.getLastIoWaitTime();
1492 int irq = mProcessStats.getLastIrqTime();
1493 int softIrq = mProcessStats.getLastSoftIrqTime();
1494 int idle = mProcessStats.getLastIdleTime();
1495
1496 int total = user + system + iowait + irq + softIrq + idle;
1497 if (total == 0) total = 1;
1498
Doug Zongker2bec3d42009-12-04 12:52:44 -08001499 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 ((user+system+iowait+irq+softIrq) * 100) / total,
1501 (user * 100) / total,
1502 (system * 100) / total,
1503 (iowait * 100) / total,
1504 (irq * 100) / total,
1505 (softIrq * 100) / total);
1506 }
1507 }
1508
Amith Yamasanie43530a2009-08-21 13:11:37 -07001509 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001510 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001511 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 synchronized(mPidsSelfLocked) {
1513 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001514 if (mOnBattery) {
1515 int perc = bstats.startAddingCpuLocked();
1516 int totalUTime = 0;
1517 int totalSTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 final int N = mProcessStats.countWorkingStats();
1519 for (int i=0; i<N; i++) {
1520 ProcessStats.Stats st
1521 = mProcessStats.getWorkingStats(i);
1522 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001523 int otherUTime = (st.rel_utime*perc)/100;
1524 int otherSTime = (st.rel_stime*perc)/100;
1525 totalUTime += otherUTime;
1526 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 if (pr != null) {
1528 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001529 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1530 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001531 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001532 } else {
1533 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001534 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001535 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001536 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1537 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001538 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 }
1541 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001542 bstats.finishAddingCpuLocked(perc, totalUTime,
1543 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 }
1545 }
1546 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1549 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001550 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 }
1552 }
1553 }
1554 }
1555
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001556 @Override
1557 public void batteryNeedsCpuUpdate() {
1558 updateCpuStatsNow();
1559 }
1560
1561 @Override
1562 public void batteryPowerChanged(boolean onBattery) {
1563 // When plugging in, update the CPU stats first before changing
1564 // the plug state.
1565 updateCpuStatsNow();
1566 synchronized (this) {
1567 synchronized(mPidsSelfLocked) {
1568 mOnBattery = onBattery;
1569 }
1570 }
1571 }
1572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 /**
1574 * Initialize the application bind args. These are passed to each
1575 * process when the bindApplication() IPC is sent to the process. They're
1576 * lazily setup to make sure the services are running when they're asked for.
1577 */
1578 private HashMap<String, IBinder> getCommonServicesLocked() {
1579 if (mAppBindArgs == null) {
1580 mAppBindArgs = new HashMap<String, IBinder>();
1581
1582 // Setup the application init args
1583 mAppBindArgs.put("package", ServiceManager.getService("package"));
1584 mAppBindArgs.put("window", ServiceManager.getService("window"));
1585 mAppBindArgs.put(Context.ALARM_SERVICE,
1586 ServiceManager.getService(Context.ALARM_SERVICE));
1587 }
1588 return mAppBindArgs;
1589 }
1590
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001591 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 if (mFocusedActivity != r) {
1593 mFocusedActivity = r;
1594 mWindowManager.setFocusedApp(r, true);
1595 }
1596 }
1597
Dianne Hackborn906497c2010-05-10 15:57:38 -07001598 private final void updateLruProcessInternalLocked(ProcessRecord app,
1599 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001601 int lrui = mLruProcesses.indexOf(app);
1602 if (lrui >= 0) mLruProcesses.remove(lrui);
1603
1604 int i = mLruProcesses.size()-1;
1605 int skipTop = 0;
1606
Dianne Hackborn906497c2010-05-10 15:57:38 -07001607 app.lruSeq = mLruSeq;
1608
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001609 // compute the new weight for this process.
1610 if (updateActivityTime) {
1611 app.lastActivityTime = SystemClock.uptimeMillis();
1612 }
1613 if (app.activities.size() > 0) {
1614 // If this process has activities, we more strongly want to keep
1615 // it around.
1616 app.lruWeight = app.lastActivityTime;
1617 } else if (app.pubProviders.size() > 0) {
1618 // If this process contains content providers, we want to keep
1619 // it a little more strongly.
1620 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1621 // Also don't let it kick out the first few "real" hidden processes.
1622 skipTop = MIN_HIDDEN_APPS;
1623 } else {
1624 // If this process doesn't have activities, we less strongly
1625 // want to keep it around, and generally want to avoid getting
1626 // in front of any very recently used activities.
1627 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1628 // Also don't let it kick out the first few "real" hidden processes.
1629 skipTop = MIN_HIDDEN_APPS;
1630 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001631
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001632 while (i >= 0) {
1633 ProcessRecord p = mLruProcesses.get(i);
1634 // If this app shouldn't be in front of the first N background
1635 // apps, then skip over that many that are currently hidden.
1636 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1637 skipTop--;
1638 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001639 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001640 mLruProcesses.add(i+1, app);
1641 break;
1642 }
1643 i--;
1644 }
1645 if (i < 0) {
1646 mLruProcesses.add(0, app);
1647 }
1648
Dianne Hackborn906497c2010-05-10 15:57:38 -07001649 // If the app is currently using a content provider or service,
1650 // bump those processes as well.
1651 if (app.connections.size() > 0) {
1652 for (ConnectionRecord cr : app.connections) {
1653 if (cr.binding != null && cr.binding.service != null
1654 && cr.binding.service.app != null
1655 && cr.binding.service.app.lruSeq != mLruSeq) {
1656 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1657 updateActivityTime, i+1);
1658 }
1659 }
1660 }
1661 if (app.conProviders.size() > 0) {
1662 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1663 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1664 updateLruProcessInternalLocked(cpr.app, oomAdj,
1665 updateActivityTime, i+1);
1666 }
1667 }
1668 }
1669
Joe Onorato8a9b2202010-02-26 18:56:32 -08001670 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 if (oomAdj) {
1672 updateOomAdjLocked();
1673 }
1674 }
1675
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001676 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001677 boolean oomAdj, boolean updateActivityTime) {
1678 mLruSeq++;
1679 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1680 }
1681
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001682 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 String processName, int uid) {
1684 if (uid == Process.SYSTEM_UID) {
1685 // The system gets to run in any process. If there are multiple
1686 // processes with the same uid, just pick the first (this
1687 // should never happen).
1688 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1689 processName);
1690 return procs != null ? procs.valueAt(0) : null;
1691 }
1692 ProcessRecord proc = mProcessNames.get(processName, uid);
1693 return proc;
1694 }
1695
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001696 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001697 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001698 try {
1699 if (pm.performDexOpt(packageName)) {
1700 mDidDexOpt = true;
1701 }
1702 } catch (RemoteException e) {
1703 }
1704 }
1705
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001706 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001707 int transit = mWindowManager.getPendingAppTransition();
1708 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1709 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1710 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1711 }
1712
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001713 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001715 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1717 // We don't have to do anything more if:
1718 // (1) There is an existing application record; and
1719 // (2) The caller doesn't think it is dead, OR there is no thread
1720 // object attached to it so we know it couldn't have crashed; and
1721 // (3) There is a pid assigned to it, so it is either starting or
1722 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001723 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 + " app=" + app + " knownToBeDead=" + knownToBeDead
1725 + " thread=" + (app != null ? app.thread : null)
1726 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001727 if (app != null && app.pid > 0) {
1728 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001729 // We already have the app running, or are waiting for it to
1730 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001731 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001732 return app;
1733 } else {
1734 // An application record is attached to a previous process,
1735 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001736 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001737 handleAppDiedLocked(app, true);
1738 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 String hostingNameStr = hostingName != null
1742 ? hostingName.flattenToShortString() : null;
1743
1744 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1745 // If we are in the background, then check to see if this process
1746 // is bad. If so, we will just silently fail.
1747 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001748 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1749 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001750 return null;
1751 }
1752 } else {
1753 // When the user is explicitly starting a process, then clear its
1754 // crash count so that we won't make it bad until they see at
1755 // least one crash dialog again, and make the process good again
1756 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001757 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1758 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 mProcessCrashTimes.remove(info.processName, info.uid);
1760 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001761 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 info.processName);
1763 mBadProcesses.remove(info.processName, info.uid);
1764 if (app != null) {
1765 app.bad = false;
1766 }
1767 }
1768 }
1769
1770 if (app == null) {
1771 app = newProcessRecordLocked(null, info, processName);
1772 mProcessNames.put(processName, info.uid, app);
1773 } else {
1774 // If this is a new package in the process, add the package to the list
1775 app.addPackage(info.packageName);
1776 }
1777
1778 // If the system is not ready yet, then hold off on starting this
1779 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001780 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001781 && !isAllowedWhileBooting(info)
1782 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 if (!mProcessesOnHold.contains(app)) {
1784 mProcessesOnHold.add(app);
1785 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001786 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 return app;
1788 }
1789
1790 startProcessLocked(app, hostingType, hostingNameStr);
1791 return (app.pid != 0) ? app : null;
1792 }
1793
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001794 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1795 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1796 }
1797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 private final void startProcessLocked(ProcessRecord app,
1799 String hostingType, String hostingNameStr) {
1800 if (app.pid > 0 && app.pid != MY_PID) {
1801 synchronized (mPidsSelfLocked) {
1802 mPidsSelfLocked.remove(app.pid);
1803 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1804 }
1805 app.pid = 0;
1806 }
1807
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001808 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1809 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810 mProcessesOnHold.remove(app);
1811
1812 updateCpuStats();
1813
1814 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1815 mProcDeaths[0] = 0;
1816
1817 try {
1818 int uid = app.info.uid;
1819 int[] gids = null;
1820 try {
1821 gids = mContext.getPackageManager().getPackageGids(
1822 app.info.packageName);
1823 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001824 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 }
1826 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1827 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1828 && mTopComponent != null
1829 && app.processName.equals(mTopComponent.getPackageName())) {
1830 uid = 0;
1831 }
1832 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1833 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1834 uid = 0;
1835 }
1836 }
1837 int debugFlags = 0;
1838 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1839 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1840 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001841 // Run the app in safe mode if its manifest requests so or the
1842 // system is booted in safe mode.
1843 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1844 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001845 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1846 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1848 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1849 }
1850 if ("1".equals(SystemProperties.get("debug.assert"))) {
1851 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1852 }
1853 int pid = Process.start("android.app.ActivityThread",
1854 mSimpleProcessManagement ? app.processName : null, uid, uid,
1855 gids, debugFlags, null);
1856 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1857 synchronized (bs) {
1858 if (bs.isOnBattery()) {
1859 app.batteryStats.incStartsLocked();
1860 }
1861 }
1862
Doug Zongker2bec3d42009-12-04 12:52:44 -08001863 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864 app.processName, hostingType,
1865 hostingNameStr != null ? hostingNameStr : "");
1866
1867 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001868 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 }
1870
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001871 StringBuilder buf = mStringBuilder;
1872 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 buf.append("Start proc ");
1874 buf.append(app.processName);
1875 buf.append(" for ");
1876 buf.append(hostingType);
1877 if (hostingNameStr != null) {
1878 buf.append(" ");
1879 buf.append(hostingNameStr);
1880 }
1881 buf.append(": pid=");
1882 buf.append(pid);
1883 buf.append(" uid=");
1884 buf.append(uid);
1885 buf.append(" gids={");
1886 if (gids != null) {
1887 for (int gi=0; gi<gids.length; gi++) {
1888 if (gi != 0) buf.append(", ");
1889 buf.append(gids[gi]);
1890
1891 }
1892 }
1893 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001894 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 if (pid == 0 || pid == MY_PID) {
1896 // Processes are being emulated with threads.
1897 app.pid = MY_PID;
1898 app.removed = false;
1899 mStartingProcesses.add(app);
1900 } else if (pid > 0) {
1901 app.pid = pid;
1902 app.removed = false;
1903 synchronized (mPidsSelfLocked) {
1904 this.mPidsSelfLocked.put(pid, app);
1905 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1906 msg.obj = app;
1907 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1908 }
1909 } else {
1910 app.pid = 0;
1911 RuntimeException e = new RuntimeException(
1912 "Failure starting process " + app.processName
1913 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001914 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 }
1916 } catch (RuntimeException e) {
1917 // XXX do better error recovery.
1918 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001919 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 }
1921 }
1922
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001923 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 if (resumed) {
1925 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1926 } else {
1927 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1928 }
1929 }
1930
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001931 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001932 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1933 && mTopAction == null) {
1934 // We are running in factory test mode, but unable to find
1935 // the factory test app, so just sit around displaying the
1936 // error message and don't try to start anything.
1937 return false;
1938 }
1939 Intent intent = new Intent(
1940 mTopAction,
1941 mTopData != null ? Uri.parse(mTopData) : null);
1942 intent.setComponent(mTopComponent);
1943 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1944 intent.addCategory(Intent.CATEGORY_HOME);
1945 }
1946 ActivityInfo aInfo =
1947 intent.resolveActivityInfo(mContext.getPackageManager(),
1948 STOCK_PM_FLAGS);
1949 if (aInfo != null) {
1950 intent.setComponent(new ComponentName(
1951 aInfo.applicationInfo.packageName, aInfo.name));
1952 // Don't do this if the home app is currently being
1953 // instrumented.
1954 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1955 aInfo.applicationInfo.uid);
1956 if (app == null || app.instrumentationClass == null) {
1957 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001958 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001959 null, null, 0, 0, 0, false, false);
1960 }
1961 }
1962
1963
1964 return true;
1965 }
1966
1967 /**
1968 * Starts the "new version setup screen" if appropriate.
1969 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001970 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001971 // Only do this once per boot.
1972 if (mCheckedForSetup) {
1973 return;
1974 }
1975
1976 // We will show this screen if the current one is a different
1977 // version than the last one shown, and we are not running in
1978 // low-level factory test mode.
1979 final ContentResolver resolver = mContext.getContentResolver();
1980 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1981 Settings.Secure.getInt(resolver,
1982 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1983 mCheckedForSetup = true;
1984
1985 // See if we should be showing the platform update setup UI.
1986 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1987 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1988 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1989
1990 // We don't allow third party apps to replace this.
1991 ResolveInfo ri = null;
1992 for (int i=0; ris != null && i<ris.size(); i++) {
1993 if ((ris.get(i).activityInfo.applicationInfo.flags
1994 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1995 ri = ris.get(i);
1996 break;
1997 }
1998 }
1999
2000 if (ri != null) {
2001 String vers = ri.activityInfo.metaData != null
2002 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2003 : null;
2004 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2005 vers = ri.activityInfo.applicationInfo.metaData.getString(
2006 Intent.METADATA_SETUP_VERSION);
2007 }
2008 String lastVers = Settings.Secure.getString(
2009 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2010 if (vers != null && !vers.equals(lastVers)) {
2011 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2012 intent.setComponent(new ComponentName(
2013 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002014 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002015 null, null, 0, 0, 0, false, false);
2016 }
2017 }
2018 }
2019 }
2020
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002021 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002022 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002023
2024 final int identHash = System.identityHashCode(r);
2025 updateUsageStats(r, true);
2026
2027 int i = mWatchers.beginBroadcast();
2028 while (i > 0) {
2029 i--;
2030 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2031 if (w != null) {
2032 try {
2033 w.activityResuming(identHash);
2034 } catch (RemoteException e) {
2035 }
2036 }
2037 }
2038 mWatchers.finishBroadcast();
2039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002041 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002042 final int N = mPendingActivityLaunches.size();
2043 if (N <= 0) {
2044 return;
2045 }
2046 for (int i=0; i<N; i++) {
2047 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002048 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002049 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2050 doResume && i == (N-1));
2051 }
2052 mPendingActivityLaunches.clear();
2053 }
2054
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002055 public final int startActivity(IApplicationThread caller,
2056 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2057 int grantedMode, IBinder resultTo,
2058 String resultWho, int requestCode, boolean onlyIfNeeded,
2059 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002060 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002061 grantedUriPermissions, grantedMode, resultTo, resultWho,
2062 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002063 }
2064
2065 public final WaitResult startActivityAndWait(IApplicationThread caller,
2066 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2067 int grantedMode, IBinder resultTo,
2068 String resultWho, int requestCode, boolean onlyIfNeeded,
2069 boolean debug) {
2070 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002071 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002072 grantedUriPermissions, grantedMode, resultTo, resultWho,
2073 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002074 return res;
2075 }
2076
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002077 public final int startActivityWithConfig(IApplicationThread caller,
2078 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2079 int grantedMode, IBinder resultTo,
2080 String resultWho, int requestCode, boolean onlyIfNeeded,
2081 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002082 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002083 grantedUriPermissions, grantedMode, resultTo, resultWho,
2084 requestCode, onlyIfNeeded, debug, null, config);
2085 }
2086
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002087 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002088 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002089 IBinder resultTo, String resultWho, int requestCode,
2090 int flagsMask, int flagsValues) {
2091 // Refuse possible leaked file descriptors
2092 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2093 throw new IllegalArgumentException("File descriptors passed in Intent");
2094 }
2095
2096 IIntentSender sender = intent.getTarget();
2097 if (!(sender instanceof PendingIntentRecord)) {
2098 throw new IllegalArgumentException("Bad PendingIntent object");
2099 }
2100
2101 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002102
2103 synchronized (this) {
2104 // If this is coming from the currently resumed activity, it is
2105 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002106 if (mMainStack.mResumedActivity != null
2107 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002108 Binder.getCallingUid()) {
2109 mAppSwitchesAllowedTime = 0;
2110 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002111 }
2112
2113 return pir.sendInner(0, fillInIntent, resolvedType,
2114 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2115 }
2116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002117 public boolean startNextMatchingActivity(IBinder callingActivity,
2118 Intent intent) {
2119 // Refuse possible leaked file descriptors
2120 if (intent != null && intent.hasFileDescriptors() == true) {
2121 throw new IllegalArgumentException("File descriptors passed in Intent");
2122 }
2123
2124 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002125 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 if (index < 0) {
2127 return false;
2128 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002129 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 if (r.app == null || r.app.thread == null) {
2131 // The caller is not running... d'oh!
2132 return false;
2133 }
2134 intent = new Intent(intent);
2135 // The caller is not allowed to change the data.
2136 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2137 // And we are resetting to find the next component...
2138 intent.setComponent(null);
2139
2140 ActivityInfo aInfo = null;
2141 try {
2142 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002143 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002145 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146
2147 // Look for the original activity in the list...
2148 final int N = resolves != null ? resolves.size() : 0;
2149 for (int i=0; i<N; i++) {
2150 ResolveInfo rInfo = resolves.get(i);
2151 if (rInfo.activityInfo.packageName.equals(r.packageName)
2152 && rInfo.activityInfo.name.equals(r.info.name)) {
2153 // We found the current one... the next matching is
2154 // after it.
2155 i++;
2156 if (i<N) {
2157 aInfo = resolves.get(i).activityInfo;
2158 }
2159 break;
2160 }
2161 }
2162 } catch (RemoteException e) {
2163 }
2164
2165 if (aInfo == null) {
2166 // Nobody who is next!
2167 return false;
2168 }
2169
2170 intent.setComponent(new ComponentName(
2171 aInfo.applicationInfo.packageName, aInfo.name));
2172 intent.setFlags(intent.getFlags()&~(
2173 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2174 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2175 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2176 Intent.FLAG_ACTIVITY_NEW_TASK));
2177
2178 // Okay now we need to start the new activity, replacing the
2179 // currently running activity. This is a little tricky because
2180 // we want to start the new one as if the current one is finished,
2181 // but not finish the current one first so that there is no flicker.
2182 // And thus...
2183 final boolean wasFinishing = r.finishing;
2184 r.finishing = true;
2185
2186 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002187 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 final String resultWho = r.resultWho;
2189 final int requestCode = r.requestCode;
2190 r.resultTo = null;
2191 if (resultTo != null) {
2192 resultTo.removeResultsLocked(r, resultWho, requestCode);
2193 }
2194
2195 final long origId = Binder.clearCallingIdentity();
2196 // XXX we are not dealing with propagating grantedUriPermissions...
2197 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002198 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002199 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002200 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002201 Binder.restoreCallingIdentity(origId);
2202
2203 r.finishing = wasFinishing;
2204 if (res != START_SUCCESS) {
2205 return false;
2206 }
2207 return true;
2208 }
2209 }
2210
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002211 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002212 Intent intent, String resolvedType, IBinder resultTo,
2213 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002214
2215 // This is so super not safe, that only the system (or okay root)
2216 // can do it.
2217 final int callingUid = Binder.getCallingUid();
2218 if (callingUid != 0 && callingUid != Process.myUid()) {
2219 throw new SecurityException(
2220 "startActivityInPackage only available to the system");
2221 }
2222
The Android Open Source Project4df24232009-03-05 14:34:35 -08002223 final boolean componentSpecified = intent.getComponent() != null;
2224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002225 // Don't modify the client's object!
2226 intent = new Intent(intent);
2227
2228 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002229 ActivityInfo aInfo;
2230 try {
2231 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002232 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002234 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002235 aInfo = rInfo != null ? rInfo.activityInfo : null;
2236 } catch (RemoteException e) {
2237 aInfo = null;
2238 }
2239
2240 if (aInfo != null) {
2241 // Store the found target back into the intent, because now that
2242 // we have it we never want to do this again. For example, if the
2243 // user navigates back to this point in the history, we should
2244 // always restart the exact same activity.
2245 intent.setComponent(new ComponentName(
2246 aInfo.applicationInfo.packageName, aInfo.name));
2247 }
2248
2249 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002250 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002251 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002252 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 }
2254 }
2255
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002256 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 // Remove any existing entries that are the same kind of task.
2258 int N = mRecentTasks.size();
2259 for (int i=0; i<N; i++) {
2260 TaskRecord tr = mRecentTasks.get(i);
2261 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2262 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2263 mRecentTasks.remove(i);
2264 i--;
2265 N--;
2266 if (task.intent == null) {
2267 // If the new recent task we are adding is not fully
2268 // specified, then replace it with the existing recent task.
2269 task = tr;
2270 }
2271 }
2272 }
2273 if (N >= MAX_RECENT_TASKS) {
2274 mRecentTasks.remove(N-1);
2275 }
2276 mRecentTasks.add(0, task);
2277 }
2278
2279 public void setRequestedOrientation(IBinder token,
2280 int requestedOrientation) {
2281 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002282 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002283 if (index < 0) {
2284 return;
2285 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002286 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002287 final long origId = Binder.clearCallingIdentity();
2288 mWindowManager.setAppOrientation(r, requestedOrientation);
2289 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002290 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002291 r.mayFreezeScreenLocked(r.app) ? r : null);
2292 if (config != null) {
2293 r.frozenBeforeDestroy = true;
2294 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002295 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002296 }
2297 }
2298 Binder.restoreCallingIdentity(origId);
2299 }
2300 }
2301
2302 public int getRequestedOrientation(IBinder token) {
2303 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002304 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 if (index < 0) {
2306 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2307 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002308 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 return mWindowManager.getAppOrientation(r);
2310 }
2311 }
2312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 /**
2314 * This is the internal entry point for handling Activity.finish().
2315 *
2316 * @param token The Binder token referencing the Activity we want to finish.
2317 * @param resultCode Result code, if any, from this Activity.
2318 * @param resultData Result data (Intent), if any, from this Activity.
2319 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002320 * @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 -08002321 */
2322 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2323 // Refuse possible leaked file descriptors
2324 if (resultData != null && resultData.hasFileDescriptors() == true) {
2325 throw new IllegalArgumentException("File descriptors passed in Intent");
2326 }
2327
2328 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002329 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002330 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002331 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 if (next != null) {
2333 // ask watcher if this is allowed
2334 boolean resumeOK = true;
2335 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002336 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002337 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002338 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002339 }
2340
2341 if (!resumeOK) {
2342 return false;
2343 }
2344 }
2345 }
2346 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002347 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002348 resultData, "app-request");
2349 Binder.restoreCallingIdentity(origId);
2350 return res;
2351 }
2352 }
2353
Dianne Hackborn860755f2010-06-03 18:47:52 -07002354 public final void finishHeavyWeightApp() {
2355 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2356 != PackageManager.PERMISSION_GRANTED) {
2357 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2358 + Binder.getCallingPid()
2359 + ", uid=" + Binder.getCallingUid()
2360 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2361 Slog.w(TAG, msg);
2362 throw new SecurityException(msg);
2363 }
2364
2365 synchronized(this) {
2366 if (mHeavyWeightProcess == null) {
2367 return;
2368 }
2369
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002370 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002371 mHeavyWeightProcess.activities);
2372 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002373 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002374 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002375 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002376 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002377 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002378 null, "finish-heavy");
2379 }
2380 }
2381 }
2382
2383 mHeavyWeightProcess = null;
2384 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2385 }
2386 }
2387
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002388 public void crashApplication(int uid, int initialPid, String packageName,
2389 String message) {
2390 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2391 != PackageManager.PERMISSION_GRANTED) {
2392 String msg = "Permission Denial: crashApplication() from pid="
2393 + Binder.getCallingPid()
2394 + ", uid=" + Binder.getCallingUid()
2395 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2396 Slog.w(TAG, msg);
2397 throw new SecurityException(msg);
2398 }
2399
2400 synchronized(this) {
2401 ProcessRecord proc = null;
2402
2403 // Figure out which process to kill. We don't trust that initialPid
2404 // still has any relation to current pids, so must scan through the
2405 // list.
2406 synchronized (mPidsSelfLocked) {
2407 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2408 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2409 if (p.info.uid != uid) {
2410 continue;
2411 }
2412 if (p.pid == initialPid) {
2413 proc = p;
2414 break;
2415 }
2416 for (String str : p.pkgList) {
2417 if (str.equals(packageName)) {
2418 proc = p;
2419 }
2420 }
2421 }
2422 }
2423
2424 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002425 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002426 + " initialPid=" + initialPid
2427 + " packageName=" + packageName);
2428 return;
2429 }
2430
2431 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002432 if (proc.pid == Process.myPid()) {
2433 Log.w(TAG, "crashApplication: trying to crash self!");
2434 return;
2435 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002436 long ident = Binder.clearCallingIdentity();
2437 try {
2438 proc.thread.scheduleCrash(message);
2439 } catch (RemoteException e) {
2440 }
2441 Binder.restoreCallingIdentity(ident);
2442 }
2443 }
2444 }
2445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002446 public final void finishSubActivity(IBinder token, String resultWho,
2447 int requestCode) {
2448 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002449 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002450 if (index < 0) {
2451 return;
2452 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002453 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002454
2455 final long origId = Binder.clearCallingIdentity();
2456
2457 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002458 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2459 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 if (r.resultTo == self && r.requestCode == requestCode) {
2461 if ((r.resultWho == null && resultWho == null) ||
2462 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002463 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002464 Activity.RESULT_CANCELED, null, "request-sub");
2465 }
2466 }
2467 }
2468
2469 Binder.restoreCallingIdentity(origId);
2470 }
2471 }
2472
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002473 public boolean willActivityBeVisible(IBinder token) {
2474 synchronized(this) {
2475 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002476 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2477 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002478 if (r == token) {
2479 return true;
2480 }
2481 if (r.fullscreen && !r.finishing) {
2482 return false;
2483 }
2484 }
2485 return true;
2486 }
2487 }
2488
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002489 public void overridePendingTransition(IBinder token, String packageName,
2490 int enterAnim, int exitAnim) {
2491 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002492 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002493 if (index < 0) {
2494 return;
2495 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002496 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002497
2498 final long origId = Binder.clearCallingIdentity();
2499
2500 if (self.state == ActivityState.RESUMED
2501 || self.state == ActivityState.PAUSING) {
2502 mWindowManager.overridePendingAppTransition(packageName,
2503 enterAnim, exitAnim);
2504 }
2505
2506 Binder.restoreCallingIdentity(origId);
2507 }
2508 }
2509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511 * Main function for removing an existing process from the activity manager
2512 * as a result of that process going away. Clears out all connections
2513 * to the process.
2514 */
2515 private final void handleAppDiedLocked(ProcessRecord app,
2516 boolean restarting) {
2517 cleanUpApplicationRecordLocked(app, restarting, -1);
2518 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002519 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002520 }
2521
2522 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002523 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2524 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2525 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002527 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2528 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002529 }
2530
2531 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002532 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533
2534 boolean atTop = true;
2535 boolean hasVisibleActivities = false;
2536
2537 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002538 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002539 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002540 TAG, "Removing app " + app + " from history with " + i + " entries");
2541 while (i > 0) {
2542 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002543 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002544 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2546 if (r.app == app) {
2547 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002548 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002549 TAG, "Removing this entry! frozen=" + r.haveState
2550 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002551 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552
2553 r.inHistory = false;
2554 mWindowManager.removeAppToken(r);
2555 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002556 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002558 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002559
2560 } else {
2561 // We have the current state for this activity, so
2562 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002563 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002564 TAG, "Keeping entry, setting app to null");
2565 if (r.visible) {
2566 hasVisibleActivities = true;
2567 }
2568 r.app = null;
2569 r.nowVisible = false;
2570 if (!r.haveState) {
2571 r.icicle = null;
2572 }
2573 }
2574
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002575 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576 r.state = ActivityState.STOPPED;
2577 }
2578 atTop = false;
2579 }
2580
2581 app.activities.clear();
2582
2583 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002584 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 + " running instrumentation " + app.instrumentationClass);
2586 Bundle info = new Bundle();
2587 info.putString("shortMsg", "Process crashed.");
2588 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2589 }
2590
2591 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002592 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 // If there was nothing to resume, and we are not already
2594 // restarting this process, but there is a visible activity that
2595 // is hosted by the process... then make sure all visible
2596 // activities are running, taking care of restarting this
2597 // process.
2598 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002599 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 }
2601 }
2602 }
2603 }
2604
2605 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2606 IBinder threadBinder = thread.asBinder();
2607
2608 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002609 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2610 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002611 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2612 return i;
2613 }
2614 }
2615 return -1;
2616 }
2617
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002618 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619 IApplicationThread thread) {
2620 if (thread == null) {
2621 return null;
2622 }
2623
2624 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002625 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 }
2627
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002628 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 IApplicationThread thread) {
2630
2631 mProcDeaths[0]++;
2632
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002633 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2634 synchronized (stats) {
2635 stats.noteProcessDiedLocked(app.info.uid, pid);
2636 }
2637
Magnus Edlund7bb25812010-02-24 15:45:06 +01002638 // Clean up already done if the process has been re-started.
2639 if (app.pid == pid && app.thread != null &&
2640 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002641 if (!app.killedBackground) {
2642 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2643 + ") has died.");
2644 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002645 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002646 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002647 TAG, "Dying app: " + app + ", pid: " + pid
2648 + ", thread: " + thread.asBinder());
2649 boolean doLowMem = app.instrumentationClass == null;
2650 handleAppDiedLocked(app, false);
2651
2652 if (doLowMem) {
2653 // If there are no longer any background processes running,
2654 // and the app that died was not running instrumentation,
2655 // then tell everyone we are now low on memory.
2656 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002657 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2658 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002659 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2660 haveBg = true;
2661 break;
2662 }
2663 }
2664
2665 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002666 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002667 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002668 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002669 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2670 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002671 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002672 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2673 // The low memory report is overriding any current
2674 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002675 // heavy/important/visible/foreground processes first.
2676 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002677 rec.lastRequestedGc = 0;
2678 } else {
2679 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002681 rec.reportLowMemory = true;
2682 rec.lastLowMemory = now;
2683 mProcessesToGc.remove(rec);
2684 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002685 }
2686 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002687 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002688 }
2689 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002690 } else if (app.pid != pid) {
2691 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002692 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002693 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002694 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002695 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002696 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 + thread.asBinder());
2698 }
2699 }
2700
Dan Egnor42471dd2010-01-07 17:25:22 -08002701 /**
2702 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002703 * @param clearTraces causes the dump file to be erased prior to the new
2704 * traces being written, if true; when false, the new traces will be
2705 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002706 * @param firstPids of dalvik VM processes to dump stack traces for first
2707 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002708 * @return file containing stack traces, or null if no dump file is configured
2709 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002710 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2711 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002712 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2713 if (tracesPath == null || tracesPath.length() == 0) {
2714 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002715 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002716
2717 File tracesFile = new File(tracesPath);
2718 try {
2719 File tracesDir = tracesFile.getParentFile();
2720 if (!tracesDir.exists()) tracesFile.mkdirs();
2721 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2722
Christopher Tate6ee412d2010-05-28 12:01:56 -07002723 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002724 tracesFile.createNewFile();
2725 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2726 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002727 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002728 return null;
2729 }
2730
2731 // Use a FileObserver to detect when traces finish writing.
2732 // The order of traces is considered important to maintain for legibility.
2733 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2734 public synchronized void onEvent(int event, String path) { notify(); }
2735 };
2736
2737 try {
2738 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002739
2740 // First collect all of the stacks of the most important pids.
2741 try {
2742 int num = firstPids.size();
2743 for (int i = 0; i < num; i++) {
2744 synchronized (observer) {
2745 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2746 observer.wait(200); // Wait for write-close, give up after 200msec
2747 }
2748 }
2749 } catch (InterruptedException e) {
2750 Log.wtf(TAG, e);
2751 }
2752
2753 // Next measure CPU usage.
2754 if (processStats != null) {
2755 processStats.init();
2756 System.gc();
2757 processStats.update();
2758 try {
2759 synchronized (processStats) {
2760 processStats.wait(500); // measure over 1/2 second.
2761 }
2762 } catch (InterruptedException e) {
2763 }
2764 processStats.update();
2765
2766 // We'll take the stack crawls of just the top apps using CPU.
2767 final int N = processStats.countWorkingStats();
2768 int numProcs = 0;
2769 for (int i=0; i<N && numProcs<5; i++) {
2770 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2771 if (lastPids.indexOfKey(stats.pid) >= 0) {
2772 numProcs++;
2773 try {
2774 synchronized (observer) {
2775 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2776 observer.wait(200); // Wait for write-close, give up after 200msec
2777 }
2778 } catch (InterruptedException e) {
2779 Log.wtf(TAG, e);
2780 }
2781
2782 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002783 }
2784 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002785
2786 return tracesFile;
2787
Dan Egnor42471dd2010-01-07 17:25:22 -08002788 } finally {
2789 observer.stopWatching();
2790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 }
2792
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002793 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2794 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002795 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2796 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2797
2798 long anrTime = SystemClock.uptimeMillis();
2799 if (MONITOR_CPU_USAGE) {
2800 updateCpuStatsNow();
2801 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002802
2803 synchronized (this) {
2804 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2805 if (mShuttingDown) {
2806 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2807 return;
2808 } else if (app.notResponding) {
2809 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2810 return;
2811 } else if (app.crashing) {
2812 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2813 return;
2814 }
2815
2816 // In case we come through here for the same app before completing
2817 // this one, mark as anring now so we will bail out.
2818 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002819
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002820 // Log the ANR to the event log.
2821 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2822 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002823
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002824 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002825 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002826
2827 int parentPid = app.pid;
2828 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002829 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002830
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002831 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002832
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002833 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2834 ProcessRecord r = mLruProcesses.get(i);
2835 if (r != null && r.thread != null) {
2836 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002837 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2838 if (r.persistent) {
2839 firstPids.add(pid);
2840 } else {
2841 lastPids.put(pid, Boolean.TRUE);
2842 }
2843 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002845 }
2846 }
2847
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002848 final ProcessStats processStats = new ProcessStats(true);
2849
2850 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002851
2852 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002853 StringBuilder info = mStringBuilder;
2854 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002855 info.append("ANR in ").append(app.processName);
2856 if (activity != null && activity.shortComponentName != null) {
2857 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002858 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002859 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002860 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002861 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002862 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002863 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002864 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002865 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002866
Dan Egnor42471dd2010-01-07 17:25:22 -08002867 String cpuInfo = null;
2868 if (MONITOR_CPU_USAGE) {
2869 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002870 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002871 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002872 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002873 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002874 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002875 }
2876
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002877 info.append(processStats.printCurrentState(anrTime));
2878
Joe Onorato8a9b2202010-02-26 18:56:32 -08002879 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002880 if (tracesFile == null) {
2881 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2882 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2883 }
2884
2885 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2886
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002887 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002889 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2890 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002891 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002892 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2893 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002894 }
2895 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002896 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 }
2898 }
2899
Dan Egnor42471dd2010-01-07 17:25:22 -08002900 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2901 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2902 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002903
2904 synchronized (this) {
2905 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2906 Process.killProcess(app.pid);
2907 return;
2908 }
2909
2910 // Set the app's notResponding state, and look up the errorReportReceiver
2911 makeAppNotRespondingLocked(app,
2912 activity != null ? activity.shortComponentName : null,
2913 annotation != null ? "ANR " + annotation : "ANR",
2914 info.toString());
2915
2916 // Bring up the infamous App Not Responding dialog
2917 Message msg = Message.obtain();
2918 HashMap map = new HashMap();
2919 msg.what = SHOW_NOT_RESPONDING_MSG;
2920 msg.obj = map;
2921 map.put("app", app);
2922 if (activity != null) {
2923 map.put("activity", activity);
2924 }
2925
2926 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 }
2929
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002930 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2931 if (!mLaunchWarningShown) {
2932 mLaunchWarningShown = true;
2933 mHandler.post(new Runnable() {
2934 @Override
2935 public void run() {
2936 synchronized (ActivityManagerService.this) {
2937 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
2938 d.show();
2939 mHandler.postDelayed(new Runnable() {
2940 @Override
2941 public void run() {
2942 synchronized (ActivityManagerService.this) {
2943 d.dismiss();
2944 mLaunchWarningShown = false;
2945 }
2946 }
2947 }, 4000);
2948 }
2949 }
2950 });
2951 }
2952 }
2953
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002954 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955 app.persistentActivities--;
2956 if (app.persistentActivities > 0) {
2957 // Still more of 'em...
2958 return;
2959 }
2960 if (app.persistent) {
2961 // Ah, but the application itself is persistent. Whatever!
2962 return;
2963 }
2964
2965 // App is no longer persistent... make sure it and the ones
2966 // following it in the LRU list have the correc oom_adj.
2967 updateOomAdjLocked();
2968 }
2969
2970 public void setPersistent(IBinder token, boolean isPersistent) {
2971 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2972 != PackageManager.PERMISSION_GRANTED) {
2973 String msg = "Permission Denial: setPersistent() from pid="
2974 + Binder.getCallingPid()
2975 + ", uid=" + Binder.getCallingUid()
2976 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002977 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002978 throw new SecurityException(msg);
2979 }
2980
2981 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002982 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002983 if (index < 0) {
2984 return;
2985 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002986 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 ProcessRecord app = r.app;
2988
Joe Onorato8a9b2202010-02-26 18:56:32 -08002989 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 TAG, "Setting persistence " + isPersistent + ": " + r);
2991
2992 if (isPersistent) {
2993 if (r.persistent) {
2994 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002995 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002996 return;
2997 }
2998 r.persistent = true;
2999 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003000 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001 if (app.persistentActivities > 1) {
3002 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003003 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003004 return;
3005 }
3006 if (app.persistent) {
3007 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003008 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 return;
3010 }
3011
3012 // App is now persistent... make sure it and the ones
3013 // following it now have the correct oom_adj.
3014 final long origId = Binder.clearCallingIdentity();
3015 updateOomAdjLocked();
3016 Binder.restoreCallingIdentity(origId);
3017
3018 } else {
3019 if (!r.persistent) {
3020 // Okay okay, I heard you already!
3021 return;
3022 }
3023 r.persistent = false;
3024 final long origId = Binder.clearCallingIdentity();
3025 decPersistentCountLocked(app);
3026 Binder.restoreCallingIdentity(origId);
3027
3028 }
3029 }
3030 }
3031
3032 public boolean clearApplicationUserData(final String packageName,
3033 final IPackageDataObserver observer) {
3034 int uid = Binder.getCallingUid();
3035 int pid = Binder.getCallingPid();
3036 long callingId = Binder.clearCallingIdentity();
3037 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003038 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003039 int pkgUid = -1;
3040 synchronized(this) {
3041 try {
3042 pkgUid = pm.getPackageUid(packageName);
3043 } catch (RemoteException e) {
3044 }
3045 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003046 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 return false;
3048 }
3049 if (uid == pkgUid || checkComponentPermission(
3050 android.Manifest.permission.CLEAR_APP_USER_DATA,
3051 pid, uid, -1)
3052 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003053 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 } else {
3055 throw new SecurityException(pid+" does not have permission:"+
3056 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3057 "for process:"+packageName);
3058 }
3059 }
3060
3061 try {
3062 //clear application user data
3063 pm.clearApplicationUserData(packageName, observer);
3064 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3065 Uri.fromParts("package", packageName, null));
3066 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003067 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3068 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 } catch (RemoteException e) {
3070 }
3071 } finally {
3072 Binder.restoreCallingIdentity(callingId);
3073 }
3074 return true;
3075 }
3076
Dianne Hackborn03abb812010-01-04 18:43:19 -08003077 public void killBackgroundProcesses(final String packageName) {
3078 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3079 != PackageManager.PERMISSION_GRANTED &&
3080 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3081 != PackageManager.PERMISSION_GRANTED) {
3082 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 + Binder.getCallingPid()
3084 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003085 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003086 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 throw new SecurityException(msg);
3088 }
3089
3090 long callingId = Binder.clearCallingIdentity();
3091 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003092 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003093 int pkgUid = -1;
3094 synchronized(this) {
3095 try {
3096 pkgUid = pm.getPackageUid(packageName);
3097 } catch (RemoteException e) {
3098 }
3099 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003100 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 return;
3102 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003103 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003104 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003105 }
3106 } finally {
3107 Binder.restoreCallingIdentity(callingId);
3108 }
3109 }
3110
3111 public void forceStopPackage(final String packageName) {
3112 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3113 != PackageManager.PERMISSION_GRANTED) {
3114 String msg = "Permission Denial: forceStopPackage() from pid="
3115 + Binder.getCallingPid()
3116 + ", uid=" + Binder.getCallingUid()
3117 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003118 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003119 throw new SecurityException(msg);
3120 }
3121
3122 long callingId = Binder.clearCallingIdentity();
3123 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003124 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003125 int pkgUid = -1;
3126 synchronized(this) {
3127 try {
3128 pkgUid = pm.getPackageUid(packageName);
3129 } catch (RemoteException e) {
3130 }
3131 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003132 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003133 return;
3134 }
3135 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003136 }
3137 } finally {
3138 Binder.restoreCallingIdentity(callingId);
3139 }
3140 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003141
3142 /*
3143 * The pkg name and uid have to be specified.
3144 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3145 */
3146 public void killApplicationWithUid(String pkg, int uid) {
3147 if (pkg == null) {
3148 return;
3149 }
3150 // Make sure the uid is valid.
3151 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003152 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003153 return;
3154 }
3155 int callerUid = Binder.getCallingUid();
3156 // Only the system server can kill an application
3157 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003158 // Post an aysnc message to kill the application
3159 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3160 msg.arg1 = uid;
3161 msg.arg2 = 0;
3162 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003163 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003164 } else {
3165 throw new SecurityException(callerUid + " cannot kill pkg: " +
3166 pkg);
3167 }
3168 }
3169
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003170 public void closeSystemDialogs(String reason) {
3171 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003172 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003173 if (reason != null) {
3174 intent.putExtra("reason", reason);
3175 }
3176
3177 final int uid = Binder.getCallingUid();
3178 final long origId = Binder.clearCallingIdentity();
3179 synchronized (this) {
3180 int i = mWatchers.beginBroadcast();
3181 while (i > 0) {
3182 i--;
3183 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3184 if (w != null) {
3185 try {
3186 w.closingSystemDialogs(reason);
3187 } catch (RemoteException e) {
3188 }
3189 }
3190 }
3191 mWatchers.finishBroadcast();
3192
Dianne Hackbornffa42482009-09-23 22:20:11 -07003193 mWindowManager.closeSystemDialogs(reason);
3194
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003195 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3196 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003197 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003198 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003199 Activity.RESULT_CANCELED, null, "close-sys");
3200 }
3201 }
3202
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003203 broadcastIntentLocked(null, null, intent, null,
3204 null, 0, null, null, null, false, false, -1, uid);
3205 }
3206 Binder.restoreCallingIdentity(origId);
3207 }
3208
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003209 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003210 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003211 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3212 for (int i=pids.length-1; i>=0; i--) {
3213 infos[i] = new Debug.MemoryInfo();
3214 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003215 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003216 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003217 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003218
3219 public void killApplicationProcess(String processName, int uid) {
3220 if (processName == null) {
3221 return;
3222 }
3223
3224 int callerUid = Binder.getCallingUid();
3225 // Only the system server can kill an application
3226 if (callerUid == Process.SYSTEM_UID) {
3227 synchronized (this) {
3228 ProcessRecord app = getProcessRecordLocked(processName, uid);
3229 if (app != null) {
3230 try {
3231 app.thread.scheduleSuicide();
3232 } catch (RemoteException e) {
3233 // If the other end already died, then our work here is done.
3234 }
3235 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003236 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003237 + processName + " / " + uid);
3238 }
3239 }
3240 } else {
3241 throw new SecurityException(callerUid + " cannot kill app process: " +
3242 processName);
3243 }
3244 }
3245
Dianne Hackborn03abb812010-01-04 18:43:19 -08003246 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003247 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3249 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003250 if (!mProcessesReady) {
3251 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 intent.putExtra(Intent.EXTRA_UID, uid);
3254 broadcastIntentLocked(null, null, intent,
3255 null, null, 0, null, null, null,
3256 false, false, MY_PID, Process.SYSTEM_UID);
3257 }
3258
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003259 private final boolean killPackageProcessesLocked(String packageName, int uid,
3260 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003261 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262
Dianne Hackborn03abb812010-01-04 18:43:19 -08003263 // Remove all processes this package may have touched: all with the
3264 // same UID (except for the system or root user), and all whose name
3265 // matches the package name.
3266 final String procNamePrefix = packageName + ":";
3267 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3268 final int NA = apps.size();
3269 for (int ia=0; ia<NA; ia++) {
3270 ProcessRecord app = apps.valueAt(ia);
3271 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003272 if (doit) {
3273 procs.add(app);
3274 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003275 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3276 || app.processName.equals(packageName)
3277 || app.processName.startsWith(procNamePrefix)) {
3278 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003279 if (!doit) {
3280 return true;
3281 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003282 app.removed = true;
3283 procs.add(app);
3284 }
3285 }
3286 }
3287 }
3288
3289 int N = procs.size();
3290 for (int i=0; i<N; i++) {
3291 removeProcessLocked(procs.get(i), callerWillRestart);
3292 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003293 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003294 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003295
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003296 private final boolean forceStopPackageLocked(String name, int uid,
3297 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003298 int i, N;
3299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003300 if (uid < 0) {
3301 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003302 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003303 } catch (RemoteException e) {
3304 }
3305 }
3306
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003307 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003308 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003309
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003310 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3311 while (badApps.hasNext()) {
3312 SparseArray<Long> ba = badApps.next();
3313 if (ba.get(uid) != null) {
3314 badApps.remove();
3315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 }
3317 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003318
3319 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3320 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003321
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003322 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3323 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003325 if (!doit) {
3326 return true;
3327 }
3328 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003329 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003330 if (r.app != null) {
3331 r.app.removed = true;
3332 }
3333 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003334 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 }
3336 }
3337
3338 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3339 for (ServiceRecord service : mServices.values()) {
3340 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003341 if (!doit) {
3342 return true;
3343 }
3344 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003345 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 if (service.app != null) {
3347 service.app.removed = true;
3348 }
3349 service.app = null;
3350 services.add(service);
3351 }
3352 }
3353
3354 N = services.size();
3355 for (i=0; i<N; i++) {
3356 bringDownServiceLocked(services.get(i), true);
3357 }
3358
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003359 if (doit) {
3360 if (purgeCache) {
3361 AttributeCache ac = AttributeCache.instance();
3362 if (ac != null) {
3363 ac.removePackage(name);
3364 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003365 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003366 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003367 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003368
3369 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 }
3371
3372 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3373 final String name = app.processName;
3374 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003375 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003376 TAG, "Force removing process " + app + " (" + name
3377 + "/" + uid + ")");
3378
3379 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003380 if (mHeavyWeightProcess == app) {
3381 mHeavyWeightProcess = null;
3382 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003384 boolean needRestart = false;
3385 if (app.pid > 0 && app.pid != MY_PID) {
3386 int pid = app.pid;
3387 synchronized (mPidsSelfLocked) {
3388 mPidsSelfLocked.remove(pid);
3389 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3390 }
3391 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003392 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 Process.killProcess(pid);
3394
3395 if (app.persistent) {
3396 if (!callerWillRestart) {
3397 addAppLocked(app.info);
3398 } else {
3399 needRestart = true;
3400 }
3401 }
3402 } else {
3403 mRemovedProcesses.add(app);
3404 }
3405
3406 return needRestart;
3407 }
3408
3409 private final void processStartTimedOutLocked(ProcessRecord app) {
3410 final int pid = app.pid;
3411 boolean gone = false;
3412 synchronized (mPidsSelfLocked) {
3413 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3414 if (knownApp != null && knownApp.thread == null) {
3415 mPidsSelfLocked.remove(pid);
3416 gone = true;
3417 }
3418 }
3419
3420 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003421 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003422 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003423 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003425 if (mHeavyWeightProcess == app) {
3426 mHeavyWeightProcess = null;
3427 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3428 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003429 // Take care of any launching providers waiting for this process.
3430 checkAppInLaunchingProvidersLocked(app, true);
3431 // Take care of any services that are waiting for the process.
3432 for (int i=0; i<mPendingServices.size(); i++) {
3433 ServiceRecord sr = mPendingServices.get(i);
3434 if (app.info.uid == sr.appInfo.uid
3435 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003436 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003437 mPendingServices.remove(i);
3438 i--;
3439 bringDownServiceLocked(sr, true);
3440 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003442 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003443 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003444 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003445 try {
3446 IBackupManager bm = IBackupManager.Stub.asInterface(
3447 ServiceManager.getService(Context.BACKUP_SERVICE));
3448 bm.agentDisconnected(app.info.packageName);
3449 } catch (RemoteException e) {
3450 // Can't happen; the backup manager is local
3451 }
3452 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003453 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003454 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003455 mPendingBroadcast.state = BroadcastRecord.IDLE;
3456 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003457 mPendingBroadcast = null;
3458 scheduleBroadcastsLocked();
3459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003461 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003462 }
3463 }
3464
3465 private final boolean attachApplicationLocked(IApplicationThread thread,
3466 int pid) {
3467
3468 // Find the application record that is being attached... either via
3469 // the pid if we are running in multiple processes, or just pull the
3470 // next app record if we are emulating process with anonymous threads.
3471 ProcessRecord app;
3472 if (pid != MY_PID && pid >= 0) {
3473 synchronized (mPidsSelfLocked) {
3474 app = mPidsSelfLocked.get(pid);
3475 }
3476 } else if (mStartingProcesses.size() > 0) {
3477 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003478 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 } else {
3480 app = null;
3481 }
3482
3483 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003484 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003486 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003487 if (pid > 0 && pid != MY_PID) {
3488 Process.killProcess(pid);
3489 } else {
3490 try {
3491 thread.scheduleExit();
3492 } catch (Exception e) {
3493 // Ignore exceptions.
3494 }
3495 }
3496 return false;
3497 }
3498
3499 // If this application record is still attached to a previous
3500 // process, clean it up now.
3501 if (app.thread != null) {
3502 handleAppDiedLocked(app, true);
3503 }
3504
3505 // Tell the process all about itself.
3506
Joe Onorato8a9b2202010-02-26 18:56:32 -08003507 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003508 TAG, "Binding process pid " + pid + " to record " + app);
3509
3510 String processName = app.processName;
3511 try {
3512 thread.asBinder().linkToDeath(new AppDeathRecipient(
3513 app, pid, thread), 0);
3514 } catch (RemoteException e) {
3515 app.resetPackageList();
3516 startProcessLocked(app, "link fail", processName);
3517 return false;
3518 }
3519
Doug Zongker2bec3d42009-12-04 12:52:44 -08003520 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521
3522 app.thread = thread;
3523 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003524 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3525 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 app.forcingToForeground = null;
3527 app.foregroundServices = false;
3528 app.debugging = false;
3529
3530 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3531
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003532 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003533 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003534
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003535 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003536 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003537 }
3538
Joe Onorato8a9b2202010-02-26 18:56:32 -08003539 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540 TAG, "New app record " + app
3541 + " thread=" + thread.asBinder() + " pid=" + pid);
3542 try {
3543 int testMode = IApplicationThread.DEBUG_OFF;
3544 if (mDebugApp != null && mDebugApp.equals(processName)) {
3545 testMode = mWaitForDebugger
3546 ? IApplicationThread.DEBUG_WAIT
3547 : IApplicationThread.DEBUG_ON;
3548 app.debugging = true;
3549 if (mDebugTransient) {
3550 mDebugApp = mOrigDebugApp;
3551 mWaitForDebugger = mOrigWaitForDebugger;
3552 }
3553 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003554
Christopher Tate181fafa2009-05-14 11:12:14 -07003555 // If the app is being launched for restore or full backup, set it up specially
3556 boolean isRestrictedBackupMode = false;
3557 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3558 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3559 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3560 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003561
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003562 ensurePackageDexOpt(app.instrumentationInfo != null
3563 ? app.instrumentationInfo.packageName
3564 : app.info.packageName);
3565 if (app.instrumentationClass != null) {
3566 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003567 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003568 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003569 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003570 thread.bindApplication(processName, app.instrumentationInfo != null
3571 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 app.instrumentationClass, app.instrumentationProfileFile,
3573 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003574 isRestrictedBackupMode || !normalMode,
3575 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003576 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003577 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 } catch (Exception e) {
3579 // todo: Yikes! What should we do? For now we will try to
3580 // start another process, but that could easily get us in
3581 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003582 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583
3584 app.resetPackageList();
3585 startProcessLocked(app, "bind fail", processName);
3586 return false;
3587 }
3588
3589 // Remove this record from the list of starting applications.
3590 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003591 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3592 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 mProcessesOnHold.remove(app);
3594
3595 boolean badApp = false;
3596 boolean didSomething = false;
3597
3598 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003599 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003600 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003601 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3602 && processName.equals(hr.processName)) {
3603 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003604 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 didSomething = true;
3606 }
3607 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003608 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 + hr.intent.getComponent().flattenToShortString(), e);
3610 badApp = true;
3611 }
3612 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003613 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 }
3615 }
3616
3617 // Find any services that should be running in this process...
3618 if (!badApp && mPendingServices.size() > 0) {
3619 ServiceRecord sr = null;
3620 try {
3621 for (int i=0; i<mPendingServices.size(); i++) {
3622 sr = mPendingServices.get(i);
3623 if (app.info.uid != sr.appInfo.uid
3624 || !processName.equals(sr.processName)) {
3625 continue;
3626 }
3627
3628 mPendingServices.remove(i);
3629 i--;
3630 realStartServiceLocked(sr, app);
3631 didSomething = true;
3632 }
3633 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003634 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003635 + sr.shortName, e);
3636 badApp = true;
3637 }
3638 }
3639
3640 // Check if the next broadcast receiver is in this process...
3641 BroadcastRecord br = mPendingBroadcast;
3642 if (!badApp && br != null && br.curApp == app) {
3643 try {
3644 mPendingBroadcast = null;
3645 processCurBroadcastLocked(br, app);
3646 didSomething = true;
3647 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003648 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003649 + br.curComponent.flattenToShortString(), e);
3650 badApp = true;
3651 logBroadcastReceiverDiscard(br);
3652 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3653 br.resultExtras, br.resultAbort, true);
3654 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003655 // We need to reset the state if we fails to start the receiver.
3656 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003657 }
3658 }
3659
Christopher Tate181fafa2009-05-14 11:12:14 -07003660 // Check whether the next backup agent is in this process...
3661 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003662 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003663 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003664 try {
3665 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3666 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003667 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003668 e.printStackTrace();
3669 }
3670 }
3671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 if (badApp) {
3673 // todo: Also need to kill application to deal with all
3674 // kinds of exceptions.
3675 handleAppDiedLocked(app, false);
3676 return false;
3677 }
3678
3679 if (!didSomething) {
3680 updateOomAdjLocked();
3681 }
3682
3683 return true;
3684 }
3685
3686 public final void attachApplication(IApplicationThread thread) {
3687 synchronized (this) {
3688 int callingPid = Binder.getCallingPid();
3689 final long origId = Binder.clearCallingIdentity();
3690 attachApplicationLocked(thread, callingPid);
3691 Binder.restoreCallingIdentity(origId);
3692 }
3693 }
3694
Dianne Hackborne88846e2009-09-30 21:34:25 -07003695 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003696 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003697 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 Binder.restoreCallingIdentity(origId);
3699 }
3700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003702 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003703 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003704 mWindowManager.enableScreenAfterBoot();
3705 }
3706
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003707 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003708 IntentFilter pkgFilter = new IntentFilter();
3709 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3710 pkgFilter.addDataScheme("package");
3711 mContext.registerReceiver(new BroadcastReceiver() {
3712 @Override
3713 public void onReceive(Context context, Intent intent) {
3714 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3715 if (pkgs != null) {
3716 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003717 synchronized (ActivityManagerService.this) {
3718 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3719 setResultCode(Activity.RESULT_OK);
3720 return;
3721 }
3722 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003723 }
3724 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003725 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003726 }, pkgFilter);
3727
3728 synchronized (this) {
3729 // Ensure that any processes we had put on hold are now started
3730 // up.
3731 final int NP = mProcessesOnHold.size();
3732 if (NP > 0) {
3733 ArrayList<ProcessRecord> procs =
3734 new ArrayList<ProcessRecord>(mProcessesOnHold);
3735 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003736 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3737 + procs.get(ip));
3738 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003739 }
3740 }
3741
3742 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003743 // Start looking for apps that are abusing wake locks.
3744 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
3745 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003746 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003747 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003748 broadcastIntentLocked(null, null,
3749 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3750 null, null, 0, null, null,
3751 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3752 false, false, MY_PID, Process.SYSTEM_UID);
3753 }
3754 }
3755 }
3756
3757 final void ensureBootCompleted() {
3758 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003759 boolean enableScreen;
3760 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003761 booting = mBooting;
3762 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003763 enableScreen = !mBooted;
3764 mBooted = true;
3765 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003766
3767 if (booting) {
3768 finishBooting();
3769 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003770
3771 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003772 enableScreenAfterBoot();
3773 }
3774 }
3775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 public final void activityPaused(IBinder token, Bundle icicle) {
3777 // Refuse possible leaked file descriptors
3778 if (icicle != null && icicle.hasFileDescriptors()) {
3779 throw new IllegalArgumentException("File descriptors passed in Bundle");
3780 }
3781
3782 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003783 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784 Binder.restoreCallingIdentity(origId);
3785 }
3786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003787 public final void activityStopped(IBinder token, Bitmap thumbnail,
3788 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003789 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790 TAG, "Activity stopped: token=" + token);
3791
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003792 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793
3794 final long origId = Binder.clearCallingIdentity();
3795
3796 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003797 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003799 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 r.thumbnail = thumbnail;
3801 r.description = description;
3802 r.stopped = true;
3803 r.state = ActivityState.STOPPED;
3804 if (!r.finishing) {
3805 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003806 r.stack.destroyActivityLocked(r, true);
3807 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808 }
3809 }
3810 }
3811 }
3812
3813 if (r != null) {
3814 sendPendingThumbnail(r, null, null, null, false);
3815 }
3816
3817 trimApplications();
3818
3819 Binder.restoreCallingIdentity(origId);
3820 }
3821
3822 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003823 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003824 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003825 }
3826
3827 public String getCallingPackage(IBinder token) {
3828 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003829 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003830 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 }
3832 }
3833
3834 public ComponentName getCallingActivity(IBinder token) {
3835 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003836 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003837 return r != null ? r.intent.getComponent() : null;
3838 }
3839 }
3840
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003841 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003842 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003843 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003844 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003845 if (r != null) {
3846 return r.resultTo;
3847 }
3848 }
3849 return null;
3850 }
3851
3852 public ComponentName getActivityClassForToken(IBinder token) {
3853 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003854 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003855 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003856 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003857 return r.intent.getComponent();
3858 }
3859 return null;
3860 }
3861 }
3862
3863 public String getPackageForToken(IBinder token) {
3864 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003865 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003867 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003868 return r.packageName;
3869 }
3870 return null;
3871 }
3872 }
3873
3874 public IIntentSender getIntentSender(int type,
3875 String packageName, IBinder token, String resultWho,
3876 int requestCode, Intent intent, String resolvedType, int flags) {
3877 // Refuse possible leaked file descriptors
3878 if (intent != null && intent.hasFileDescriptors() == true) {
3879 throw new IllegalArgumentException("File descriptors passed in Intent");
3880 }
3881
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003882 if (type == INTENT_SENDER_BROADCAST) {
3883 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3884 throw new IllegalArgumentException(
3885 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3886 }
3887 }
3888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003889 synchronized(this) {
3890 int callingUid = Binder.getCallingUid();
3891 try {
3892 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3893 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003894 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003895 .getPackageUid(packageName);
3896 if (uid != Binder.getCallingUid()) {
3897 String msg = "Permission Denial: getIntentSender() from pid="
3898 + Binder.getCallingPid()
3899 + ", uid=" + Binder.getCallingUid()
3900 + ", (need uid=" + uid + ")"
3901 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003902 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003903 throw new SecurityException(msg);
3904 }
3905 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003906
3907 return getIntentSenderLocked(type, packageName, callingUid,
3908 token, resultWho, requestCode, intent, resolvedType, flags);
3909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 } catch (RemoteException e) {
3911 throw new SecurityException(e);
3912 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003913 }
3914 }
3915
3916 IIntentSender getIntentSenderLocked(int type,
3917 String packageName, int callingUid, IBinder token, String resultWho,
3918 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003919 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003920 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003921 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003922 if (index < 0) {
3923 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003924 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003925 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003926 if (activity.finishing) {
3927 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003929 }
3930
3931 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3932 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3933 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3934 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3935 |PendingIntent.FLAG_UPDATE_CURRENT);
3936
3937 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3938 type, packageName, activity, resultWho,
3939 requestCode, intent, resolvedType, flags);
3940 WeakReference<PendingIntentRecord> ref;
3941 ref = mIntentSenderRecords.get(key);
3942 PendingIntentRecord rec = ref != null ? ref.get() : null;
3943 if (rec != null) {
3944 if (!cancelCurrent) {
3945 if (updateCurrent) {
3946 rec.key.requestIntent.replaceExtras(intent);
3947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003948 return rec;
3949 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003950 rec.canceled = true;
3951 mIntentSenderRecords.remove(key);
3952 }
3953 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003954 return rec;
3955 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003956 rec = new PendingIntentRecord(this, key, callingUid);
3957 mIntentSenderRecords.put(key, rec.ref);
3958 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3959 if (activity.pendingResults == null) {
3960 activity.pendingResults
3961 = new HashSet<WeakReference<PendingIntentRecord>>();
3962 }
3963 activity.pendingResults.add(rec.ref);
3964 }
3965 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 }
3967
3968 public void cancelIntentSender(IIntentSender sender) {
3969 if (!(sender instanceof PendingIntentRecord)) {
3970 return;
3971 }
3972 synchronized(this) {
3973 PendingIntentRecord rec = (PendingIntentRecord)sender;
3974 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003975 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003976 .getPackageUid(rec.key.packageName);
3977 if (uid != Binder.getCallingUid()) {
3978 String msg = "Permission Denial: cancelIntentSender() from pid="
3979 + Binder.getCallingPid()
3980 + ", uid=" + Binder.getCallingUid()
3981 + " is not allowed to cancel packges "
3982 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003983 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003984 throw new SecurityException(msg);
3985 }
3986 } catch (RemoteException e) {
3987 throw new SecurityException(e);
3988 }
3989 cancelIntentSenderLocked(rec, true);
3990 }
3991 }
3992
3993 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3994 rec.canceled = true;
3995 mIntentSenderRecords.remove(rec.key);
3996 if (cleanActivity && rec.key.activity != null) {
3997 rec.key.activity.pendingResults.remove(rec.ref);
3998 }
3999 }
4000
4001 public String getPackageForIntentSender(IIntentSender pendingResult) {
4002 if (!(pendingResult instanceof PendingIntentRecord)) {
4003 return null;
4004 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004005 try {
4006 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4007 return res.key.packageName;
4008 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004009 }
4010 return null;
4011 }
4012
4013 public void setProcessLimit(int max) {
4014 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4015 "setProcessLimit()");
4016 mProcessLimit = max;
4017 }
4018
4019 public int getProcessLimit() {
4020 return mProcessLimit;
4021 }
4022
4023 void foregroundTokenDied(ForegroundToken token) {
4024 synchronized (ActivityManagerService.this) {
4025 synchronized (mPidsSelfLocked) {
4026 ForegroundToken cur
4027 = mForegroundProcesses.get(token.pid);
4028 if (cur != token) {
4029 return;
4030 }
4031 mForegroundProcesses.remove(token.pid);
4032 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4033 if (pr == null) {
4034 return;
4035 }
4036 pr.forcingToForeground = null;
4037 pr.foregroundServices = false;
4038 }
4039 updateOomAdjLocked();
4040 }
4041 }
4042
4043 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4044 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4045 "setProcessForeground()");
4046 synchronized(this) {
4047 boolean changed = false;
4048
4049 synchronized (mPidsSelfLocked) {
4050 ProcessRecord pr = mPidsSelfLocked.get(pid);
4051 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004052 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004053 return;
4054 }
4055 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4056 if (oldToken != null) {
4057 oldToken.token.unlinkToDeath(oldToken, 0);
4058 mForegroundProcesses.remove(pid);
4059 pr.forcingToForeground = null;
4060 changed = true;
4061 }
4062 if (isForeground && token != null) {
4063 ForegroundToken newToken = new ForegroundToken() {
4064 public void binderDied() {
4065 foregroundTokenDied(this);
4066 }
4067 };
4068 newToken.pid = pid;
4069 newToken.token = token;
4070 try {
4071 token.linkToDeath(newToken, 0);
4072 mForegroundProcesses.put(pid, newToken);
4073 pr.forcingToForeground = token;
4074 changed = true;
4075 } catch (RemoteException e) {
4076 // If the process died while doing this, we will later
4077 // do the cleanup with the process death link.
4078 }
4079 }
4080 }
4081
4082 if (changed) {
4083 updateOomAdjLocked();
4084 }
4085 }
4086 }
4087
4088 // =========================================================
4089 // PERMISSIONS
4090 // =========================================================
4091
4092 static class PermissionController extends IPermissionController.Stub {
4093 ActivityManagerService mActivityManagerService;
4094 PermissionController(ActivityManagerService activityManagerService) {
4095 mActivityManagerService = activityManagerService;
4096 }
4097
4098 public boolean checkPermission(String permission, int pid, int uid) {
4099 return mActivityManagerService.checkPermission(permission, pid,
4100 uid) == PackageManager.PERMISSION_GRANTED;
4101 }
4102 }
4103
4104 /**
4105 * This can be called with or without the global lock held.
4106 */
4107 int checkComponentPermission(String permission, int pid, int uid,
4108 int reqUid) {
4109 // We might be performing an operation on behalf of an indirect binder
4110 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4111 // client identity accordingly before proceeding.
4112 Identity tlsIdentity = sCallerIdentity.get();
4113 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004114 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004115 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4116 uid = tlsIdentity.uid;
4117 pid = tlsIdentity.pid;
4118 }
4119
4120 // Root, system server and our own process get to do everything.
4121 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4122 !Process.supportsProcesses()) {
4123 return PackageManager.PERMISSION_GRANTED;
4124 }
4125 // If the target requires a specific UID, always fail for others.
4126 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004127 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 return PackageManager.PERMISSION_DENIED;
4129 }
4130 if (permission == null) {
4131 return PackageManager.PERMISSION_GRANTED;
4132 }
4133 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004134 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004135 .checkUidPermission(permission, uid);
4136 } catch (RemoteException e) {
4137 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004138 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004139 }
4140 return PackageManager.PERMISSION_DENIED;
4141 }
4142
4143 /**
4144 * As the only public entry point for permissions checking, this method
4145 * can enforce the semantic that requesting a check on a null global
4146 * permission is automatically denied. (Internally a null permission
4147 * string is used when calling {@link #checkComponentPermission} in cases
4148 * when only uid-based security is needed.)
4149 *
4150 * This can be called with or without the global lock held.
4151 */
4152 public int checkPermission(String permission, int pid, int uid) {
4153 if (permission == null) {
4154 return PackageManager.PERMISSION_DENIED;
4155 }
4156 return checkComponentPermission(permission, pid, uid, -1);
4157 }
4158
4159 /**
4160 * Binder IPC calls go through the public entry point.
4161 * This can be called with or without the global lock held.
4162 */
4163 int checkCallingPermission(String permission) {
4164 return checkPermission(permission,
4165 Binder.getCallingPid(),
4166 Binder.getCallingUid());
4167 }
4168
4169 /**
4170 * This can be called with or without the global lock held.
4171 */
4172 void enforceCallingPermission(String permission, String func) {
4173 if (checkCallingPermission(permission)
4174 == PackageManager.PERMISSION_GRANTED) {
4175 return;
4176 }
4177
4178 String msg = "Permission Denial: " + func + " from pid="
4179 + Binder.getCallingPid()
4180 + ", uid=" + Binder.getCallingUid()
4181 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004182 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004183 throw new SecurityException(msg);
4184 }
4185
4186 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4187 ProviderInfo pi, int uid, int modeFlags) {
4188 try {
4189 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4190 if ((pi.readPermission != null) &&
4191 (pm.checkUidPermission(pi.readPermission, uid)
4192 != PackageManager.PERMISSION_GRANTED)) {
4193 return false;
4194 }
4195 }
4196 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4197 if ((pi.writePermission != null) &&
4198 (pm.checkUidPermission(pi.writePermission, uid)
4199 != PackageManager.PERMISSION_GRANTED)) {
4200 return false;
4201 }
4202 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004203 if (!pi.exported && pi.applicationInfo.uid != uid) {
4204 return false;
4205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004206 return true;
4207 } catch (RemoteException e) {
4208 return false;
4209 }
4210 }
4211
4212 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4213 int modeFlags) {
4214 // Root gets to do everything.
4215 if (uid == 0 || !Process.supportsProcesses()) {
4216 return true;
4217 }
4218 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4219 if (perms == null) return false;
4220 UriPermission perm = perms.get(uri);
4221 if (perm == null) return false;
4222 return (modeFlags&perm.modeFlags) == modeFlags;
4223 }
4224
4225 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4226 // Another redirected-binder-call permissions check as in
4227 // {@link checkComponentPermission}.
4228 Identity tlsIdentity = sCallerIdentity.get();
4229 if (tlsIdentity != null) {
4230 uid = tlsIdentity.uid;
4231 pid = tlsIdentity.pid;
4232 }
4233
4234 // Our own process gets to do everything.
4235 if (pid == MY_PID) {
4236 return PackageManager.PERMISSION_GRANTED;
4237 }
4238 synchronized(this) {
4239 return checkUriPermissionLocked(uri, uid, modeFlags)
4240 ? PackageManager.PERMISSION_GRANTED
4241 : PackageManager.PERMISSION_DENIED;
4242 }
4243 }
4244
Dianne Hackborn39792d22010-08-19 18:01:52 -07004245 /**
4246 * Check if the targetPkg can be granted permission to access uri by
4247 * the callingUid using the given modeFlags. Throws a security exception
4248 * if callingUid is not allowed to do this. Returns the uid of the target
4249 * if the URI permission grant should be performed; returns -1 if it is not
4250 * needed (for example targetPkg already has permission to access the URI).
4251 */
4252 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4253 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4255 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4256 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004257 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004258 }
4259
Joe Onorato8a9b2202010-02-26 18:56:32 -08004260 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004261 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004262
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004263 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004264
4265 // If this is not a content: uri, we can't do anything with it.
4266 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004267 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004268 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004269 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004270 }
4271
4272 String name = uri.getAuthority();
4273 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004274 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004275 if (cpr != null) {
4276 pi = cpr.info;
4277 } else {
4278 try {
4279 pi = pm.resolveContentProvider(name,
4280 PackageManager.GET_URI_PERMISSION_PATTERNS);
4281 } catch (RemoteException ex) {
4282 }
4283 }
4284 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004285 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004286 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287 }
4288
4289 int targetUid;
4290 try {
4291 targetUid = pm.getPackageUid(targetPkg);
4292 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004293 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004294 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004295 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004296 }
4297 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004298 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004299 }
4300
4301 // First... does the target actually need this permission?
4302 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4303 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004304 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004305 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004306 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 }
4308
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004309 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 if (!pi.grantUriPermissions) {
4311 throw new SecurityException("Provider " + pi.packageName
4312 + "/" + pi.name
4313 + " does not allow granting of Uri permissions (uri "
4314 + uri + ")");
4315 }
4316 if (pi.uriPermissionPatterns != null) {
4317 final int N = pi.uriPermissionPatterns.length;
4318 boolean allowed = false;
4319 for (int i=0; i<N; i++) {
4320 if (pi.uriPermissionPatterns[i] != null
4321 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4322 allowed = true;
4323 break;
4324 }
4325 }
4326 if (!allowed) {
4327 throw new SecurityException("Provider " + pi.packageName
4328 + "/" + pi.name
4329 + " does not allow granting of permission to path of Uri "
4330 + uri);
4331 }
4332 }
4333
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004334 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004335 // this uri?
4336 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4337 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4338 throw new SecurityException("Uid " + callingUid
4339 + " does not have permission to uri " + uri);
4340 }
4341 }
4342
Dianne Hackborn39792d22010-08-19 18:01:52 -07004343 return targetUid;
4344 }
4345
4346 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4347 Uri uri, int modeFlags, UriPermissionOwner owner) {
4348 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4349 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4350 if (modeFlags == 0) {
4351 return;
4352 }
4353
4354 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355 // to the uri, and the target doesn't. Let's now give this to
4356 // the target.
4357
Joe Onorato8a9b2202010-02-26 18:56:32 -08004358 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004359 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004361 HashMap<Uri, UriPermission> targetUris
4362 = mGrantedUriPermissions.get(targetUid);
4363 if (targetUris == null) {
4364 targetUris = new HashMap<Uri, UriPermission>();
4365 mGrantedUriPermissions.put(targetUid, targetUris);
4366 }
4367
4368 UriPermission perm = targetUris.get(uri);
4369 if (perm == null) {
4370 perm = new UriPermission(targetUid, uri);
4371 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004375 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 perm.globalModeFlags |= modeFlags;
4377 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004378 perm.readOwners.add(owner);
4379 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004381 perm.writeOwners.add(owner);
4382 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383 }
4384 }
4385
Dianne Hackborn39792d22010-08-19 18:01:52 -07004386 void grantUriPermissionLocked(int callingUid,
4387 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4388 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4389 if (targetUid < 0) {
4390 return;
4391 }
4392
4393 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4394 }
4395
4396 /**
4397 * Like checkGrantUriPermissionLocked, but takes an Intent.
4398 */
4399 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4400 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004401 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004402 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004403 + " from " + intent + "; flags=0x"
4404 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004407 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004408 }
4409 Uri data = intent.getData();
4410 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004411 return -1;
4412 }
4413 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4414 intent.getFlags());
4415 }
4416
4417 /**
4418 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4419 */
4420 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4421 String targetPkg, Intent intent, UriPermissionOwner owner) {
4422 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4423 intent.getFlags(), owner);
4424 }
4425
4426 void grantUriPermissionFromIntentLocked(int callingUid,
4427 String targetPkg, Intent intent, UriPermissionOwner owner) {
4428 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4429 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004430 return;
4431 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004432
4433 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004434 }
4435
4436 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4437 Uri uri, int modeFlags) {
4438 synchronized(this) {
4439 final ProcessRecord r = getRecordForAppLocked(caller);
4440 if (r == null) {
4441 throw new SecurityException("Unable to find app for caller "
4442 + caller
4443 + " when granting permission to uri " + uri);
4444 }
4445 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004446 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004447 }
4448 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004449 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004450 }
4451
4452 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4453 null);
4454 }
4455 }
4456
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004457 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4459 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4460 HashMap<Uri, UriPermission> perms
4461 = mGrantedUriPermissions.get(perm.uid);
4462 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004463 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004464 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 perms.remove(perm.uri);
4466 if (perms.size() == 0) {
4467 mGrantedUriPermissions.remove(perm.uid);
4468 }
4469 }
4470 }
4471 }
4472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4474 int modeFlags) {
4475 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4476 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4477 if (modeFlags == 0) {
4478 return;
4479 }
4480
Joe Onorato8a9b2202010-02-26 18:56:32 -08004481 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004482 "Revoking all granted permissions to " + uri);
4483
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004484 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485
4486 final String authority = uri.getAuthority();
4487 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004488 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 if (cpr != null) {
4490 pi = cpr.info;
4491 } else {
4492 try {
4493 pi = pm.resolveContentProvider(authority,
4494 PackageManager.GET_URI_PERMISSION_PATTERNS);
4495 } catch (RemoteException ex) {
4496 }
4497 }
4498 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004499 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500 return;
4501 }
4502
4503 // Does the caller have this permission on the URI?
4504 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4505 // Right now, if you are not the original owner of the permission,
4506 // you are not allowed to revoke it.
4507 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4508 throw new SecurityException("Uid " + callingUid
4509 + " does not have permission to uri " + uri);
4510 //}
4511 }
4512
4513 // Go through all of the permissions and remove any that match.
4514 final List<String> SEGMENTS = uri.getPathSegments();
4515 if (SEGMENTS != null) {
4516 final int NS = SEGMENTS.size();
4517 int N = mGrantedUriPermissions.size();
4518 for (int i=0; i<N; i++) {
4519 HashMap<Uri, UriPermission> perms
4520 = mGrantedUriPermissions.valueAt(i);
4521 Iterator<UriPermission> it = perms.values().iterator();
4522 toploop:
4523 while (it.hasNext()) {
4524 UriPermission perm = it.next();
4525 Uri targetUri = perm.uri;
4526 if (!authority.equals(targetUri.getAuthority())) {
4527 continue;
4528 }
4529 List<String> targetSegments = targetUri.getPathSegments();
4530 if (targetSegments == null) {
4531 continue;
4532 }
4533 if (targetSegments.size() < NS) {
4534 continue;
4535 }
4536 for (int j=0; j<NS; j++) {
4537 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4538 continue toploop;
4539 }
4540 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004541 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004542 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004543 perm.clearModes(modeFlags);
4544 if (perm.modeFlags == 0) {
4545 it.remove();
4546 }
4547 }
4548 if (perms.size() == 0) {
4549 mGrantedUriPermissions.remove(
4550 mGrantedUriPermissions.keyAt(i));
4551 N--;
4552 i--;
4553 }
4554 }
4555 }
4556 }
4557
4558 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4559 int modeFlags) {
4560 synchronized(this) {
4561 final ProcessRecord r = getRecordForAppLocked(caller);
4562 if (r == null) {
4563 throw new SecurityException("Unable to find app for caller "
4564 + caller
4565 + " when revoking permission to uri " + uri);
4566 }
4567 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004568 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004569 return;
4570 }
4571
4572 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4573 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4574 if (modeFlags == 0) {
4575 return;
4576 }
4577
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004578 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579
4580 final String authority = uri.getAuthority();
4581 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004582 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004583 if (cpr != null) {
4584 pi = cpr.info;
4585 } else {
4586 try {
4587 pi = pm.resolveContentProvider(authority,
4588 PackageManager.GET_URI_PERMISSION_PATTERNS);
4589 } catch (RemoteException ex) {
4590 }
4591 }
4592 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004593 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 return;
4595 }
4596
4597 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4598 }
4599 }
4600
Dianne Hackborn7e269642010-08-25 19:50:20 -07004601 @Override
4602 public IBinder newUriPermissionOwner(String name) {
4603 synchronized(this) {
4604 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4605 return owner.getExternalTokenLocked();
4606 }
4607 }
4608
4609 @Override
4610 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4611 Uri uri, int modeFlags) {
4612 synchronized(this) {
4613 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4614 if (owner == null) {
4615 throw new IllegalArgumentException("Unknown owner: " + token);
4616 }
4617 if (fromUid != Binder.getCallingUid()) {
4618 if (Binder.getCallingUid() != Process.myUid()) {
4619 // Only system code can grant URI permissions on behalf
4620 // of other users.
4621 throw new SecurityException("nice try");
4622 }
4623 }
4624 if (targetPkg == null) {
4625 throw new IllegalArgumentException("null target");
4626 }
4627 if (uri == null) {
4628 throw new IllegalArgumentException("null uri");
4629 }
4630
4631 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4632 }
4633 }
4634
4635 @Override
4636 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4637 synchronized(this) {
4638 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4639 if (owner == null) {
4640 throw new IllegalArgumentException("Unknown owner: " + token);
4641 }
4642
4643 if (uri == null) {
4644 owner.removeUriPermissionsLocked(mode);
4645 } else {
4646 owner.removeUriPermissionLocked(uri, mode);
4647 }
4648 }
4649 }
4650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004651 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4652 synchronized (this) {
4653 ProcessRecord app =
4654 who != null ? getRecordForAppLocked(who) : null;
4655 if (app == null) return;
4656
4657 Message msg = Message.obtain();
4658 msg.what = WAIT_FOR_DEBUGGER_MSG;
4659 msg.obj = app;
4660 msg.arg1 = waiting ? 1 : 0;
4661 mHandler.sendMessage(msg);
4662 }
4663 }
4664
4665 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4666 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004667 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004668 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004669 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 }
4671
4672 // =========================================================
4673 // TASK MANAGEMENT
4674 // =========================================================
4675
4676 public List getTasks(int maxNum, int flags,
4677 IThumbnailReceiver receiver) {
4678 ArrayList list = new ArrayList();
4679
4680 PendingThumbnailsRecord pending = null;
4681 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004682 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004683
4684 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004685 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004686 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4687 + ", receiver=" + receiver);
4688
4689 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4690 != PackageManager.PERMISSION_GRANTED) {
4691 if (receiver != null) {
4692 // If the caller wants to wait for pending thumbnails,
4693 // it ain't gonna get them.
4694 try {
4695 receiver.finished();
4696 } catch (RemoteException ex) {
4697 }
4698 }
4699 String msg = "Permission Denial: getTasks() from pid="
4700 + Binder.getCallingPid()
4701 + ", uid=" + Binder.getCallingUid()
4702 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004703 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004704 throw new SecurityException(msg);
4705 }
4706
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004707 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004708 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004709 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004710 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 CharSequence topDescription = null;
4712 TaskRecord curTask = null;
4713 int numActivities = 0;
4714 int numRunning = 0;
4715 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004716 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004718 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004719
4720 // Initialize state for next task if needed.
4721 if (top == null ||
4722 (top.state == ActivityState.INITIALIZING
4723 && top.task == r.task)) {
4724 top = r;
4725 topDescription = r.description;
4726 curTask = r.task;
4727 numActivities = numRunning = 0;
4728 }
4729
4730 // Add 'r' into the current task.
4731 numActivities++;
4732 if (r.app != null && r.app.thread != null) {
4733 numRunning++;
4734 }
4735 if (topDescription == null) {
4736 topDescription = r.description;
4737 }
4738
Joe Onorato8a9b2202010-02-26 18:56:32 -08004739 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 TAG, r.intent.getComponent().flattenToShortString()
4741 + ": task=" + r.task);
4742
4743 // If the next one is a different task, generate a new
4744 // TaskInfo entry for what we have.
4745 if (next == null || next.task != curTask) {
4746 ActivityManager.RunningTaskInfo ci
4747 = new ActivityManager.RunningTaskInfo();
4748 ci.id = curTask.taskId;
4749 ci.baseActivity = r.intent.getComponent();
4750 ci.topActivity = top.intent.getComponent();
4751 ci.thumbnail = top.thumbnail;
4752 ci.description = topDescription;
4753 ci.numActivities = numActivities;
4754 ci.numRunning = numRunning;
4755 //System.out.println(
4756 // "#" + maxNum + ": " + " descr=" + ci.description);
4757 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004758 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759 TAG, "State=" + top.state + "Idle=" + top.idle
4760 + " app=" + top.app
4761 + " thr=" + (top.app != null ? top.app.thread : null));
4762 if (top.state == ActivityState.RESUMED
4763 || top.state == ActivityState.PAUSING) {
4764 if (top.idle && top.app != null
4765 && top.app.thread != null) {
4766 topRecord = top;
4767 topThumbnail = top.app.thread;
4768 } else {
4769 top.thumbnailNeeded = true;
4770 }
4771 }
4772 if (pending == null) {
4773 pending = new PendingThumbnailsRecord(receiver);
4774 }
4775 pending.pendingRecords.add(top);
4776 }
4777 list.add(ci);
4778 maxNum--;
4779 top = null;
4780 }
4781 }
4782
4783 if (pending != null) {
4784 mPendingThumbnails.add(pending);
4785 }
4786 }
4787
Joe Onorato8a9b2202010-02-26 18:56:32 -08004788 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789
4790 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004791 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004792 try {
4793 topThumbnail.requestThumbnail(topRecord);
4794 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004795 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 sendPendingThumbnail(null, topRecord, null, null, true);
4797 }
4798 }
4799
4800 if (pending == null && receiver != null) {
4801 // In this case all thumbnails were available and the client
4802 // is being asked to be told when the remaining ones come in...
4803 // which is unusually, since the top-most currently running
4804 // activity should never have a canned thumbnail! Oh well.
4805 try {
4806 receiver.finished();
4807 } catch (RemoteException ex) {
4808 }
4809 }
4810
4811 return list;
4812 }
4813
4814 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4815 int flags) {
4816 synchronized (this) {
4817 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4818 "getRecentTasks()");
4819
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004820 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004822 final int N = mRecentTasks.size();
4823 ArrayList<ActivityManager.RecentTaskInfo> res
4824 = new ArrayList<ActivityManager.RecentTaskInfo>(
4825 maxNum < N ? maxNum : N);
4826 for (int i=0; i<N && maxNum > 0; i++) {
4827 TaskRecord tr = mRecentTasks.get(i);
4828 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4829 || (tr.intent == null)
4830 || ((tr.intent.getFlags()
4831 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4832 ActivityManager.RecentTaskInfo rti
4833 = new ActivityManager.RecentTaskInfo();
4834 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4835 rti.baseIntent = new Intent(
4836 tr.intent != null ? tr.intent : tr.affinityIntent);
4837 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004838
4839 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4840 // Check whether this activity is currently available.
4841 try {
4842 if (rti.origActivity != null) {
4843 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4844 continue;
4845 }
4846 } else if (rti.baseIntent != null) {
4847 if (pm.queryIntentActivities(rti.baseIntent,
4848 null, 0) == null) {
4849 continue;
4850 }
4851 }
4852 } catch (RemoteException e) {
4853 // Will never happen.
4854 }
4855 }
4856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004857 res.add(rti);
4858 maxNum--;
4859 }
4860 }
4861 return res;
4862 }
4863 }
4864
4865 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4866 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004867 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 TaskRecord jt = startTask;
4869
4870 // First look backwards
4871 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004872 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004873 if (r.task != jt) {
4874 jt = r.task;
4875 if (affinity.equals(jt.affinity)) {
4876 return j;
4877 }
4878 }
4879 }
4880
4881 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004882 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004883 jt = startTask;
4884 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004885 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004886 if (r.task != jt) {
4887 if (affinity.equals(jt.affinity)) {
4888 return j;
4889 }
4890 jt = r.task;
4891 }
4892 }
4893
4894 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004895 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 return N-1;
4897 }
4898
4899 return -1;
4900 }
4901
4902 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004903 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004904 */
4905 public void moveTaskToFront(int task) {
4906 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4907 "moveTaskToFront()");
4908
4909 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004910 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4911 Binder.getCallingUid(), "Task to front")) {
4912 return;
4913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004914 final long origId = Binder.clearCallingIdentity();
4915 try {
4916 int N = mRecentTasks.size();
4917 for (int i=0; i<N; i++) {
4918 TaskRecord tr = mRecentTasks.get(i);
4919 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004920 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004921 return;
4922 }
4923 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004924 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4925 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004926 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004927 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928 return;
4929 }
4930 }
4931 } finally {
4932 Binder.restoreCallingIdentity(origId);
4933 }
4934 }
4935 }
4936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 public void moveTaskToBack(int task) {
4938 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4939 "moveTaskToBack()");
4940
4941 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004942 if (mMainStack.mResumedActivity != null
4943 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004944 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4945 Binder.getCallingUid(), "Task to back")) {
4946 return;
4947 }
4948 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004950 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004951 Binder.restoreCallingIdentity(origId);
4952 }
4953 }
4954
4955 /**
4956 * Moves an activity, and all of the other activities within the same task, to the bottom
4957 * of the history stack. The activity's order within the task is unchanged.
4958 *
4959 * @param token A reference to the activity we wish to move
4960 * @param nonRoot If false then this only works if the activity is the root
4961 * of a task; if true it will work for any activity in a task.
4962 * @return Returns true if the move completed, false if not.
4963 */
4964 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4965 synchronized(this) {
4966 final long origId = Binder.clearCallingIdentity();
4967 int taskId = getTaskForActivityLocked(token, !nonRoot);
4968 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004969 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004970 }
4971 Binder.restoreCallingIdentity(origId);
4972 }
4973 return false;
4974 }
4975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004976 public void moveTaskBackwards(int task) {
4977 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4978 "moveTaskBackwards()");
4979
4980 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004981 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4982 Binder.getCallingUid(), "Task backwards")) {
4983 return;
4984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004985 final long origId = Binder.clearCallingIdentity();
4986 moveTaskBackwardsLocked(task);
4987 Binder.restoreCallingIdentity(origId);
4988 }
4989 }
4990
4991 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004992 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 }
4994
4995 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4996 synchronized(this) {
4997 return getTaskForActivityLocked(token, onlyRoot);
4998 }
4999 }
5000
5001 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005002 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005003 TaskRecord lastTask = null;
5004 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005005 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005006 if (r == token) {
5007 if (!onlyRoot || lastTask != r.task) {
5008 return r.task.taskId;
5009 }
5010 return -1;
5011 }
5012 lastTask = r.task;
5013 }
5014
5015 return -1;
5016 }
5017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 public void finishOtherInstances(IBinder token, ComponentName className) {
5019 synchronized(this) {
5020 final long origId = Binder.clearCallingIdentity();
5021
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005022 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005023 TaskRecord lastTask = null;
5024 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005025 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 if (r.realActivity.equals(className)
5027 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005028 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005029 null, "others")) {
5030 i--;
5031 N--;
5032 }
5033 }
5034 lastTask = r.task;
5035 }
5036
5037 Binder.restoreCallingIdentity(origId);
5038 }
5039 }
5040
5041 // =========================================================
5042 // THUMBNAILS
5043 // =========================================================
5044
5045 public void reportThumbnail(IBinder token,
5046 Bitmap thumbnail, CharSequence description) {
5047 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5048 final long origId = Binder.clearCallingIdentity();
5049 sendPendingThumbnail(null, token, thumbnail, description, true);
5050 Binder.restoreCallingIdentity(origId);
5051 }
5052
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005053 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005054 Bitmap thumbnail, CharSequence description, boolean always) {
5055 TaskRecord task = null;
5056 ArrayList receivers = null;
5057
5058 //System.out.println("Send pending thumbnail: " + r);
5059
5060 synchronized(this) {
5061 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005062 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 if (index < 0) {
5064 return;
5065 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005066 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005067 }
5068 if (thumbnail == null) {
5069 thumbnail = r.thumbnail;
5070 description = r.description;
5071 }
5072 if (thumbnail == null && !always) {
5073 // If there is no thumbnail, and this entry is not actually
5074 // going away, then abort for now and pick up the next
5075 // thumbnail we get.
5076 return;
5077 }
5078 task = r.task;
5079
5080 int N = mPendingThumbnails.size();
5081 int i=0;
5082 while (i<N) {
5083 PendingThumbnailsRecord pr =
5084 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5085 //System.out.println("Looking in " + pr.pendingRecords);
5086 if (pr.pendingRecords.remove(r)) {
5087 if (receivers == null) {
5088 receivers = new ArrayList();
5089 }
5090 receivers.add(pr);
5091 if (pr.pendingRecords.size() == 0) {
5092 pr.finished = true;
5093 mPendingThumbnails.remove(i);
5094 N--;
5095 continue;
5096 }
5097 }
5098 i++;
5099 }
5100 }
5101
5102 if (receivers != null) {
5103 final int N = receivers.size();
5104 for (int i=0; i<N; i++) {
5105 try {
5106 PendingThumbnailsRecord pr =
5107 (PendingThumbnailsRecord)receivers.get(i);
5108 pr.receiver.newThumbnail(
5109 task != null ? task.taskId : -1, thumbnail, description);
5110 if (pr.finished) {
5111 pr.receiver.finished();
5112 }
5113 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005114 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 }
5116 }
5117 }
5118 }
5119
5120 // =========================================================
5121 // CONTENT PROVIDERS
5122 // =========================================================
5123
5124 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5125 List providers = null;
5126 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005127 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005129 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 } catch (RemoteException ex) {
5131 }
5132 if (providers != null) {
5133 final int N = providers.size();
5134 for (int i=0; i<N; i++) {
5135 ProviderInfo cpi =
5136 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005137 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 if (cpr == null) {
5139 cpr = new ContentProviderRecord(cpi, app.info);
5140 mProvidersByClass.put(cpi.name, cpr);
5141 }
5142 app.pubProviders.put(cpi.name, cpr);
5143 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005144 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 }
5146 }
5147 return providers;
5148 }
5149
5150 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005151 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005152 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5153 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5154 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5155 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005156 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005157 return null;
5158 }
5159 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5160 cpi.exported ? -1 : cpi.applicationInfo.uid)
5161 == PackageManager.PERMISSION_GRANTED) {
5162 return null;
5163 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005164
5165 PathPermission[] pps = cpi.pathPermissions;
5166 if (pps != null) {
5167 int i = pps.length;
5168 while (i > 0) {
5169 i--;
5170 PathPermission pp = pps[i];
5171 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5172 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005173 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005174 return null;
5175 }
5176 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5177 cpi.exported ? -1 : cpi.applicationInfo.uid)
5178 == PackageManager.PERMISSION_GRANTED) {
5179 return null;
5180 }
5181 }
5182 }
5183
Dianne Hackbornb424b632010-08-18 15:59:05 -07005184 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5185 if (perms != null) {
5186 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5187 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5188 return null;
5189 }
5190 }
5191 }
5192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193 String msg = "Permission Denial: opening provider " + cpi.name
5194 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5195 + ", uid=" + callingUid + ") requires "
5196 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005197 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005198 return msg;
5199 }
5200
5201 private final ContentProviderHolder getContentProviderImpl(
5202 IApplicationThread caller, String name) {
5203 ContentProviderRecord cpr;
5204 ProviderInfo cpi = null;
5205
5206 synchronized(this) {
5207 ProcessRecord r = null;
5208 if (caller != null) {
5209 r = getRecordForAppLocked(caller);
5210 if (r == null) {
5211 throw new SecurityException(
5212 "Unable to find app for caller " + caller
5213 + " (pid=" + Binder.getCallingPid()
5214 + ") when getting content provider " + name);
5215 }
5216 }
5217
5218 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005219 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 if (cpr != null) {
5221 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005222 String msg;
5223 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5224 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 }
5226
5227 if (r != null && cpr.canRunHere(r)) {
5228 // This provider has been published or is in the process
5229 // of being published... but it is also allowed to run
5230 // in the caller's process, so don't make a connection
5231 // and just let the caller instantiate its own instance.
5232 if (cpr.provider != null) {
5233 // don't give caller the provider object, it needs
5234 // to make its own.
5235 cpr = new ContentProviderRecord(cpr);
5236 }
5237 return cpr;
5238 }
5239
5240 final long origId = Binder.clearCallingIdentity();
5241
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005242 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 // return it right away.
5244 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005245 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005246 "Adding provider requested by "
5247 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005248 + cpr.info.processName);
5249 Integer cnt = r.conProviders.get(cpr);
5250 if (cnt == null) {
5251 r.conProviders.put(cpr, new Integer(1));
5252 } else {
5253 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005256 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5257 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005258 // make sure to count it as being accessed and thus
5259 // back up on the LRU list. This is good because
5260 // content providers are often expensive to start.
5261 updateLruProcessLocked(cpr.app, false, true);
5262 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005263 } else {
5264 cpr.externals++;
5265 }
5266
5267 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005268 updateOomAdjLocked(cpr.app);
5269 }
5270
5271 Binder.restoreCallingIdentity(origId);
5272
5273 } else {
5274 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005275 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005276 resolveContentProvider(name,
5277 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 } catch (RemoteException ex) {
5279 }
5280 if (cpi == null) {
5281 return null;
5282 }
5283
Dianne Hackbornb424b632010-08-18 15:59:05 -07005284 String msg;
5285 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5286 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287 }
5288
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005289 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005290 && !cpi.processName.equals("system")) {
5291 // If this content provider does not run in the system
5292 // process, and the system is not yet ready to run other
5293 // processes, then fail fast instead of hanging.
5294 throw new IllegalArgumentException(
5295 "Attempt to launch content provider before system ready");
5296 }
5297
Dianne Hackborn860755f2010-06-03 18:47:52 -07005298 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 final boolean firstClass = cpr == null;
5300 if (firstClass) {
5301 try {
5302 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005303 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 getApplicationInfo(
5305 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005306 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005308 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005309 + cpi.name);
5310 return null;
5311 }
5312 cpr = new ContentProviderRecord(cpi, ai);
5313 } catch (RemoteException ex) {
5314 // pm is in same process, this will never happen.
5315 }
5316 }
5317
5318 if (r != null && cpr.canRunHere(r)) {
5319 // If this is a multiprocess provider, then just return its
5320 // info and allow the caller to instantiate it. Only do
5321 // this if the provider is the same user as the caller's
5322 // process, or can run as root (so can be in any process).
5323 return cpr;
5324 }
5325
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005326 if (DEBUG_PROVIDER) {
5327 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005328 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005329 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 }
5331
5332 // This is single process, and our app is now connecting to it.
5333 // See if we are already in the process of launching this
5334 // provider.
5335 final int N = mLaunchingProviders.size();
5336 int i;
5337 for (i=0; i<N; i++) {
5338 if (mLaunchingProviders.get(i) == cpr) {
5339 break;
5340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005341 }
5342
5343 // If the provider is not already being launched, then get it
5344 // started.
5345 if (i >= N) {
5346 final long origId = Binder.clearCallingIdentity();
5347 ProcessRecord proc = startProcessLocked(cpi.processName,
5348 cpr.appInfo, false, 0, "content provider",
5349 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005350 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005351 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005352 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 + cpi.applicationInfo.packageName + "/"
5354 + cpi.applicationInfo.uid + " for provider "
5355 + name + ": process is bad");
5356 return null;
5357 }
5358 cpr.launchingApp = proc;
5359 mLaunchingProviders.add(cpr);
5360 Binder.restoreCallingIdentity(origId);
5361 }
5362
5363 // Make sure the provider is published (the same provider class
5364 // may be published under multiple names).
5365 if (firstClass) {
5366 mProvidersByClass.put(cpi.name, cpr);
5367 }
5368 mProvidersByName.put(name, cpr);
5369
5370 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005371 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005372 "Adding provider requested by "
5373 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005374 + cpr.info.processName);
5375 Integer cnt = r.conProviders.get(cpr);
5376 if (cnt == null) {
5377 r.conProviders.put(cpr, new Integer(1));
5378 } else {
5379 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005381 cpr.clients.add(r);
5382 } else {
5383 cpr.externals++;
5384 }
5385 }
5386 }
5387
5388 // Wait for the provider to be published...
5389 synchronized (cpr) {
5390 while (cpr.provider == null) {
5391 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005392 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005393 + cpi.applicationInfo.packageName + "/"
5394 + cpi.applicationInfo.uid + " for provider "
5395 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005396 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005397 cpi.applicationInfo.packageName,
5398 cpi.applicationInfo.uid, name);
5399 return null;
5400 }
5401 try {
5402 cpr.wait();
5403 } catch (InterruptedException ex) {
5404 }
5405 }
5406 }
5407 return cpr;
5408 }
5409
5410 public final ContentProviderHolder getContentProvider(
5411 IApplicationThread caller, String name) {
5412 if (caller == null) {
5413 String msg = "null IApplicationThread when getting content provider "
5414 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005415 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005416 throw new SecurityException(msg);
5417 }
5418
5419 return getContentProviderImpl(caller, name);
5420 }
5421
5422 private ContentProviderHolder getContentProviderExternal(String name) {
5423 return getContentProviderImpl(null, name);
5424 }
5425
5426 /**
5427 * Drop a content provider from a ProcessRecord's bookkeeping
5428 * @param cpr
5429 */
5430 public void removeContentProvider(IApplicationThread caller, String name) {
5431 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005432 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005433 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005434 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005435 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005436 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005437 return;
5438 }
5439 final ProcessRecord r = getRecordForAppLocked(caller);
5440 if (r == null) {
5441 throw new SecurityException(
5442 "Unable to find app for caller " + caller +
5443 " when removing content provider " + name);
5444 }
5445 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005446 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005447 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005448 + r.info.processName + " from process "
5449 + localCpr.appInfo.processName);
5450 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005452 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005453 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005454 return;
5455 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005456 Integer cnt = r.conProviders.get(localCpr);
5457 if (cnt == null || cnt.intValue() <= 1) {
5458 localCpr.clients.remove(r);
5459 r.conProviders.remove(localCpr);
5460 } else {
5461 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005463 }
5464 updateOomAdjLocked();
5465 }
5466 }
5467
5468 private void removeContentProviderExternal(String name) {
5469 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005470 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005471 if(cpr == null) {
5472 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005473 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 return;
5475 }
5476
5477 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005478 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 localCpr.externals--;
5480 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005481 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005482 }
5483 updateOomAdjLocked();
5484 }
5485 }
5486
5487 public final void publishContentProviders(IApplicationThread caller,
5488 List<ContentProviderHolder> providers) {
5489 if (providers == null) {
5490 return;
5491 }
5492
5493 synchronized(this) {
5494 final ProcessRecord r = getRecordForAppLocked(caller);
5495 if (r == null) {
5496 throw new SecurityException(
5497 "Unable to find app for caller " + caller
5498 + " (pid=" + Binder.getCallingPid()
5499 + ") when publishing content providers");
5500 }
5501
5502 final long origId = Binder.clearCallingIdentity();
5503
5504 final int N = providers.size();
5505 for (int i=0; i<N; i++) {
5506 ContentProviderHolder src = providers.get(i);
5507 if (src == null || src.info == null || src.provider == null) {
5508 continue;
5509 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005510 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 if (dst != null) {
5512 mProvidersByClass.put(dst.info.name, dst);
5513 String names[] = dst.info.authority.split(";");
5514 for (int j = 0; j < names.length; j++) {
5515 mProvidersByName.put(names[j], dst);
5516 }
5517
5518 int NL = mLaunchingProviders.size();
5519 int j;
5520 for (j=0; j<NL; j++) {
5521 if (mLaunchingProviders.get(j) == dst) {
5522 mLaunchingProviders.remove(j);
5523 j--;
5524 NL--;
5525 }
5526 }
5527 synchronized (dst) {
5528 dst.provider = src.provider;
5529 dst.app = r;
5530 dst.notifyAll();
5531 }
5532 updateOomAdjLocked(r);
5533 }
5534 }
5535
5536 Binder.restoreCallingIdentity(origId);
5537 }
5538 }
5539
5540 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005541 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005542 synchronized (mSelf) {
5543 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5544 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005545 if (providers != null) {
5546 for (int i=providers.size()-1; i>=0; i--) {
5547 ProviderInfo pi = (ProviderInfo)providers.get(i);
5548 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5549 Slog.w(TAG, "Not installing system proc provider " + pi.name
5550 + ": not system .apk");
5551 providers.remove(i);
5552 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005553 }
5554 }
5555 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005556 if (providers != null) {
5557 mSystemThread.installSystemProviders(providers);
5558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005559 }
5560
5561 // =========================================================
5562 // GLOBAL MANAGEMENT
5563 // =========================================================
5564
5565 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5566 ApplicationInfo info, String customProcess) {
5567 String proc = customProcess != null ? customProcess : info.processName;
5568 BatteryStatsImpl.Uid.Proc ps = null;
5569 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5570 synchronized (stats) {
5571 ps = stats.getProcessStatsLocked(info.uid, proc);
5572 }
5573 return new ProcessRecord(ps, thread, info, proc);
5574 }
5575
5576 final ProcessRecord addAppLocked(ApplicationInfo info) {
5577 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5578
5579 if (app == null) {
5580 app = newProcessRecordLocked(null, info, null);
5581 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005582 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005583 }
5584
5585 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5586 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5587 app.persistent = true;
5588 app.maxAdj = CORE_SERVER_ADJ;
5589 }
5590 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5591 mPersistentStartingProcesses.add(app);
5592 startProcessLocked(app, "added application", app.processName);
5593 }
5594
5595 return app;
5596 }
5597
5598 public void unhandledBack() {
5599 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5600 "unhandledBack()");
5601
5602 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005603 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005604 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005605 TAG, "Performing unhandledBack(): stack size = " + count);
5606 if (count > 1) {
5607 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005608 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005609 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5610 Binder.restoreCallingIdentity(origId);
5611 }
5612 }
5613 }
5614
5615 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5616 String name = uri.getAuthority();
5617 ContentProviderHolder cph = getContentProviderExternal(name);
5618 ParcelFileDescriptor pfd = null;
5619 if (cph != null) {
5620 // We record the binder invoker's uid in thread-local storage before
5621 // going to the content provider to open the file. Later, in the code
5622 // that handles all permissions checks, we look for this uid and use
5623 // that rather than the Activity Manager's own uid. The effect is that
5624 // we do the check against the caller's permissions even though it looks
5625 // to the content provider like the Activity Manager itself is making
5626 // the request.
5627 sCallerIdentity.set(new Identity(
5628 Binder.getCallingPid(), Binder.getCallingUid()));
5629 try {
5630 pfd = cph.provider.openFile(uri, "r");
5631 } catch (FileNotFoundException e) {
5632 // do nothing; pfd will be returned null
5633 } finally {
5634 // Ensure that whatever happens, we clean up the identity state
5635 sCallerIdentity.remove();
5636 }
5637
5638 // We've got the fd now, so we're done with the provider.
5639 removeContentProviderExternal(name);
5640 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005641 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005642 }
5643 return pfd;
5644 }
5645
5646 public void goingToSleep() {
5647 synchronized(this) {
5648 mSleeping = true;
5649 mWindowManager.setEventDispatching(false);
5650
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005651 if (mMainStack.mResumedActivity != null) {
5652 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005653 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005654 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005656
5657 // Initialize the wake times of all processes.
5658 checkExcessiveWakeLocksLocked(false);
5659 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5660 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5661 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005662 }
5663 }
5664
Dianne Hackborn55280a92009-05-07 15:53:46 -07005665 public boolean shutdown(int timeout) {
5666 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5667 != PackageManager.PERMISSION_GRANTED) {
5668 throw new SecurityException("Requires permission "
5669 + android.Manifest.permission.SHUTDOWN);
5670 }
5671
5672 boolean timedout = false;
5673
5674 synchronized(this) {
5675 mShuttingDown = true;
5676 mWindowManager.setEventDispatching(false);
5677
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005678 if (mMainStack.mResumedActivity != null) {
5679 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005680 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005681 while (mMainStack.mResumedActivity != null
5682 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005683 long delay = endTime - System.currentTimeMillis();
5684 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005685 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005686 timedout = true;
5687 break;
5688 }
5689 try {
5690 this.wait();
5691 } catch (InterruptedException e) {
5692 }
5693 }
5694 }
5695 }
5696
5697 mUsageStatsService.shutdown();
5698 mBatteryStatsService.shutdown();
5699
5700 return timedout;
5701 }
5702
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005703 public void wakingUp() {
5704 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005705 if (mMainStack.mGoingToSleep.isHeld()) {
5706 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005707 }
5708 mWindowManager.setEventDispatching(true);
5709 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005710 mMainStack.resumeTopActivityLocked(null);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005711 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005712 }
5713 }
5714
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005715 public void stopAppSwitches() {
5716 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5717 != PackageManager.PERMISSION_GRANTED) {
5718 throw new SecurityException("Requires permission "
5719 + android.Manifest.permission.STOP_APP_SWITCHES);
5720 }
5721
5722 synchronized(this) {
5723 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5724 + APP_SWITCH_DELAY_TIME;
5725 mDidAppSwitch = false;
5726 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5727 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5728 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5729 }
5730 }
5731
5732 public void resumeAppSwitches() {
5733 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5734 != PackageManager.PERMISSION_GRANTED) {
5735 throw new SecurityException("Requires permission "
5736 + android.Manifest.permission.STOP_APP_SWITCHES);
5737 }
5738
5739 synchronized(this) {
5740 // Note that we don't execute any pending app switches... we will
5741 // let those wait until either the timeout, or the next start
5742 // activity request.
5743 mAppSwitchesAllowedTime = 0;
5744 }
5745 }
5746
5747 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5748 String name) {
5749 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5750 return true;
5751 }
5752
5753 final int perm = checkComponentPermission(
5754 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5755 callingUid, -1);
5756 if (perm == PackageManager.PERMISSION_GRANTED) {
5757 return true;
5758 }
5759
Joe Onorato8a9b2202010-02-26 18:56:32 -08005760 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005761 return false;
5762 }
5763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005764 public void setDebugApp(String packageName, boolean waitForDebugger,
5765 boolean persistent) {
5766 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5767 "setDebugApp()");
5768
5769 // Note that this is not really thread safe if there are multiple
5770 // callers into it at the same time, but that's not a situation we
5771 // care about.
5772 if (persistent) {
5773 final ContentResolver resolver = mContext.getContentResolver();
5774 Settings.System.putString(
5775 resolver, Settings.System.DEBUG_APP,
5776 packageName);
5777 Settings.System.putInt(
5778 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5779 waitForDebugger ? 1 : 0);
5780 }
5781
5782 synchronized (this) {
5783 if (!persistent) {
5784 mOrigDebugApp = mDebugApp;
5785 mOrigWaitForDebugger = mWaitForDebugger;
5786 }
5787 mDebugApp = packageName;
5788 mWaitForDebugger = waitForDebugger;
5789 mDebugTransient = !persistent;
5790 if (packageName != null) {
5791 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005792 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005793 Binder.restoreCallingIdentity(origId);
5794 }
5795 }
5796 }
5797
5798 public void setAlwaysFinish(boolean enabled) {
5799 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5800 "setAlwaysFinish()");
5801
5802 Settings.System.putInt(
5803 mContext.getContentResolver(),
5804 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5805
5806 synchronized (this) {
5807 mAlwaysFinishActivities = enabled;
5808 }
5809 }
5810
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005811 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005812 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005813 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005814 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005815 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005816 }
5817 }
5818
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005819 public boolean isUserAMonkey() {
5820 // For now the fact that there is a controller implies
5821 // we have a monkey.
5822 synchronized (this) {
5823 return mController != null;
5824 }
5825 }
5826
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005827 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005828 synchronized (this) {
5829 mWatchers.register(watcher);
5830 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005831 }
5832
5833 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005834 synchronized (this) {
5835 mWatchers.unregister(watcher);
5836 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005837 }
5838
Daniel Sandler69a48172010-06-23 16:29:36 -04005839 public void setImmersive(IBinder token, boolean immersive) {
5840 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005841 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005842 if (index < 0) {
5843 throw new IllegalArgumentException();
5844 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005845 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005846 r.immersive = immersive;
5847 }
5848 }
5849
5850 public boolean isImmersive(IBinder token) {
5851 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005852 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005853 if (index < 0) {
5854 throw new IllegalArgumentException();
5855 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005856 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005857 return r.immersive;
5858 }
5859 }
5860
5861 public boolean isTopActivityImmersive() {
5862 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005863 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005864 return (r != null) ? r.immersive : false;
5865 }
5866 }
5867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 public final void enterSafeMode() {
5869 synchronized(this) {
5870 // It only makes sense to do this before the system is ready
5871 // and started launching other packages.
5872 if (!mSystemReady) {
5873 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005874 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005875 } catch (RemoteException e) {
5876 }
5877
5878 View v = LayoutInflater.from(mContext).inflate(
5879 com.android.internal.R.layout.safe_mode, null);
5880 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5881 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5882 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5883 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5884 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5885 lp.format = v.getBackground().getOpacity();
5886 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5887 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5888 ((WindowManager)mContext.getSystemService(
5889 Context.WINDOW_SERVICE)).addView(v, lp);
5890 }
5891 }
5892 }
5893
5894 public void noteWakeupAlarm(IIntentSender sender) {
5895 if (!(sender instanceof PendingIntentRecord)) {
5896 return;
5897 }
5898 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5899 synchronized (stats) {
5900 if (mBatteryStatsService.isOnBattery()) {
5901 mBatteryStatsService.enforceCallingPermission();
5902 PendingIntentRecord rec = (PendingIntentRecord)sender;
5903 int MY_UID = Binder.getCallingUid();
5904 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5905 BatteryStatsImpl.Uid.Pkg pkg =
5906 stats.getPackageStatsLocked(uid, rec.key.packageName);
5907 pkg.incWakeupsLocked();
5908 }
5909 }
5910 }
5911
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005912 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005913 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005914 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005916 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005917 // XXX Note: don't acquire main activity lock here, because the window
5918 // manager calls in with its locks held.
5919
5920 boolean killed = false;
5921 synchronized (mPidsSelfLocked) {
5922 int[] types = new int[pids.length];
5923 int worstType = 0;
5924 for (int i=0; i<pids.length; i++) {
5925 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5926 if (proc != null) {
5927 int type = proc.setAdj;
5928 types[i] = type;
5929 if (type > worstType) {
5930 worstType = type;
5931 }
5932 }
5933 }
5934
5935 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5936 // then constrain it so we will kill all hidden procs.
5937 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5938 worstType = HIDDEN_APP_MIN_ADJ;
5939 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005940 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 for (int i=0; i<pids.length; i++) {
5942 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5943 if (proc == null) {
5944 continue;
5945 }
5946 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005947 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005948 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005949 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5950 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005951 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005952 proc.killedBackground = true;
5953 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005954 }
5955 }
5956 }
5957 return killed;
5958 }
5959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 public final void startRunning(String pkg, String cls, String action,
5961 String data) {
5962 synchronized(this) {
5963 if (mStartRunning) {
5964 return;
5965 }
5966 mStartRunning = true;
5967 mTopComponent = pkg != null && cls != null
5968 ? new ComponentName(pkg, cls) : null;
5969 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5970 mTopData = data;
5971 if (!mSystemReady) {
5972 return;
5973 }
5974 }
5975
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005976 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005977 }
5978
5979 private void retrieveSettings() {
5980 final ContentResolver resolver = mContext.getContentResolver();
5981 String debugApp = Settings.System.getString(
5982 resolver, Settings.System.DEBUG_APP);
5983 boolean waitForDebugger = Settings.System.getInt(
5984 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5985 boolean alwaysFinishActivities = Settings.System.getInt(
5986 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5987
5988 Configuration configuration = new Configuration();
5989 Settings.System.getConfiguration(resolver, configuration);
5990
5991 synchronized (this) {
5992 mDebugApp = mOrigDebugApp = debugApp;
5993 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5994 mAlwaysFinishActivities = alwaysFinishActivities;
5995 // This happens before any activities are started, so we can
5996 // change mConfiguration in-place.
5997 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005998 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005999 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006000 }
6001 }
6002
6003 public boolean testIsSystemReady() {
6004 // no need to synchronize(this) just to read & return the value
6005 return mSystemReady;
6006 }
6007
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006008 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006009 // In the simulator, startRunning will never have been called, which
6010 // normally sets a few crucial variables. Do it here instead.
6011 if (!Process.supportsProcesses()) {
6012 mStartRunning = true;
6013 mTopAction = Intent.ACTION_MAIN;
6014 }
6015
6016 synchronized(this) {
6017 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006018 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006019 return;
6020 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006021
6022 // Check to see if there are any update receivers to run.
6023 if (!mDidUpdate) {
6024 if (mWaitingUpdate) {
6025 return;
6026 }
6027 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6028 List<ResolveInfo> ris = null;
6029 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006030 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006031 intent, null, 0);
6032 } catch (RemoteException e) {
6033 }
6034 if (ris != null) {
6035 for (int i=ris.size()-1; i>=0; i--) {
6036 if ((ris.get(i).activityInfo.applicationInfo.flags
6037 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6038 ris.remove(i);
6039 }
6040 }
6041 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
6042 for (int i=0; i<ris.size(); i++) {
6043 ActivityInfo ai = ris.get(i).activityInfo;
6044 intent.setComponent(new ComponentName(ai.packageName, ai.name));
6045 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006046 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006047 finisher = new IIntentReceiver.Stub() {
6048 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006049 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006050 boolean sticky) {
6051 // The raw IIntentReceiver interface is called
6052 // with the AM lock held, so redispatch to
6053 // execute our code without the lock.
6054 mHandler.post(new Runnable() {
6055 public void run() {
6056 synchronized (ActivityManagerService.this) {
6057 mDidUpdate = true;
6058 }
6059 systemReady(goingCallback);
6060 }
6061 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006062 }
6063 };
6064 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006065 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006066 broadcastIntentLocked(null, null, intent, null, finisher,
6067 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006068 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006069 mWaitingUpdate = true;
6070 }
6071 }
6072 }
6073 if (mWaitingUpdate) {
6074 return;
6075 }
6076 mDidUpdate = true;
6077 }
6078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 mSystemReady = true;
6080 if (!mStartRunning) {
6081 return;
6082 }
6083 }
6084
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006085 ArrayList<ProcessRecord> procsToKill = null;
6086 synchronized(mPidsSelfLocked) {
6087 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6088 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6089 if (!isAllowedWhileBooting(proc.info)){
6090 if (procsToKill == null) {
6091 procsToKill = new ArrayList<ProcessRecord>();
6092 }
6093 procsToKill.add(proc);
6094 }
6095 }
6096 }
6097
6098 if (procsToKill != null) {
6099 synchronized(this) {
6100 for (int i=procsToKill.size()-1; i>=0; i--) {
6101 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006102 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006103 removeProcessLocked(proc, true);
6104 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07006105
6106 // Now that we have cleaned up any update processes, we
6107 // are ready to start launching real processes and know that
6108 // we won't trample on them any more.
6109 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006110 }
6111 }
6112
Joe Onorato8a9b2202010-02-26 18:56:32 -08006113 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006114 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 SystemClock.uptimeMillis());
6116
6117 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006118 // Make sure we have no pre-ready processes sitting around.
6119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006120 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6121 ResolveInfo ri = mContext.getPackageManager()
6122 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006123 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006124 CharSequence errorMsg = null;
6125 if (ri != null) {
6126 ActivityInfo ai = ri.activityInfo;
6127 ApplicationInfo app = ai.applicationInfo;
6128 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6129 mTopAction = Intent.ACTION_FACTORY_TEST;
6130 mTopData = null;
6131 mTopComponent = new ComponentName(app.packageName,
6132 ai.name);
6133 } else {
6134 errorMsg = mContext.getResources().getText(
6135 com.android.internal.R.string.factorytest_not_system);
6136 }
6137 } else {
6138 errorMsg = mContext.getResources().getText(
6139 com.android.internal.R.string.factorytest_no_action);
6140 }
6141 if (errorMsg != null) {
6142 mTopAction = null;
6143 mTopData = null;
6144 mTopComponent = null;
6145 Message msg = Message.obtain();
6146 msg.what = SHOW_FACTORY_ERROR_MSG;
6147 msg.getData().putCharSequence("msg", errorMsg);
6148 mHandler.sendMessage(msg);
6149 }
6150 }
6151 }
6152
6153 retrieveSettings();
6154
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006155 if (goingCallback != null) goingCallback.run();
6156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006157 synchronized (this) {
6158 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6159 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006160 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006161 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006162 if (apps != null) {
6163 int N = apps.size();
6164 int i;
6165 for (i=0; i<N; i++) {
6166 ApplicationInfo info
6167 = (ApplicationInfo)apps.get(i);
6168 if (info != null &&
6169 !info.packageName.equals("android")) {
6170 addAppLocked(info);
6171 }
6172 }
6173 }
6174 } catch (RemoteException ex) {
6175 // pm is in same process, this will never happen.
6176 }
6177 }
6178
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006179 // Start up initial activity.
6180 mBooting = true;
6181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006182 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006183 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006184 Message msg = Message.obtain();
6185 msg.what = SHOW_UID_ERROR_MSG;
6186 mHandler.sendMessage(msg);
6187 }
6188 } catch (RemoteException e) {
6189 }
6190
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006191 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006192 }
6193 }
6194
Dan Egnorb7f03672009-12-09 16:22:32 -08006195 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006196 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006197 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006198 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006199 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006200 startAppProblemLocked(app);
6201 app.stopFreezingAllLocked();
6202 return handleAppCrashLocked(app);
6203 }
6204
Dan Egnorb7f03672009-12-09 16:22:32 -08006205 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006206 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006207 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006208 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006209 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6210 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006211 startAppProblemLocked(app);
6212 app.stopFreezingAllLocked();
6213 }
6214
6215 /**
6216 * Generate a process error record, suitable for attachment to a ProcessRecord.
6217 *
6218 * @param app The ProcessRecord in which the error occurred.
6219 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6220 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006221 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006222 * @param shortMsg Short message describing the crash.
6223 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006224 * @param stackTrace Full crash stack trace, may be null.
6225 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006226 * @return Returns a fully-formed AppErrorStateInfo record.
6227 */
6228 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006229 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006230 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006232 report.condition = condition;
6233 report.processName = app.processName;
6234 report.pid = app.pid;
6235 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006236 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006237 report.shortMsg = shortMsg;
6238 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006239 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006240
6241 return report;
6242 }
6243
Dan Egnor42471dd2010-01-07 17:25:22 -08006244 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006245 synchronized (this) {
6246 app.crashing = false;
6247 app.crashingReport = null;
6248 app.notResponding = false;
6249 app.notRespondingReport = null;
6250 if (app.anrDialog == fromDialog) {
6251 app.anrDialog = null;
6252 }
6253 if (app.waitDialog == fromDialog) {
6254 app.waitDialog = null;
6255 }
6256 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006257 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006258 Slog.i(ActivityManagerService.TAG, "Killing "
6259 + app.processName + " (pid=" + app.pid + "): user's request");
6260 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6261 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006262 Process.killProcess(app.pid);
6263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006264 }
6265 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006266
Dan Egnorb7f03672009-12-09 16:22:32 -08006267 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006268 long now = SystemClock.uptimeMillis();
6269
6270 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6271 app.info.uid);
6272 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6273 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006274 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006275 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006276 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006277 app.info.processName, app.info.uid);
6278 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006279 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6280 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006281 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006282 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006283 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006284 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006285 }
6286 }
6287 if (!app.persistent) {
6288 // We don't want to start this process again until the user
6289 // explicitly does so... but for persistent process, we really
6290 // need to keep it running. If a persistent process is actually
6291 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006292 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006293 app.info.processName);
6294 mBadProcesses.put(app.info.processName, app.info.uid, now);
6295 app.bad = true;
6296 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6297 app.removed = true;
6298 removeProcessLocked(app, false);
6299 return false;
6300 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006301 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006302 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006303 if (r.app == app) {
6304 // If the top running activity is from this crashing
6305 // process, then terminate it to avoid getting in a loop.
6306 Slog.w(TAG, " Force finishing activity "
6307 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006308 int index = mMainStack.indexOfTokenLocked(r);
6309 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006310 Activity.RESULT_CANCELED, null, "crashed");
6311 // Also terminate an activities below it that aren't yet
6312 // stopped, to avoid a situation where one will get
6313 // re-start our crashing activity once it gets resumed again.
6314 index--;
6315 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006316 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006317 if (r.state == ActivityState.RESUMED
6318 || r.state == ActivityState.PAUSING
6319 || r.state == ActivityState.PAUSED) {
6320 if (!r.isHomeActivity) {
6321 Slog.w(TAG, " Force finishing activity "
6322 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006323 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006324 Activity.RESULT_CANCELED, null, "crashed");
6325 }
6326 }
6327 }
6328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 }
6330
6331 // Bump up the crash count of any services currently running in the proc.
6332 if (app.services.size() != 0) {
6333 // Any services running in the application need to be placed
6334 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006335 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006336 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006337 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006338 sr.crashCount++;
6339 }
6340 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006341
6342 // If the crashing process is what we consider to be the "home process" and it has been
6343 // replaced by a third-party app, clear the package preferred activities from packages
6344 // with a home activity running in the process to prevent a repeatedly crashing app
6345 // from blocking the user to manually clear the list.
6346 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6347 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6348 Iterator it = mHomeProcess.activities.iterator();
6349 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006350 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006351 if (r.isHomeActivity) {
6352 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6353 try {
6354 ActivityThread.getPackageManager()
6355 .clearPackagePreferredActivities(r.packageName);
6356 } catch (RemoteException c) {
6357 // pm is in same process, this will never happen.
6358 }
6359 }
6360 }
6361 }
6362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6364 return true;
6365 }
6366
6367 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006368 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6369 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006370 skipCurrentReceiverLocked(app);
6371 }
6372
6373 void skipCurrentReceiverLocked(ProcessRecord app) {
6374 boolean reschedule = false;
6375 BroadcastRecord r = app.curReceiver;
6376 if (r != null) {
6377 // The current broadcast is waiting for this app's receiver
6378 // to be finished. Looks like that's not going to happen, so
6379 // let the broadcast continue.
6380 logBroadcastReceiverDiscard(r);
6381 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6382 r.resultExtras, r.resultAbort, true);
6383 reschedule = true;
6384 }
6385 r = mPendingBroadcast;
6386 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006387 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006388 "skip & discard pending app " + r);
6389 logBroadcastReceiverDiscard(r);
6390 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6391 r.resultExtras, r.resultAbort, true);
6392 reschedule = true;
6393 }
6394 if (reschedule) {
6395 scheduleBroadcastsLocked();
6396 }
6397 }
6398
Dan Egnor60d87622009-12-16 16:32:58 -08006399 /**
6400 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6401 * The application process will exit immediately after this call returns.
6402 * @param app object of the crashing app, null for the system server
6403 * @param crashInfo describing the exception
6404 */
6405 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6406 ProcessRecord r = findAppProcess(app);
6407
6408 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6409 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006410 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006411 crashInfo.exceptionClassName,
6412 crashInfo.exceptionMessage,
6413 crashInfo.throwFileName,
6414 crashInfo.throwLineNumber);
6415
Dan Egnor42471dd2010-01-07 17:25:22 -08006416 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006417
6418 crashApplication(r, crashInfo);
6419 }
6420
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006421 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006422 IBinder app,
6423 int violationMask,
6424 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006425 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006426
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006427 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006428 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006429 boolean logIt = true;
6430 synchronized (mAlreadyLoggedViolatedStacks) {
6431 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6432 logIt = false;
6433 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006434 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006435 // the relative pain numbers, without logging all
6436 // the stack traces repeatedly. We'd want to do
6437 // likewise in the client code, which also does
6438 // dup suppression, before the Binder call.
6439 } else {
6440 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6441 mAlreadyLoggedViolatedStacks.clear();
6442 }
6443 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6444 }
6445 }
6446 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006447 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006448 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006449 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006450
6451 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6452 AppErrorResult result = new AppErrorResult();
6453 synchronized (this) {
6454 final long origId = Binder.clearCallingIdentity();
6455
6456 Message msg = Message.obtain();
6457 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6458 HashMap<String, Object> data = new HashMap<String, Object>();
6459 data.put("result", result);
6460 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006461 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006462 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006463 msg.obj = data;
6464 mHandler.sendMessage(msg);
6465
6466 Binder.restoreCallingIdentity(origId);
6467 }
6468 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006469 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006470 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006471 }
6472
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006473 // Depending on the policy in effect, there could be a bunch of
6474 // these in quick succession so we try to batch these together to
6475 // minimize disk writes, number of dropbox entries, and maximize
6476 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006477 private void logStrictModeViolationToDropBox(
6478 ProcessRecord process,
6479 StrictMode.ViolationInfo info) {
6480 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006481 return;
6482 }
6483 final boolean isSystemApp = process == null ||
6484 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6485 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6486 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6487 final DropBoxManager dbox = (DropBoxManager)
6488 mContext.getSystemService(Context.DROPBOX_SERVICE);
6489
6490 // Exit early if the dropbox isn't configured to accept this report type.
6491 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6492
6493 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006494 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006495 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6496 synchronized (sb) {
6497 bufferWasEmpty = sb.length() == 0;
6498 appendDropBoxProcessHeaders(process, sb);
6499 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6500 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006501 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6502 if (info.violationNumThisLoop != 0) {
6503 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6504 }
6505 if (info != null && info.durationMillis != -1) {
6506 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006507 }
6508 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006509 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6510 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006511 }
6512 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006513
6514 // Only buffer up to ~64k. Various logging bits truncate
6515 // things at 128k.
6516 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006517 }
6518
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006519 // Flush immediately if the buffer's grown too large, or this
6520 // is a non-system app. Non-system apps are isolated with a
6521 // different tag & policy and not batched.
6522 //
6523 // Batching is useful during internal testing with
6524 // StrictMode settings turned up high. Without batching,
6525 // thousands of separate files could be created on boot.
6526 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006527 new Thread("Error dump: " + dropboxTag) {
6528 @Override
6529 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006530 String report;
6531 synchronized (sb) {
6532 report = sb.toString();
6533 sb.delete(0, sb.length());
6534 sb.trimToSize();
6535 }
6536 if (report.length() != 0) {
6537 dbox.addText(dropboxTag, report);
6538 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006539 }
6540 }.start();
6541 return;
6542 }
6543
6544 // System app batching:
6545 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006546 // An existing dropbox-writing thread is outstanding, so
6547 // we don't need to start it up. The existing thread will
6548 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006549 return;
6550 }
6551
6552 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6553 // (After this point, we shouldn't access AMS internal data structures.)
6554 new Thread("Error dump: " + dropboxTag) {
6555 @Override
6556 public void run() {
6557 // 5 second sleep to let stacks arrive and be batched together
6558 try {
6559 Thread.sleep(5000); // 5 seconds
6560 } catch (InterruptedException e) {}
6561
6562 String errorReport;
6563 synchronized (mStrictModeBuffer) {
6564 errorReport = mStrictModeBuffer.toString();
6565 if (errorReport.length() == 0) {
6566 return;
6567 }
6568 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6569 mStrictModeBuffer.trimToSize();
6570 }
6571 dbox.addText(dropboxTag, errorReport);
6572 }
6573 }.start();
6574 }
6575
Dan Egnor60d87622009-12-16 16:32:58 -08006576 /**
6577 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6578 * @param app object of the crashing app, null for the system server
6579 * @param tag reported by the caller
6580 * @param crashInfo describing the context of the error
6581 * @return true if the process should exit immediately (WTF is fatal)
6582 */
6583 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006584 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006585 ProcessRecord r = findAppProcess(app);
6586
6587 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6588 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006589 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006590 tag, crashInfo.exceptionMessage);
6591
Dan Egnor42471dd2010-01-07 17:25:22 -08006592 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006593
Doug Zongker43866e02010-01-07 12:09:54 -08006594 if (Settings.Secure.getInt(mContext.getContentResolver(),
6595 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006596 crashApplication(r, crashInfo);
6597 return true;
6598 } else {
6599 return false;
6600 }
6601 }
6602
6603 /**
6604 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6605 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6606 */
6607 private ProcessRecord findAppProcess(IBinder app) {
6608 if (app == null) {
6609 return null;
6610 }
6611
6612 synchronized (this) {
6613 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6614 final int NA = apps.size();
6615 for (int ia=0; ia<NA; ia++) {
6616 ProcessRecord p = apps.valueAt(ia);
6617 if (p.thread != null && p.thread.asBinder() == app) {
6618 return p;
6619 }
6620 }
6621 }
6622
Joe Onorato8a9b2202010-02-26 18:56:32 -08006623 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006624 return null;
6625 }
6626 }
6627
6628 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006629 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6630 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006631 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006632 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6633 // Note: ProcessRecord 'process' is guarded by the service
6634 // instance. (notably process.pkgList, which could otherwise change
6635 // concurrently during execution of this method)
6636 synchronized (this) {
6637 if (process == null || process.pid == MY_PID) {
6638 sb.append("Process: system_server\n");
6639 } else {
6640 sb.append("Process: ").append(process.processName).append("\n");
6641 }
6642 if (process == null) {
6643 return;
6644 }
Dan Egnora455d192010-03-12 08:52:28 -08006645 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006646 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006647 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6648 for (String pkg : process.pkgList) {
6649 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006650 try {
Dan Egnora455d192010-03-12 08:52:28 -08006651 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6652 if (pi != null) {
6653 sb.append(" v").append(pi.versionCode);
6654 if (pi.versionName != null) {
6655 sb.append(" (").append(pi.versionName).append(")");
6656 }
6657 }
6658 } catch (RemoteException e) {
6659 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006660 }
Dan Egnora455d192010-03-12 08:52:28 -08006661 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006662 }
Dan Egnora455d192010-03-12 08:52:28 -08006663 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006664 }
6665
6666 private static String processClass(ProcessRecord process) {
6667 if (process == null || process.pid == MY_PID) {
6668 return "system_server";
6669 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6670 return "system_app";
6671 } else {
6672 return "data_app";
6673 }
6674 }
6675
6676 /**
6677 * Write a description of an error (crash, WTF, ANR) to the drop box.
6678 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6679 * @param process which caused the error, null means the system server
6680 * @param activity which triggered the error, null if unknown
6681 * @param parent activity related to the error, null if unknown
6682 * @param subject line related to the error, null if absent
6683 * @param report in long form describing the error, null if absent
6684 * @param logFile to include in the report, null if none
6685 * @param crashInfo giving an application stack trace, null if absent
6686 */
6687 public void addErrorToDropBox(String eventType,
6688 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6689 final String report, final File logFile,
6690 final ApplicationErrorReport.CrashInfo crashInfo) {
6691 // NOTE -- this must never acquire the ActivityManagerService lock,
6692 // otherwise the watchdog may be prevented from resetting the system.
6693
6694 final String dropboxTag = processClass(process) + "_" + eventType;
6695 final DropBoxManager dbox = (DropBoxManager)
6696 mContext.getSystemService(Context.DROPBOX_SERVICE);
6697
6698 // Exit early if the dropbox isn't configured to accept this report type.
6699 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6700
6701 final StringBuilder sb = new StringBuilder(1024);
6702 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006703 if (activity != null) {
6704 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6705 }
6706 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6707 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6708 }
6709 if (parent != null && parent != activity) {
6710 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6711 }
6712 if (subject != null) {
6713 sb.append("Subject: ").append(subject).append("\n");
6714 }
6715 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6716 sb.append("\n");
6717
6718 // Do the rest in a worker thread to avoid blocking the caller on I/O
6719 // (After this point, we shouldn't access AMS internal data structures.)
6720 Thread worker = new Thread("Error dump: " + dropboxTag) {
6721 @Override
6722 public void run() {
6723 if (report != null) {
6724 sb.append(report);
6725 }
6726 if (logFile != null) {
6727 try {
6728 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6729 } catch (IOException e) {
6730 Slog.e(TAG, "Error reading " + logFile, e);
6731 }
6732 }
6733 if (crashInfo != null && crashInfo.stackTrace != null) {
6734 sb.append(crashInfo.stackTrace);
6735 }
6736
6737 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6738 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6739 if (lines > 0) {
6740 sb.append("\n");
6741
6742 // Merge several logcat streams, and take the last N lines
6743 InputStreamReader input = null;
6744 try {
6745 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6746 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6747 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6748
6749 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6750 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6751 input = new InputStreamReader(logcat.getInputStream());
6752
6753 int num;
6754 char[] buf = new char[8192];
6755 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6756 } catch (IOException e) {
6757 Slog.e(TAG, "Error running logcat", e);
6758 } finally {
6759 if (input != null) try { input.close(); } catch (IOException e) {}
6760 }
6761 }
6762
6763 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006764 }
Dan Egnora455d192010-03-12 08:52:28 -08006765 };
6766
6767 if (process == null || process.pid == MY_PID) {
6768 worker.run(); // We may be about to die -- need to run this synchronously
6769 } else {
6770 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006771 }
6772 }
6773
6774 /**
6775 * Bring up the "unexpected error" dialog box for a crashing app.
6776 * Deal with edge cases (intercepts from instrumented applications,
6777 * ActivityController, error intent receivers, that sort of thing).
6778 * @param r the application crashing
6779 * @param crashInfo describing the failure
6780 */
6781 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006782 long timeMillis = System.currentTimeMillis();
6783 String shortMsg = crashInfo.exceptionClassName;
6784 String longMsg = crashInfo.exceptionMessage;
6785 String stackTrace = crashInfo.stackTrace;
6786 if (shortMsg != null && longMsg != null) {
6787 longMsg = shortMsg + ": " + longMsg;
6788 } else if (shortMsg != null) {
6789 longMsg = shortMsg;
6790 }
6791
Dan Egnor60d87622009-12-16 16:32:58 -08006792 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006793 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006794 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006795 try {
6796 String name = r != null ? r.processName : null;
6797 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006798 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006799 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006800 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006801 + " at watcher's request");
6802 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006803 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006804 }
6805 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006806 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006807 }
6808 }
6809
6810 final long origId = Binder.clearCallingIdentity();
6811
6812 // If this process is running instrumentation, finish it.
6813 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006814 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006815 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006816 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6817 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006818 Bundle info = new Bundle();
6819 info.putString("shortMsg", shortMsg);
6820 info.putString("longMsg", longMsg);
6821 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6822 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006823 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006824 }
6825
Dan Egnor60d87622009-12-16 16:32:58 -08006826 // If we can't identify the process or it's already exceeded its crash quota,
6827 // quit right away without showing a crash dialog.
6828 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006829 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006830 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006831 }
6832
6833 Message msg = Message.obtain();
6834 msg.what = SHOW_ERROR_MSG;
6835 HashMap data = new HashMap();
6836 data.put("result", result);
6837 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006838 msg.obj = data;
6839 mHandler.sendMessage(msg);
6840
6841 Binder.restoreCallingIdentity(origId);
6842 }
6843
6844 int res = result.get();
6845
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006846 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006847 synchronized (this) {
6848 if (r != null) {
6849 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6850 SystemClock.uptimeMillis());
6851 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006852 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006853 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006854 }
6855 }
6856
6857 if (appErrorIntent != null) {
6858 try {
6859 mContext.startActivity(appErrorIntent);
6860 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006861 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006862 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006863 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006864 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006865
6866 Intent createAppErrorIntentLocked(ProcessRecord r,
6867 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6868 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006869 if (report == null) {
6870 return null;
6871 }
6872 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6873 result.setComponent(r.errorReportReceiver);
6874 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6875 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6876 return result;
6877 }
6878
Dan Egnorb7f03672009-12-09 16:22:32 -08006879 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6880 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006881 if (r.errorReportReceiver == null) {
6882 return null;
6883 }
6884
6885 if (!r.crashing && !r.notResponding) {
6886 return null;
6887 }
6888
Dan Egnorb7f03672009-12-09 16:22:32 -08006889 ApplicationErrorReport report = new ApplicationErrorReport();
6890 report.packageName = r.info.packageName;
6891 report.installerPackageName = r.errorReportReceiver.getPackageName();
6892 report.processName = r.processName;
6893 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006894 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006895
Dan Egnorb7f03672009-12-09 16:22:32 -08006896 if (r.crashing) {
6897 report.type = ApplicationErrorReport.TYPE_CRASH;
6898 report.crashInfo = crashInfo;
6899 } else if (r.notResponding) {
6900 report.type = ApplicationErrorReport.TYPE_ANR;
6901 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006902
Dan Egnorb7f03672009-12-09 16:22:32 -08006903 report.anrInfo.activity = r.notRespondingReport.tag;
6904 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6905 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006906 }
6907
Dan Egnorb7f03672009-12-09 16:22:32 -08006908 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006909 }
6910
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006911 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6912 // assume our apps are happy - lazy create the list
6913 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6914
6915 synchronized (this) {
6916
6917 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006918 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6919 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006920 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6921 // This one's in trouble, so we'll generate a report for it
6922 // crashes are higher priority (in case there's a crash *and* an anr)
6923 ActivityManager.ProcessErrorStateInfo report = null;
6924 if (app.crashing) {
6925 report = app.crashingReport;
6926 } else if (app.notResponding) {
6927 report = app.notRespondingReport;
6928 }
6929
6930 if (report != null) {
6931 if (errList == null) {
6932 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6933 }
6934 errList.add(report);
6935 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006936 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 " crashing = " + app.crashing +
6938 " notResponding = " + app.notResponding);
6939 }
6940 }
6941 }
6942 }
6943
6944 return errList;
6945 }
6946
6947 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6948 // Lazy instantiation of list
6949 List<ActivityManager.RunningAppProcessInfo> runList = null;
6950 synchronized (this) {
6951 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006952 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6953 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006954 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6955 // Generate process state info for running application
6956 ActivityManager.RunningAppProcessInfo currApp =
6957 new ActivityManager.RunningAppProcessInfo(app.processName,
6958 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006959 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006960 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07006961 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006963 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006964 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006965 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6966 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6967 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006968 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6969 } else if (adj >= HOME_APP_ADJ) {
6970 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6971 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006972 } else if (adj >= SECONDARY_SERVER_ADJ) {
6973 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006974 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6975 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6976 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6977 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006978 } else if (adj >= VISIBLE_APP_ADJ) {
6979 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6980 } else {
6981 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6982 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006983 currApp.importanceReasonCode = app.adjTypeCode;
6984 if (app.adjSource instanceof ProcessRecord) {
6985 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006986 } else if (app.adjSource instanceof ActivityRecord) {
6987 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006988 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6989 }
6990 if (app.adjTarget instanceof ComponentName) {
6991 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6992 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006993 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006994 // + " lru=" + currApp.lru);
6995 if (runList == null) {
6996 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6997 }
6998 runList.add(currApp);
6999 }
7000 }
7001 }
7002 return runList;
7003 }
7004
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007005 public List<ApplicationInfo> getRunningExternalApplications() {
7006 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7007 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7008 if (runningApps != null && runningApps.size() > 0) {
7009 Set<String> extList = new HashSet<String>();
7010 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7011 if (app.pkgList != null) {
7012 for (String pkg : app.pkgList) {
7013 extList.add(pkg);
7014 }
7015 }
7016 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007017 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007018 for (String pkg : extList) {
7019 try {
7020 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7021 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7022 retList.add(info);
7023 }
7024 } catch (RemoteException e) {
7025 }
7026 }
7027 }
7028 return retList;
7029 }
7030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007031 @Override
7032 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007033 if (checkCallingPermission(android.Manifest.permission.DUMP)
7034 != PackageManager.PERMISSION_GRANTED) {
7035 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7036 + Binder.getCallingPid()
7037 + ", uid=" + Binder.getCallingUid()
7038 + " without permission "
7039 + android.Manifest.permission.DUMP);
7040 return;
7041 }
7042
7043 boolean dumpAll = false;
7044
7045 int opti = 0;
7046 while (opti < args.length) {
7047 String opt = args[opti];
7048 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7049 break;
7050 }
7051 opti++;
7052 if ("-a".equals(opt)) {
7053 dumpAll = true;
7054 } else if ("-h".equals(opt)) {
7055 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007056 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007057 pw.println(" cmd may be one of:");
7058 pw.println(" activities: activity stack state");
7059 pw.println(" broadcasts: broadcast state");
7060 pw.println(" intents: pending intent state");
7061 pw.println(" processes: process state");
7062 pw.println(" providers: content provider state");
7063 pw.println(" services: service state");
7064 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007065 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007066 } else {
7067 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007068 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007069 }
7070
7071 // Is the caller requesting to dump a particular piece of data?
7072 if (opti < args.length) {
7073 String cmd = args[opti];
7074 opti++;
7075 if ("activities".equals(cmd) || "a".equals(cmd)) {
7076 synchronized (this) {
7077 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007078 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007079 return;
7080 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7081 synchronized (this) {
7082 dumpBroadcastsLocked(fd, pw, args, opti, true);
7083 }
7084 return;
7085 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7086 synchronized (this) {
7087 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7088 }
7089 return;
7090 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7091 synchronized (this) {
7092 dumpProcessesLocked(fd, pw, args, opti, true);
7093 }
7094 return;
7095 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7096 synchronized (this) {
7097 dumpProvidersLocked(fd, pw, args, opti, true);
7098 }
7099 return;
7100 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007101 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007102 return;
7103 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7104 synchronized (this) {
7105 dumpServicesLocked(fd, pw, args, opti, true);
7106 }
7107 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007108 } else {
7109 // Dumping a single activity?
7110 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7111 return;
7112 }
7113 pw.println("Bad activity command: " + cmd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007114 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007115 }
7116
7117 // No piece of data specified, dump everything.
7118 synchronized (this) {
7119 boolean needSep;
7120 if (dumpAll) {
7121 pw.println("Providers in Current Activity Manager State:");
7122 }
7123 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7124 if (needSep) {
7125 pw.println(" ");
7126 }
7127 if (dumpAll) {
7128 pw.println("-------------------------------------------------------------------------------");
7129 pw.println("Broadcasts in Current Activity Manager State:");
7130 }
7131 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7132 if (needSep) {
7133 pw.println(" ");
7134 }
7135 if (dumpAll) {
7136 pw.println("-------------------------------------------------------------------------------");
7137 pw.println("Services in Current Activity Manager State:");
7138 }
7139 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7140 if (needSep) {
7141 pw.println(" ");
7142 }
7143 if (dumpAll) {
7144 pw.println("-------------------------------------------------------------------------------");
7145 pw.println("PendingIntents in Current Activity Manager State:");
7146 }
7147 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7148 if (needSep) {
7149 pw.println(" ");
7150 }
7151 if (dumpAll) {
7152 pw.println("-------------------------------------------------------------------------------");
7153 pw.println("Activities in Current Activity Manager State:");
7154 }
7155 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7156 if (needSep) {
7157 pw.println(" ");
7158 }
7159 if (dumpAll) {
7160 pw.println("-------------------------------------------------------------------------------");
7161 pw.println("Processes in Current Activity Manager State:");
7162 }
7163 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7164 }
7165 }
7166
7167 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7168 int opti, boolean dumpAll, boolean needHeader) {
7169 if (needHeader) {
7170 pw.println(" Activity stack:");
7171 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007172 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007173 pw.println(" ");
7174 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007175 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7176 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007177 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007178 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007179 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007180 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007181 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007182 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007183 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007184 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007185 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007186 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007187 pw.println(" ");
7188 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007189 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007191
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007192 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007193 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7194 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007195 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007196 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007197
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007198 if (dumpAll && mRecentTasks.size() > 0) {
7199 pw.println(" ");
7200 pw.println("Recent tasks in Current Activity Manager State:");
7201
7202 final int N = mRecentTasks.size();
7203 for (int i=0; i<N; i++) {
7204 TaskRecord tr = mRecentTasks.get(i);
7205 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7206 pw.println(tr);
7207 mRecentTasks.get(i).dump(pw, " ");
7208 }
7209 }
7210
7211 pw.println(" ");
7212 pw.println(" mCurTask: " + mCurTask);
7213
7214 return true;
7215 }
7216
7217 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7218 int opti, boolean dumpAll) {
7219 boolean needSep = false;
7220 int numPers = 0;
7221
7222 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007223 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7224 final int NA = procs.size();
7225 for (int ia=0; ia<NA; ia++) {
7226 if (!needSep) {
7227 pw.println(" All known processes:");
7228 needSep = true;
7229 }
7230 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007231 pw.print(r.persistent ? " *PERS*" : " *APP*");
7232 pw.print(" UID "); pw.print(procs.keyAt(ia));
7233 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007234 r.dump(pw, " ");
7235 if (r.persistent) {
7236 numPers++;
7237 }
7238 }
7239 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007240 }
7241
7242 if (mLruProcesses.size() > 0) {
7243 if (needSep) pw.println(" ");
7244 needSep = true;
7245 pw.println(" Running processes (most recent first):");
7246 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007247 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007248 needSep = true;
7249 }
7250
7251 synchronized (mPidsSelfLocked) {
7252 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007253 if (needSep) pw.println(" ");
7254 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007255 pw.println(" PID mappings:");
7256 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7257 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7258 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007259 }
7260 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007261 }
7262
7263 if (mForegroundProcesses.size() > 0) {
7264 if (needSep) pw.println(" ");
7265 needSep = true;
7266 pw.println(" Foreground Processes:");
7267 for (int i=0; i<mForegroundProcesses.size(); i++) {
7268 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7269 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007270 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007271 }
7272
7273 if (mPersistentStartingProcesses.size() > 0) {
7274 if (needSep) pw.println(" ");
7275 needSep = true;
7276 pw.println(" Persisent processes that are starting:");
7277 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
7278 "Starting Norm", "Restarting PERS", false);
7279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007280
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007281 if (mStartingProcesses.size() > 0) {
7282 if (needSep) pw.println(" ");
7283 needSep = true;
7284 pw.println(" Processes that are starting:");
7285 dumpProcessList(pw, this, mStartingProcesses, " ",
7286 "Starting Norm", "Starting PERS", false);
7287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007288
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007289 if (mRemovedProcesses.size() > 0) {
7290 if (needSep) pw.println(" ");
7291 needSep = true;
7292 pw.println(" Processes that are being removed:");
7293 dumpProcessList(pw, this, mRemovedProcesses, " ",
7294 "Removed Norm", "Removed PERS", false);
7295 }
7296
7297 if (mProcessesOnHold.size() > 0) {
7298 if (needSep) pw.println(" ");
7299 needSep = true;
7300 pw.println(" Processes that are on old until the system is ready:");
7301 dumpProcessList(pw, this, mProcessesOnHold, " ",
7302 "OnHold Norm", "OnHold PERS", false);
7303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007304
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007305 if (mProcessesToGc.size() > 0) {
7306 if (needSep) pw.println(" ");
7307 needSep = true;
7308 pw.println(" Processes that are waiting to GC:");
7309 long now = SystemClock.uptimeMillis();
7310 for (int i=0; i<mProcessesToGc.size(); i++) {
7311 ProcessRecord proc = mProcessesToGc.get(i);
7312 pw.print(" Process "); pw.println(proc);
7313 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7314 pw.print(", last gced=");
7315 pw.print(now-proc.lastRequestedGc);
7316 pw.print(" ms ago, last lowMem=");
7317 pw.print(now-proc.lastLowMemory);
7318 pw.println(" ms ago");
7319
7320 }
7321 }
7322
7323 if (mProcessCrashTimes.getMap().size() > 0) {
7324 if (needSep) pw.println(" ");
7325 needSep = true;
7326 pw.println(" Time since processes crashed:");
7327 long now = SystemClock.uptimeMillis();
7328 for (Map.Entry<String, SparseArray<Long>> procs
7329 : mProcessCrashTimes.getMap().entrySet()) {
7330 SparseArray<Long> uids = procs.getValue();
7331 final int N = uids.size();
7332 for (int i=0; i<N; i++) {
7333 pw.print(" Process "); pw.print(procs.getKey());
7334 pw.print(" uid "); pw.print(uids.keyAt(i));
7335 pw.print(": last crashed ");
7336 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007337 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007338 }
7339 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007342 if (mBadProcesses.getMap().size() > 0) {
7343 if (needSep) pw.println(" ");
7344 needSep = true;
7345 pw.println(" Bad processes:");
7346 for (Map.Entry<String, SparseArray<Long>> procs
7347 : mBadProcesses.getMap().entrySet()) {
7348 SparseArray<Long> uids = procs.getValue();
7349 final int N = uids.size();
7350 for (int i=0; i<N; i++) {
7351 pw.print(" Bad process "); pw.print(procs.getKey());
7352 pw.print(" uid "); pw.print(uids.keyAt(i));
7353 pw.print(": crashed at time ");
7354 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007355 }
7356 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007358
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007359 pw.println(" ");
7360 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007361 if (mHeavyWeightProcess != null) {
7362 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7363 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007364 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007365 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007366 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7367 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7368 || mOrigWaitForDebugger) {
7369 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7370 + " mDebugTransient=" + mDebugTransient
7371 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7372 }
7373 if (mAlwaysFinishActivities || mController != null) {
7374 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7375 + " mController=" + mController);
7376 }
7377 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007379 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007380 + " mProcessesReady=" + mProcessesReady
7381 + " mSystemReady=" + mSystemReady);
7382 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007383 + " mBooted=" + mBooted
7384 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007385 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7386 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007387 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007388 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007389
7390 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 }
7392
7393 /**
7394 * There are three ways to call this:
7395 * - no service specified: dump all the services
7396 * - a flattened component name that matched an existing service was specified as the
7397 * first arg: dump that one service
7398 * - the first arg isn't the flattened component name of an existing service:
7399 * dump all services whose component contains the first arg as a substring
7400 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007401 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7402 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007403 String[] newArgs;
7404 String componentNameString;
7405 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007406 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007407 componentNameString = null;
7408 newArgs = EMPTY_STRING_ARRAY;
7409 r = null;
7410 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007411 componentNameString = args[opti];
7412 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007413 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007414 synchronized (this) {
7415 r = componentName != null ? mServices.get(componentName) : null;
7416 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007417 newArgs = new String[args.length - opti];
7418 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419 }
7420
7421 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007422 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007424 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7425 synchronized (this) {
7426 for (ServiceRecord r1 : mServices.values()) {
7427 if (componentNameString == null
7428 || r1.name.flattenToString().contains(componentNameString)) {
7429 services.add(r1);
7430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007431 }
7432 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007433 for (int i=0; i<services.size(); i++) {
7434 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436 }
7437 }
7438
7439 /**
7440 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7441 * there is a thread associated with the service.
7442 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007443 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7444 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007445 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007446 if (dumpAll) {
7447 synchronized (this) {
7448 pw.print(" * "); pw.println(r);
7449 r.dump(pw, " ");
7450 }
7451 pw.println("");
7452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007453 if (r.app != null && r.app.thread != null) {
7454 try {
7455 // flush anything that is already in the PrintWriter since the thread is going
7456 // to write to the file descriptor directly
7457 pw.flush();
7458 r.app.thread.dumpService(fd, r, args);
7459 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007460 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 } catch (RemoteException e) {
7462 pw.println("got a RemoteException while dumping the service");
7463 }
7464 }
7465 }
7466
Dianne Hackborn625ac272010-09-17 18:29:22 -07007467 /**
7468 * There are three things that cmd can be:
7469 * - a flattened component name that matched an existing activity
7470 * - the cmd arg isn't the flattened component name of an existing activity:
7471 * dump all activity whose component contains the cmd as a substring
7472 * - A hex number of the ActivityRecord object instance.
7473 */
7474 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7475 int opti, boolean dumpAll) {
7476 String[] newArgs;
7477 ComponentName componentName = ComponentName.unflattenFromString(name);
7478 int objectId = 0;
7479 try {
7480 objectId = Integer.parseInt(name, 16);
7481 name = null;
7482 componentName = null;
7483 } catch (RuntimeException e) {
7484 }
7485 newArgs = new String[args.length - opti];
7486 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7487
7488 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7489 synchronized (this) {
7490 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7491 if (componentName != null) {
7492 if (r1.intent.getComponent().equals(componentName)) {
7493 activities.add(r1);
7494 }
7495 } else if (name != null) {
7496 if (r1.intent.getComponent().flattenToString().contains(name)) {
7497 activities.add(r1);
7498 }
7499 } else if (System.identityHashCode(this) == objectId) {
7500 activities.add(r1);
7501 }
7502 }
7503 }
7504
7505 if (activities.size() <= 0) {
7506 return false;
7507 }
7508
7509 for (int i=0; i<activities.size(); i++) {
7510 dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
7511 }
7512 return true;
7513 }
7514
7515 /**
7516 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7517 * there is a thread associated with the activity.
7518 */
7519 private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
7520 boolean dumpAll) {
7521 pw.println(" Activity " + r.intent.getComponent().flattenToString());
7522 if (dumpAll) {
7523 synchronized (this) {
7524 pw.print(" * "); pw.println(r);
7525 r.dump(pw, " ");
7526 }
7527 pw.println("");
7528 }
7529 if (r.app != null && r.app.thread != null) {
7530 try {
7531 // flush anything that is already in the PrintWriter since the thread is going
7532 // to write to the file descriptor directly
7533 pw.flush();
7534 r.app.thread.dumpActivity(fd, r, args);
7535 pw.print("\n");
7536 pw.flush();
7537 } catch (RemoteException e) {
7538 pw.println("got a RemoteException while dumping the activity");
7539 }
7540 }
7541 }
7542
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007543 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7544 int opti, boolean dumpAll) {
7545 boolean needSep = false;
7546
7547 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007548 if (mRegisteredReceivers.size() > 0) {
7549 pw.println(" ");
7550 pw.println(" Registered Receivers:");
7551 Iterator it = mRegisteredReceivers.values().iterator();
7552 while (it.hasNext()) {
7553 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007554 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007555 r.dump(pw, " ");
7556 }
7557 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559 pw.println(" ");
7560 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007561 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007562 needSep = true;
7563 }
7564
7565 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7566 || mPendingBroadcast != null) {
7567 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007568 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007569 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007571 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7572 pw.println(" Broadcast #" + i + ":");
7573 mParallelBroadcasts.get(i).dump(pw, " ");
7574 }
7575 if (mOrderedBroadcasts.size() > 0) {
7576 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007577 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007578 }
7579 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7580 pw.println(" Serialized Broadcast #" + i + ":");
7581 mOrderedBroadcasts.get(i).dump(pw, " ");
7582 }
7583 pw.println(" ");
7584 pw.println(" Pending broadcast:");
7585 if (mPendingBroadcast != null) {
7586 mPendingBroadcast.dump(pw, " ");
7587 } else {
7588 pw.println(" (null)");
7589 }
7590 needSep = true;
7591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007592
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007593 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007594 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007595 pw.println(" Historical broadcasts:");
7596 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7597 BroadcastRecord r = mBroadcastHistory[i];
7598 if (r == null) {
7599 break;
7600 }
7601 pw.println(" Historical Broadcast #" + i + ":");
7602 r.dump(pw, " ");
7603 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007604 needSep = true;
7605 }
7606
7607 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007608 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007609 pw.println(" Sticky broadcasts:");
7610 StringBuilder sb = new StringBuilder(128);
7611 for (Map.Entry<String, ArrayList<Intent>> ent
7612 : mStickyBroadcasts.entrySet()) {
7613 pw.print(" * Sticky action "); pw.print(ent.getKey());
7614 pw.println(":");
7615 ArrayList<Intent> intents = ent.getValue();
7616 final int N = intents.size();
7617 for (int i=0; i<N; i++) {
7618 sb.setLength(0);
7619 sb.append(" Intent: ");
7620 intents.get(i).toShortString(sb, true, false);
7621 pw.println(sb.toString());
7622 Bundle bundle = intents.get(i).getExtras();
7623 if (bundle != null) {
7624 pw.print(" ");
7625 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007626 }
7627 }
7628 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007629 needSep = true;
7630 }
7631
7632 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007633 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007634 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007635 pw.println(" mHandler:");
7636 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007637 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007638 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007639
7640 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007641 }
7642
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007643 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7644 int opti, boolean dumpAll) {
7645 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007646
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007647 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007648 if (mServices.size() > 0) {
7649 pw.println(" Active services:");
7650 Iterator<ServiceRecord> it = mServices.values().iterator();
7651 while (it.hasNext()) {
7652 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007653 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007654 r.dump(pw, " ");
7655 }
7656 needSep = true;
7657 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007659
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007660 if (mPendingServices.size() > 0) {
7661 if (needSep) pw.println(" ");
7662 pw.println(" Pending services:");
7663 for (int i=0; i<mPendingServices.size(); i++) {
7664 ServiceRecord r = mPendingServices.get(i);
7665 pw.print(" * Pending "); pw.println(r);
7666 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007667 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007668 needSep = true;
7669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007670
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007671 if (mRestartingServices.size() > 0) {
7672 if (needSep) pw.println(" ");
7673 pw.println(" Restarting services:");
7674 for (int i=0; i<mRestartingServices.size(); i++) {
7675 ServiceRecord r = mRestartingServices.get(i);
7676 pw.print(" * Restarting "); pw.println(r);
7677 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007678 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007679 needSep = true;
7680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007681
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007682 if (mStoppingServices.size() > 0) {
7683 if (needSep) pw.println(" ");
7684 pw.println(" Stopping services:");
7685 for (int i=0; i<mStoppingServices.size(); i++) {
7686 ServiceRecord r = mStoppingServices.get(i);
7687 pw.print(" * Stopping "); pw.println(r);
7688 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007689 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007690 needSep = true;
7691 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007692
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007693 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007694 if (mServiceConnections.size() > 0) {
7695 if (needSep) pw.println(" ");
7696 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007697 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 = mServiceConnections.values().iterator();
7699 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007700 ArrayList<ConnectionRecord> r = it.next();
7701 for (int i=0; i<r.size(); i++) {
7702 pw.print(" * "); pw.println(r.get(i));
7703 r.get(i).dump(pw, " ");
7704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007705 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007706 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007707 }
7708 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007709
7710 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007711 }
7712
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007713 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7714 int opti, boolean dumpAll) {
7715 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007716
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007717 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718 if (mProvidersByClass.size() > 0) {
7719 if (needSep) pw.println(" ");
7720 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007721 Iterator<Map.Entry<String, ContentProviderRecord>> it
7722 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007723 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007724 Map.Entry<String, ContentProviderRecord> e = it.next();
7725 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007726 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007727 r.dump(pw, " ");
7728 }
7729 needSep = true;
7730 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007731
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007732 if (mProvidersByName.size() > 0) {
7733 pw.println(" ");
7734 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007735 Iterator<Map.Entry<String, ContentProviderRecord>> it
7736 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007737 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007738 Map.Entry<String, ContentProviderRecord> e = it.next();
7739 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007740 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7741 pw.println(r);
7742 }
7743 needSep = true;
7744 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007745 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007746
7747 if (mLaunchingProviders.size() > 0) {
7748 if (needSep) pw.println(" ");
7749 pw.println(" Launching content providers:");
7750 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7751 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7752 pw.println(mLaunchingProviders.get(i));
7753 }
7754 needSep = true;
7755 }
7756
7757 if (mGrantedUriPermissions.size() > 0) {
7758 pw.println();
7759 pw.println("Granted Uri Permissions:");
7760 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7761 int uid = mGrantedUriPermissions.keyAt(i);
7762 HashMap<Uri, UriPermission> perms
7763 = mGrantedUriPermissions.valueAt(i);
7764 pw.print(" * UID "); pw.print(uid);
7765 pw.println(" holds:");
7766 for (UriPermission perm : perms.values()) {
7767 pw.print(" "); pw.println(perm);
7768 perm.dump(pw, " ");
7769 }
7770 }
7771 needSep = true;
7772 }
7773
7774 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007775 }
7776
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007777 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7778 int opti, boolean dumpAll) {
7779 boolean needSep = false;
7780
7781 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 if (this.mIntentSenderRecords.size() > 0) {
7783 Iterator<WeakReference<PendingIntentRecord>> it
7784 = mIntentSenderRecords.values().iterator();
7785 while (it.hasNext()) {
7786 WeakReference<PendingIntentRecord> ref = it.next();
7787 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007788 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007789 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007790 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007791 rec.dump(pw, " ");
7792 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007793 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 }
7795 }
7796 }
7797 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007798
7799 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 }
7801
7802 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007803 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007804 TaskRecord lastTask = null;
7805 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007806 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007807 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007808 if (lastTask != r.task) {
7809 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007810 pw.print(prefix);
7811 pw.print(full ? "* " : " ");
7812 pw.println(lastTask);
7813 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007814 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007816 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007817 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7818 pw.print(" #"); pw.print(i); pw.print(": ");
7819 pw.println(r);
7820 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007821 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823 }
7824 }
7825
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007826 private static String buildOomTag(String prefix, String space, int val, int base) {
7827 if (val == base) {
7828 if (space == null) return prefix;
7829 return prefix + " ";
7830 }
7831 return prefix + "+" + Integer.toString(val-base);
7832 }
7833
7834 private static final int dumpProcessList(PrintWriter pw,
7835 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007836 String prefix, String normalLabel, String persistentLabel,
7837 boolean inclOomAdj) {
7838 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007839 final int N = list.size()-1;
7840 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007841 ProcessRecord r = (ProcessRecord)list.get(i);
7842 if (false) {
7843 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7844 + " #" + i + ":");
7845 r.dump(pw, prefix + " ");
7846 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007847 String oomAdj;
7848 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007849 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007850 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007851 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7852 } else if (r.setAdj >= HOME_APP_ADJ) {
7853 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7854 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7855 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7856 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7857 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007858 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7859 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7860 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7861 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007862 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7863 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7864 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7865 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007866 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007867 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007868 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007869 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007870 } else {
7871 oomAdj = Integer.toString(r.setAdj);
7872 }
7873 String schedGroup;
7874 switch (r.setSchedGroup) {
7875 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7876 schedGroup = "B";
7877 break;
7878 case Process.THREAD_GROUP_DEFAULT:
7879 schedGroup = "F";
7880 break;
7881 default:
7882 schedGroup = Integer.toString(r.setSchedGroup);
7883 break;
7884 }
7885 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007886 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007887 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007888 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007889 pw.print(prefix);
7890 pw.print(" ");
7891 if (r.adjTarget instanceof ComponentName) {
7892 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7893 } else if (r.adjTarget != null) {
7894 pw.print(r.adjTarget.toString());
7895 } else {
7896 pw.print("{null}");
7897 }
7898 pw.print("<=");
7899 if (r.adjSource instanceof ProcessRecord) {
7900 pw.print("Proc{");
7901 pw.print(((ProcessRecord)r.adjSource).toShortString());
7902 pw.println("}");
7903 } else if (r.adjSource != null) {
7904 pw.println(r.adjSource.toString());
7905 } else {
7906 pw.println("{null}");
7907 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007909 } else {
7910 pw.println(String.format("%s%s #%2d: %s",
7911 prefix, (r.persistent ? persistentLabel : normalLabel),
7912 i, r.toString()));
7913 }
7914 if (r.persistent) {
7915 numPers++;
7916 }
7917 }
7918 return numPers;
7919 }
7920
Dianne Hackborn472ad872010-04-07 17:31:48 -07007921 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007922 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007923 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007924 long uptime = SystemClock.uptimeMillis();
7925 long realtime = SystemClock.elapsedRealtime();
7926
7927 if (isCheckinRequest) {
7928 // short checkin version
7929 pw.println(uptime + "," + realtime);
7930 pw.flush();
7931 } else {
7932 pw.println("Applications Memory Usage (kB):");
7933 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7934 }
7935 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7936 ProcessRecord r = (ProcessRecord)list.get(i);
7937 if (r.thread != null) {
7938 if (!isCheckinRequest) {
7939 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7940 pw.flush();
7941 }
7942 try {
7943 r.thread.asBinder().dump(fd, args);
7944 } catch (RemoteException e) {
7945 if (!isCheckinRequest) {
7946 pw.println("Got RemoteException!");
7947 pw.flush();
7948 }
7949 }
7950 }
7951 }
7952 }
7953
7954 /**
7955 * Searches array of arguments for the specified string
7956 * @param args array of argument strings
7957 * @param value value to search for
7958 * @return true if the value is contained in the array
7959 */
7960 private static boolean scanArgs(String[] args, String value) {
7961 if (args != null) {
7962 for (String arg : args) {
7963 if (value.equals(arg)) {
7964 return true;
7965 }
7966 }
7967 }
7968 return false;
7969 }
7970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007971 private final void killServicesLocked(ProcessRecord app,
7972 boolean allowRestart) {
7973 // Report disconnected services.
7974 if (false) {
7975 // XXX we are letting the client link to the service for
7976 // death notifications.
7977 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007978 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007979 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007980 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007981 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007982 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007983 = r.connections.values().iterator();
7984 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007985 ArrayList<ConnectionRecord> cl = jt.next();
7986 for (int i=0; i<cl.size(); i++) {
7987 ConnectionRecord c = cl.get(i);
7988 if (c.binding.client != app) {
7989 try {
7990 //c.conn.connected(r.className, null);
7991 } catch (Exception e) {
7992 // todo: this should be asynchronous!
7993 Slog.w(TAG, "Exception thrown disconnected servce "
7994 + r.shortName
7995 + " from app " + app.processName, e);
7996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007997 }
7998 }
7999 }
8000 }
8001 }
8002 }
8003 }
8004
8005 // Clean up any connections this application has to other services.
8006 if (app.connections.size() > 0) {
8007 Iterator<ConnectionRecord> it = app.connections.iterator();
8008 while (it.hasNext()) {
8009 ConnectionRecord r = it.next();
8010 removeConnectionLocked(r, app, null);
8011 }
8012 }
8013 app.connections.clear();
8014
8015 if (app.services.size() != 0) {
8016 // Any services running in the application need to be placed
8017 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008018 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008019 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008020 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021 synchronized (sr.stats.getBatteryStats()) {
8022 sr.stats.stopLaunchedLocked();
8023 }
8024 sr.app = null;
8025 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008026 if (mStoppingServices.remove(sr)) {
8027 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8028 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008029
8030 boolean hasClients = sr.bindings.size() > 0;
8031 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 Iterator<IntentBindRecord> bindings
8033 = sr.bindings.values().iterator();
8034 while (bindings.hasNext()) {
8035 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008036 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037 + ": shouldUnbind=" + b.hasBound);
8038 b.binder = null;
8039 b.requested = b.received = b.hasBound = false;
8040 }
8041 }
8042
8043 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008044 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008046 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008047 sr.crashCount, sr.shortName, app.pid);
8048 bringDownServiceLocked(sr, true);
8049 } else if (!allowRestart) {
8050 bringDownServiceLocked(sr, true);
8051 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008052 boolean canceled = scheduleServiceRestartLocked(sr, true);
8053
8054 // Should the service remain running? Note that in the
8055 // extreme case of so many attempts to deliver a command
8056 // that it failed, that we also will stop it here.
8057 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8058 if (sr.pendingStarts.size() == 0) {
8059 sr.startRequested = false;
8060 if (!hasClients) {
8061 // Whoops, no reason to restart!
8062 bringDownServiceLocked(sr, true);
8063 }
8064 }
8065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 }
8067 }
8068
8069 if (!allowRestart) {
8070 app.services.clear();
8071 }
8072 }
8073
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008074 // Make sure we have no more records on the stopping list.
8075 int i = mStoppingServices.size();
8076 while (i > 0) {
8077 i--;
8078 ServiceRecord sr = mStoppingServices.get(i);
8079 if (sr.app == app) {
8080 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008081 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008082 }
8083 }
8084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008085 app.executingServices.clear();
8086 }
8087
8088 private final void removeDyingProviderLocked(ProcessRecord proc,
8089 ContentProviderRecord cpr) {
8090 synchronized (cpr) {
8091 cpr.launchingApp = null;
8092 cpr.notifyAll();
8093 }
8094
8095 mProvidersByClass.remove(cpr.info.name);
8096 String names[] = cpr.info.authority.split(";");
8097 for (int j = 0; j < names.length; j++) {
8098 mProvidersByName.remove(names[j]);
8099 }
8100
8101 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8102 while (cit.hasNext()) {
8103 ProcessRecord capp = cit.next();
8104 if (!capp.persistent && capp.thread != null
8105 && capp.pid != 0
8106 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008107 Slog.i(TAG, "Kill " + capp.processName
8108 + " (pid " + capp.pid + "): provider " + cpr.info.name
8109 + " in dying process " + proc.processName);
8110 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8111 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008112 Process.killProcess(capp.pid);
8113 }
8114 }
8115
8116 mLaunchingProviders.remove(cpr);
8117 }
8118
8119 /**
8120 * Main code for cleaning up a process when it has gone away. This is
8121 * called both as a result of the process dying, or directly when stopping
8122 * a process when running in single process mode.
8123 */
8124 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8125 boolean restarting, int index) {
8126 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008127 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008128 }
8129
Dianne Hackborn36124872009-10-08 16:22:03 -07008130 mProcessesToGc.remove(app);
8131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008132 // Dismiss any open dialogs.
8133 if (app.crashDialog != null) {
8134 app.crashDialog.dismiss();
8135 app.crashDialog = null;
8136 }
8137 if (app.anrDialog != null) {
8138 app.anrDialog.dismiss();
8139 app.anrDialog = null;
8140 }
8141 if (app.waitDialog != null) {
8142 app.waitDialog.dismiss();
8143 app.waitDialog = null;
8144 }
8145
8146 app.crashing = false;
8147 app.notResponding = false;
8148
8149 app.resetPackageList();
8150 app.thread = null;
8151 app.forcingToForeground = null;
8152 app.foregroundServices = false;
8153
8154 killServicesLocked(app, true);
8155
8156 boolean restart = false;
8157
8158 int NL = mLaunchingProviders.size();
8159
8160 // Remove published content providers.
8161 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008162 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008163 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008164 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165 cpr.provider = null;
8166 cpr.app = null;
8167
8168 // See if someone is waiting for this provider... in which
8169 // case we don't remove it, but just let it restart.
8170 int i = 0;
8171 if (!app.bad) {
8172 for (; i<NL; i++) {
8173 if (mLaunchingProviders.get(i) == cpr) {
8174 restart = true;
8175 break;
8176 }
8177 }
8178 } else {
8179 i = NL;
8180 }
8181
8182 if (i >= NL) {
8183 removeDyingProviderLocked(app, cpr);
8184 NL = mLaunchingProviders.size();
8185 }
8186 }
8187 app.pubProviders.clear();
8188 }
8189
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008190 // Take care of any launching providers waiting for this process.
8191 if (checkAppInLaunchingProvidersLocked(app, false)) {
8192 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008193 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008195 // Unregister from connected content providers.
8196 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008197 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008198 while (it.hasNext()) {
8199 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8200 cpr.clients.remove(app);
8201 }
8202 app.conProviders.clear();
8203 }
8204
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008205 // At this point there may be remaining entries in mLaunchingProviders
8206 // where we were the only one waiting, so they are no longer of use.
8207 // Look for these and clean up if found.
8208 // XXX Commented out for now. Trying to figure out a way to reproduce
8209 // the actual situation to identify what is actually going on.
8210 if (false) {
8211 for (int i=0; i<NL; i++) {
8212 ContentProviderRecord cpr = (ContentProviderRecord)
8213 mLaunchingProviders.get(i);
8214 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8215 synchronized (cpr) {
8216 cpr.launchingApp = null;
8217 cpr.notifyAll();
8218 }
8219 }
8220 }
8221 }
8222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 skipCurrentReceiverLocked(app);
8224
8225 // Unregister any receivers.
8226 if (app.receivers.size() > 0) {
8227 Iterator<ReceiverList> it = app.receivers.iterator();
8228 while (it.hasNext()) {
8229 removeReceiverLocked(it.next());
8230 }
8231 app.receivers.clear();
8232 }
8233
Christopher Tate181fafa2009-05-14 11:12:14 -07008234 // If the app is undergoing backup, tell the backup manager about it
8235 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008236 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008237 try {
8238 IBackupManager bm = IBackupManager.Stub.asInterface(
8239 ServiceManager.getService(Context.BACKUP_SERVICE));
8240 bm.agentDisconnected(app.info.packageName);
8241 } catch (RemoteException e) {
8242 // can't happen; backup manager is local
8243 }
8244 }
8245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008246 // If the caller is restarting this app, then leave it in its
8247 // current lists and let the caller take care of it.
8248 if (restarting) {
8249 return;
8250 }
8251
8252 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008253 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008254 "Removing non-persistent process during cleanup: " + app);
8255 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008256 if (mHeavyWeightProcess == app) {
8257 mHeavyWeightProcess = null;
8258 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 } else if (!app.removed) {
8261 // This app is persistent, so we need to keep its record around.
8262 // If it is not already on the pending app list, add it there
8263 // and start a new process for it.
8264 app.thread = null;
8265 app.forcingToForeground = null;
8266 app.foregroundServices = false;
8267 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8268 mPersistentStartingProcesses.add(app);
8269 restart = true;
8270 }
8271 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008272 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8273 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008274 mProcessesOnHold.remove(app);
8275
The Android Open Source Project4df24232009-03-05 14:34:35 -08008276 if (app == mHomeProcess) {
8277 mHomeProcess = null;
8278 }
8279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008280 if (restart) {
8281 // We have components that still need to be running in the
8282 // process, so re-launch it.
8283 mProcessNames.put(app.processName, app.info.uid, app);
8284 startProcessLocked(app, "restart", app.processName);
8285 } else if (app.pid > 0 && app.pid != MY_PID) {
8286 // Goodbye!
8287 synchronized (mPidsSelfLocked) {
8288 mPidsSelfLocked.remove(app.pid);
8289 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8290 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008291 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008292 }
8293 }
8294
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008295 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8296 // Look through the content providers we are waiting to have launched,
8297 // and if any run in this process then either schedule a restart of
8298 // the process or kill the client waiting for it if this process has
8299 // gone bad.
8300 int NL = mLaunchingProviders.size();
8301 boolean restart = false;
8302 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008303 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008304 if (cpr.launchingApp == app) {
8305 if (!alwaysBad && !app.bad) {
8306 restart = true;
8307 } else {
8308 removeDyingProviderLocked(app, cpr);
8309 NL = mLaunchingProviders.size();
8310 }
8311 }
8312 }
8313 return restart;
8314 }
8315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008316 // =========================================================
8317 // SERVICES
8318 // =========================================================
8319
8320 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8321 ActivityManager.RunningServiceInfo info =
8322 new ActivityManager.RunningServiceInfo();
8323 info.service = r.name;
8324 if (r.app != null) {
8325 info.pid = r.app.pid;
8326 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008327 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 info.process = r.processName;
8329 info.foreground = r.isForeground;
8330 info.activeSince = r.createTime;
8331 info.started = r.startRequested;
8332 info.clientCount = r.connections.size();
8333 info.crashCount = r.crashCount;
8334 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008335 if (r.isForeground) {
8336 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8337 }
8338 if (r.startRequested) {
8339 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8340 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008341 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008342 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8343 }
8344 if (r.app != null && r.app.persistent) {
8345 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8346 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008347
8348 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8349 for (int i=0; i<connl.size(); i++) {
8350 ConnectionRecord conn = connl.get(i);
8351 if (conn.clientLabel != 0) {
8352 info.clientPackage = conn.binding.client.info.packageName;
8353 info.clientLabel = conn.clientLabel;
8354 return info;
8355 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008356 }
8357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008358 return info;
8359 }
8360
8361 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8362 int flags) {
8363 synchronized (this) {
8364 ArrayList<ActivityManager.RunningServiceInfo> res
8365 = new ArrayList<ActivityManager.RunningServiceInfo>();
8366
8367 if (mServices.size() > 0) {
8368 Iterator<ServiceRecord> it = mServices.values().iterator();
8369 while (it.hasNext() && res.size() < maxNum) {
8370 res.add(makeRunningServiceInfoLocked(it.next()));
8371 }
8372 }
8373
8374 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8375 ServiceRecord r = mRestartingServices.get(i);
8376 ActivityManager.RunningServiceInfo info =
8377 makeRunningServiceInfoLocked(r);
8378 info.restarting = r.nextRestartTime;
8379 res.add(info);
8380 }
8381
8382 return res;
8383 }
8384 }
8385
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008386 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8387 synchronized (this) {
8388 ServiceRecord r = mServices.get(name);
8389 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008390 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8391 for (int i=0; i<conn.size(); i++) {
8392 if (conn.get(i).clientIntent != null) {
8393 return conn.get(i).clientIntent;
8394 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008395 }
8396 }
8397 }
8398 }
8399 return null;
8400 }
8401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008402 private final ServiceRecord findServiceLocked(ComponentName name,
8403 IBinder token) {
8404 ServiceRecord r = mServices.get(name);
8405 return r == token ? r : null;
8406 }
8407
8408 private final class ServiceLookupResult {
8409 final ServiceRecord record;
8410 final String permission;
8411
8412 ServiceLookupResult(ServiceRecord _record, String _permission) {
8413 record = _record;
8414 permission = _permission;
8415 }
8416 };
8417
8418 private ServiceLookupResult findServiceLocked(Intent service,
8419 String resolvedType) {
8420 ServiceRecord r = null;
8421 if (service.getComponent() != null) {
8422 r = mServices.get(service.getComponent());
8423 }
8424 if (r == null) {
8425 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8426 r = mServicesByIntent.get(filter);
8427 }
8428
8429 if (r == null) {
8430 try {
8431 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008432 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008433 service, resolvedType, 0);
8434 ServiceInfo sInfo =
8435 rInfo != null ? rInfo.serviceInfo : null;
8436 if (sInfo == null) {
8437 return null;
8438 }
8439
8440 ComponentName name = new ComponentName(
8441 sInfo.applicationInfo.packageName, sInfo.name);
8442 r = mServices.get(name);
8443 } catch (RemoteException ex) {
8444 // pm is in same process, this will never happen.
8445 }
8446 }
8447 if (r != null) {
8448 int callingPid = Binder.getCallingPid();
8449 int callingUid = Binder.getCallingUid();
8450 if (checkComponentPermission(r.permission,
8451 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8452 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008453 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008454 + " from pid=" + callingPid
8455 + ", uid=" + callingUid
8456 + " requires " + r.permission);
8457 return new ServiceLookupResult(null, r.permission);
8458 }
8459 return new ServiceLookupResult(r, null);
8460 }
8461 return null;
8462 }
8463
8464 private class ServiceRestarter implements Runnable {
8465 private ServiceRecord mService;
8466
8467 void setService(ServiceRecord service) {
8468 mService = service;
8469 }
8470
8471 public void run() {
8472 synchronized(ActivityManagerService.this) {
8473 performServiceRestartLocked(mService);
8474 }
8475 }
8476 }
8477
8478 private ServiceLookupResult retrieveServiceLocked(Intent service,
8479 String resolvedType, int callingPid, int callingUid) {
8480 ServiceRecord r = null;
8481 if (service.getComponent() != null) {
8482 r = mServices.get(service.getComponent());
8483 }
8484 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8485 r = mServicesByIntent.get(filter);
8486 if (r == null) {
8487 try {
8488 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008489 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008490 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008491 ServiceInfo sInfo =
8492 rInfo != null ? rInfo.serviceInfo : null;
8493 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008494 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008495 ": not found");
8496 return null;
8497 }
8498
8499 ComponentName name = new ComponentName(
8500 sInfo.applicationInfo.packageName, sInfo.name);
8501 r = mServices.get(name);
8502 if (r == null) {
8503 filter = new Intent.FilterComparison(service.cloneFilter());
8504 ServiceRestarter res = new ServiceRestarter();
8505 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8506 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8507 synchronized (stats) {
8508 ss = stats.getServiceStatsLocked(
8509 sInfo.applicationInfo.uid, sInfo.packageName,
8510 sInfo.name);
8511 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008512 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008513 res.setService(r);
8514 mServices.put(name, r);
8515 mServicesByIntent.put(filter, r);
8516
8517 // Make sure this component isn't in the pending list.
8518 int N = mPendingServices.size();
8519 for (int i=0; i<N; i++) {
8520 ServiceRecord pr = mPendingServices.get(i);
8521 if (pr.name.equals(name)) {
8522 mPendingServices.remove(i);
8523 i--;
8524 N--;
8525 }
8526 }
8527 }
8528 } catch (RemoteException ex) {
8529 // pm is in same process, this will never happen.
8530 }
8531 }
8532 if (r != null) {
8533 if (checkComponentPermission(r.permission,
8534 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8535 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008536 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 + " from pid=" + Binder.getCallingPid()
8538 + ", uid=" + Binder.getCallingUid()
8539 + " requires " + r.permission);
8540 return new ServiceLookupResult(null, r.permission);
8541 }
8542 return new ServiceLookupResult(r, null);
8543 }
8544 return null;
8545 }
8546
8547 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8548 long now = SystemClock.uptimeMillis();
8549 if (r.executeNesting == 0 && r.app != null) {
8550 if (r.app.executingServices.size() == 0) {
8551 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8552 msg.obj = r.app;
8553 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8554 }
8555 r.app.executingServices.add(r);
8556 }
8557 r.executeNesting++;
8558 r.executingStart = now;
8559 }
8560
8561 private final void sendServiceArgsLocked(ServiceRecord r,
8562 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008563 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008564 if (N == 0) {
8565 return;
8566 }
8567
Dianne Hackborn39792d22010-08-19 18:01:52 -07008568 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008569 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008570 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008571 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8572 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008573 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008574 // If somehow we got a dummy start at the front, then
8575 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008576 continue;
8577 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008578 si.deliveredTime = SystemClock.uptimeMillis();
8579 r.deliveredStarts.add(si);
8580 si.deliveryCount++;
8581 if (si.targetPermissionUid >= 0) {
8582 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008583 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008584 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008585 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008586 bumpServiceExecutingLocked(r);
8587 if (!oomAdjusted) {
8588 oomAdjusted = true;
8589 updateOomAdjLocked(r.app);
8590 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008591 int flags = 0;
8592 if (si.deliveryCount > 0) {
8593 flags |= Service.START_FLAG_RETRY;
8594 }
8595 if (si.doneExecutingCount > 0) {
8596 flags |= Service.START_FLAG_REDELIVERY;
8597 }
8598 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008599 } catch (RemoteException e) {
8600 // Remote process gone... we'll let the normal cleanup take
8601 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008602 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008603 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008604 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008605 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008606 break;
8607 }
8608 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008609 }
8610
8611 private final boolean requestServiceBindingLocked(ServiceRecord r,
8612 IntentBindRecord i, boolean rebind) {
8613 if (r.app == null || r.app.thread == null) {
8614 // If service is not currently running, can't yet bind.
8615 return false;
8616 }
8617 if ((!i.requested || rebind) && i.apps.size() > 0) {
8618 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008619 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
8620 + " in " + i + ": shouldUnbind=" + i.hasBound);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008621 bumpServiceExecutingLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008622 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8623 if (!rebind) {
8624 i.requested = true;
8625 }
8626 i.hasBound = true;
8627 i.doRebind = false;
8628 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008629 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008630 return false;
8631 }
8632 }
8633 return true;
8634 }
8635
8636 private final void requestServiceBindingsLocked(ServiceRecord r) {
8637 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8638 while (bindings.hasNext()) {
8639 IntentBindRecord i = bindings.next();
8640 if (!requestServiceBindingLocked(r, i, false)) {
8641 break;
8642 }
8643 }
8644 }
8645
8646 private final void realStartServiceLocked(ServiceRecord r,
8647 ProcessRecord app) throws RemoteException {
8648 if (app.thread == null) {
8649 throw new RemoteException();
8650 }
8651
8652 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008653 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008654
8655 app.services.add(r);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008656 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008657 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008658 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008659
8660 boolean created = false;
8661 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008662 mStringBuilder.setLength(0);
8663 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008664 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008665 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008666 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008667 synchronized (r.stats.getBatteryStats()) {
8668 r.stats.startLaunchedLocked();
8669 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008670 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008671 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008672 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008673 created = true;
8674 } finally {
8675 if (!created) {
8676 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008677 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008678 }
8679 }
8680
8681 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008682
8683 // If the service is in the started state, and there are no
8684 // pending arguments, then fake up one so its onStartCommand() will
8685 // be called.
8686 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8687 r.lastStartId++;
8688 if (r.lastStartId < 1) {
8689 r.lastStartId = 1;
8690 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008691 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008692 }
8693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008694 sendServiceArgsLocked(r, true);
8695 }
8696
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008697 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8698 boolean allowCancel) {
8699 boolean canceled = false;
8700
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008701 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008702 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008703 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008704
8705 // Any delivered but not yet finished starts should be put back
8706 // on the pending list.
8707 final int N = r.deliveredStarts.size();
8708 if (N > 0) {
8709 for (int i=N-1; i>=0; i--) {
8710 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008711 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008712 if (si.intent == null) {
8713 // We'll generate this again if needed.
8714 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8715 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8716 r.pendingStarts.add(0, si);
8717 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8718 dur *= 2;
8719 if (minDuration < dur) minDuration = dur;
8720 if (resetTime < dur) resetTime = dur;
8721 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008722 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008723 + r.name);
8724 canceled = true;
8725 }
8726 }
8727 r.deliveredStarts.clear();
8728 }
8729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008730 r.totalRestartCount++;
8731 if (r.restartDelay == 0) {
8732 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008733 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008734 } else {
8735 // If it has been a "reasonably long time" since the service
8736 // was started, then reset our restart duration back to
8737 // the beginning, so we don't infinitely increase the duration
8738 // on a service that just occasionally gets killed (which is
8739 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008740 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008741 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008742 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008743 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008744 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008745 if (r.restartDelay < minDuration) {
8746 r.restartDelay = minDuration;
8747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008748 }
8749 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008750
8751 r.nextRestartTime = now + r.restartDelay;
8752
8753 // Make sure that we don't end up restarting a bunch of services
8754 // all at the same time.
8755 boolean repeat;
8756 do {
8757 repeat = false;
8758 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8759 ServiceRecord r2 = mRestartingServices.get(i);
8760 if (r2 != r && r.nextRestartTime
8761 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8762 && r.nextRestartTime
8763 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8764 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8765 r.restartDelay = r.nextRestartTime - now;
8766 repeat = true;
8767 break;
8768 }
8769 }
8770 } while (repeat);
8771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008772 if (!mRestartingServices.contains(r)) {
8773 mRestartingServices.add(r);
8774 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008775
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008776 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008778 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008779 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008780 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008781 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008783 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008784 r.shortName, r.restartDelay);
8785
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008786 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008787 }
8788
8789 final void performServiceRestartLocked(ServiceRecord r) {
8790 if (!mRestartingServices.contains(r)) {
8791 return;
8792 }
8793 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8794 }
8795
8796 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8797 if (r.restartDelay == 0) {
8798 return false;
8799 }
8800 r.resetRestartCounter();
8801 mRestartingServices.remove(r);
8802 mHandler.removeCallbacks(r.restarter);
8803 return true;
8804 }
8805
8806 private final boolean bringUpServiceLocked(ServiceRecord r,
8807 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008808 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008809 //r.dump(" ");
8810
Dianne Hackborn36124872009-10-08 16:22:03 -07008811 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 sendServiceArgsLocked(r, false);
8813 return true;
8814 }
8815
8816 if (!whileRestarting && r.restartDelay > 0) {
8817 // If waiting for a restart, then do nothing.
8818 return true;
8819 }
8820
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008821 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008822
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008823 // We are now bringing the service up, so no longer in the
8824 // restarting state.
8825 mRestartingServices.remove(r);
8826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008827 final String appName = r.processName;
8828 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8829 if (app != null && app.thread != null) {
8830 try {
8831 realStartServiceLocked(r, app);
8832 return true;
8833 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008834 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008835 }
8836
8837 // If a dead object exception was thrown -- fall through to
8838 // restart the application.
8839 }
8840
Dianne Hackborn36124872009-10-08 16:22:03 -07008841 // Not running -- get it started, and enqueue this service record
8842 // to be executed when the app comes up.
8843 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8844 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008845 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008846 + r.appInfo.packageName + "/"
8847 + r.appInfo.uid + " for service "
8848 + r.intent.getIntent() + ": process is bad");
8849 bringDownServiceLocked(r, true);
8850 return false;
8851 }
8852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008853 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008854 mPendingServices.add(r);
8855 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008857 return true;
8858 }
8859
8860 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008861 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008862 //r.dump(" ");
8863
8864 // Does it still need to run?
8865 if (!force && r.startRequested) {
8866 return;
8867 }
8868 if (r.connections.size() > 0) {
8869 if (!force) {
8870 // XXX should probably keep a count of the number of auto-create
8871 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008872 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008873 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008874 ArrayList<ConnectionRecord> cr = it.next();
8875 for (int i=0; i<cr.size(); i++) {
8876 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8877 return;
8878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008879 }
8880 }
8881 }
8882
8883 // Report to all of the connections that the service is no longer
8884 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008885 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008886 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008887 ArrayList<ConnectionRecord> c = it.next();
8888 for (int i=0; i<c.size(); i++) {
8889 try {
8890 c.get(i).conn.connected(r.name, null);
8891 } catch (Exception e) {
8892 Slog.w(TAG, "Failure disconnecting service " + r.name +
8893 " to connection " + c.get(i).conn.asBinder() +
8894 " (in " + c.get(i).binding.client.processName + ")", e);
8895 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008896 }
8897 }
8898 }
8899
8900 // Tell the service that it has been unbound.
8901 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8902 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8903 while (it.hasNext()) {
8904 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008905 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008906 + ": hasBound=" + ibr.hasBound);
8907 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8908 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008909 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
8910 + " for " + ibr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008911 bumpServiceExecutingLocked(r);
8912 updateOomAdjLocked(r.app);
8913 ibr.hasBound = false;
8914 r.app.thread.scheduleUnbindService(r,
8915 ibr.intent.getIntent());
8916 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008917 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008918 + r.shortName, e);
8919 serviceDoneExecutingLocked(r, true);
8920 }
8921 }
8922 }
8923 }
8924
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008925 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008926 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008927 System.identityHashCode(r), r.shortName,
8928 (r.app != null) ? r.app.pid : -1);
8929
8930 mServices.remove(r.name);
8931 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008932 r.totalRestartCount = 0;
8933 unscheduleServiceRestartLocked(r);
8934
8935 // Also make sure it is not on the pending list.
8936 int N = mPendingServices.size();
8937 for (int i=0; i<N; i++) {
8938 if (mPendingServices.get(i) == r) {
8939 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008940 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008941 i--;
8942 N--;
8943 }
8944 }
8945
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008946 r.cancelNotification();
8947 r.isForeground = false;
8948 r.foregroundId = 0;
8949 r.foregroundNoti = null;
8950
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008951 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07008952 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008953 r.pendingStarts.clear();
8954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008955 if (r.app != null) {
8956 synchronized (r.stats.getBatteryStats()) {
8957 r.stats.stopLaunchedLocked();
8958 }
8959 r.app.services.remove(r);
8960 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008961 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008962 if (DEBUG_SERVICE) {
8963 RuntimeException here = new RuntimeException();
8964 here.fillInStackTrace();
8965 Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
8966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008967 bumpServiceExecutingLocked(r);
8968 mStoppingServices.add(r);
8969 updateOomAdjLocked(r.app);
8970 r.app.thread.scheduleStopService(r);
8971 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008972 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 + r.shortName, e);
8974 serviceDoneExecutingLocked(r, true);
8975 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008976 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008977 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008978 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008979 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008980 }
8981 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008982 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008983 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984 }
8985 }
8986
8987 ComponentName startServiceLocked(IApplicationThread caller,
8988 Intent service, String resolvedType,
8989 int callingPid, int callingUid) {
8990 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008991 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008992 + " type=" + resolvedType + " args=" + service.getExtras());
8993
8994 if (caller != null) {
8995 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8996 if (callerApp == null) {
8997 throw new SecurityException(
8998 "Unable to find app for caller " + caller
8999 + " (pid=" + Binder.getCallingPid()
9000 + ") when starting service " + service);
9001 }
9002 }
9003
9004 ServiceLookupResult res =
9005 retrieveServiceLocked(service, resolvedType,
9006 callingPid, callingUid);
9007 if (res == null) {
9008 return null;
9009 }
9010 if (res.record == null) {
9011 return new ComponentName("!", res.permission != null
9012 ? res.permission : "private to package");
9013 }
9014 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009015 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9016 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009017 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009018 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009019 }
9020 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009021 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009022 r.lastStartId++;
9023 if (r.lastStartId < 1) {
9024 r.lastStartId = 1;
9025 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009026 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9027 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009028 r.lastActivity = SystemClock.uptimeMillis();
9029 synchronized (r.stats.getBatteryStats()) {
9030 r.stats.startRunningLocked();
9031 }
9032 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9033 return new ComponentName("!", "Service process is bad");
9034 }
9035 return r.name;
9036 }
9037 }
9038
9039 public ComponentName startService(IApplicationThread caller, Intent service,
9040 String resolvedType) {
9041 // Refuse possible leaked file descriptors
9042 if (service != null && service.hasFileDescriptors() == true) {
9043 throw new IllegalArgumentException("File descriptors passed in Intent");
9044 }
9045
9046 synchronized(this) {
9047 final int callingPid = Binder.getCallingPid();
9048 final int callingUid = Binder.getCallingUid();
9049 final long origId = Binder.clearCallingIdentity();
9050 ComponentName res = startServiceLocked(caller, service,
9051 resolvedType, callingPid, callingUid);
9052 Binder.restoreCallingIdentity(origId);
9053 return res;
9054 }
9055 }
9056
9057 ComponentName startServiceInPackage(int uid,
9058 Intent service, String resolvedType) {
9059 synchronized(this) {
9060 final long origId = Binder.clearCallingIdentity();
9061 ComponentName res = startServiceLocked(null, service,
9062 resolvedType, -1, uid);
9063 Binder.restoreCallingIdentity(origId);
9064 return res;
9065 }
9066 }
9067
9068 public int stopService(IApplicationThread caller, Intent service,
9069 String resolvedType) {
9070 // Refuse possible leaked file descriptors
9071 if (service != null && service.hasFileDescriptors() == true) {
9072 throw new IllegalArgumentException("File descriptors passed in Intent");
9073 }
9074
9075 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009076 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 + " type=" + resolvedType);
9078
9079 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9080 if (caller != null && callerApp == null) {
9081 throw new SecurityException(
9082 "Unable to find app for caller " + caller
9083 + " (pid=" + Binder.getCallingPid()
9084 + ") when stopping service " + service);
9085 }
9086
9087 // If this service is active, make sure it is stopped.
9088 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9089 if (r != null) {
9090 if (r.record != null) {
9091 synchronized (r.record.stats.getBatteryStats()) {
9092 r.record.stats.stopRunningLocked();
9093 }
9094 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009095 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009096 final long origId = Binder.clearCallingIdentity();
9097 bringDownServiceLocked(r.record, false);
9098 Binder.restoreCallingIdentity(origId);
9099 return 1;
9100 }
9101 return -1;
9102 }
9103 }
9104
9105 return 0;
9106 }
9107
9108 public IBinder peekService(Intent service, String resolvedType) {
9109 // Refuse possible leaked file descriptors
9110 if (service != null && service.hasFileDescriptors() == true) {
9111 throw new IllegalArgumentException("File descriptors passed in Intent");
9112 }
9113
9114 IBinder ret = null;
9115
9116 synchronized(this) {
9117 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9118
9119 if (r != null) {
9120 // r.record is null if findServiceLocked() failed the caller permission check
9121 if (r.record == null) {
9122 throw new SecurityException(
9123 "Permission Denial: Accessing service " + r.record.name
9124 + " from pid=" + Binder.getCallingPid()
9125 + ", uid=" + Binder.getCallingUid()
9126 + " requires " + r.permission);
9127 }
9128 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9129 if (ib != null) {
9130 ret = ib.binder;
9131 }
9132 }
9133 }
9134
9135 return ret;
9136 }
9137
9138 public boolean stopServiceToken(ComponentName className, IBinder token,
9139 int startId) {
9140 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009141 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009142 + " " + token + " startId=" + startId);
9143 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009144 if (r != null) {
9145 if (startId >= 0) {
9146 // Asked to only stop if done with all work. Note that
9147 // to avoid leaks, we will take this as dropping all
9148 // start items up to and including this one.
9149 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9150 if (si != null) {
9151 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009152 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9153 cur.removeUriPermissionsLocked();
9154 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009155 break;
9156 }
9157 }
9158 }
9159
9160 if (r.lastStartId != startId) {
9161 return false;
9162 }
9163
9164 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009165 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009166 + " is last, but have " + r.deliveredStarts.size()
9167 + " remaining args");
9168 }
9169 }
9170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009171 synchronized (r.stats.getBatteryStats()) {
9172 r.stats.stopRunningLocked();
9173 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009174 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009175 }
9176 final long origId = Binder.clearCallingIdentity();
9177 bringDownServiceLocked(r, false);
9178 Binder.restoreCallingIdentity(origId);
9179 return true;
9180 }
9181 }
9182 return false;
9183 }
9184
9185 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009186 int id, Notification notification, boolean removeNotification) {
9187 final long origId = Binder.clearCallingIdentity();
9188 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 synchronized(this) {
9190 ServiceRecord r = findServiceLocked(className, token);
9191 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009192 if (id != 0) {
9193 if (notification == null) {
9194 throw new IllegalArgumentException("null notification");
9195 }
9196 if (r.foregroundId != id) {
9197 r.cancelNotification();
9198 r.foregroundId = id;
9199 }
9200 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9201 r.foregroundNoti = notification;
9202 r.isForeground = true;
9203 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009204 if (r.app != null) {
9205 updateServiceForegroundLocked(r.app, true);
9206 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009207 } else {
9208 if (r.isForeground) {
9209 r.isForeground = false;
9210 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009211 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009212 updateServiceForegroundLocked(r.app, true);
9213 }
9214 }
9215 if (removeNotification) {
9216 r.cancelNotification();
9217 r.foregroundId = 0;
9218 r.foregroundNoti = null;
9219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009220 }
9221 }
9222 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009223 } finally {
9224 Binder.restoreCallingIdentity(origId);
9225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 }
9227
9228 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9229 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009230 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 if (sr.isForeground) {
9232 anyForeground = true;
9233 break;
9234 }
9235 }
9236 if (anyForeground != proc.foregroundServices) {
9237 proc.foregroundServices = anyForeground;
9238 if (oomAdj) {
9239 updateOomAdjLocked();
9240 }
9241 }
9242 }
9243
9244 public int bindService(IApplicationThread caller, IBinder token,
9245 Intent service, String resolvedType,
9246 IServiceConnection connection, int flags) {
9247 // Refuse possible leaked file descriptors
9248 if (service != null && service.hasFileDescriptors() == true) {
9249 throw new IllegalArgumentException("File descriptors passed in Intent");
9250 }
9251
9252 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009253 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009254 + " type=" + resolvedType + " conn=" + connection.asBinder()
9255 + " flags=0x" + Integer.toHexString(flags));
9256 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9257 if (callerApp == null) {
9258 throw new SecurityException(
9259 "Unable to find app for caller " + caller
9260 + " (pid=" + Binder.getCallingPid()
9261 + ") when binding service " + service);
9262 }
9263
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009264 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009265 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009266 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009267 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009268 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009269 return 0;
9270 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009271 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009272 }
9273
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009274 int clientLabel = 0;
9275 PendingIntent clientIntent = null;
9276
9277 if (callerApp.info.uid == Process.SYSTEM_UID) {
9278 // Hacky kind of thing -- allow system stuff to tell us
9279 // what they are, so we can report this elsewhere for
9280 // others to know why certain services are running.
9281 try {
9282 clientIntent = (PendingIntent)service.getParcelableExtra(
9283 Intent.EXTRA_CLIENT_INTENT);
9284 } catch (RuntimeException e) {
9285 }
9286 if (clientIntent != null) {
9287 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9288 if (clientLabel != 0) {
9289 // There are no useful extras in the intent, trash them.
9290 // System code calling with this stuff just needs to know
9291 // this will happen.
9292 service = service.cloneFilter();
9293 }
9294 }
9295 }
9296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009297 ServiceLookupResult res =
9298 retrieveServiceLocked(service, resolvedType,
9299 Binder.getCallingPid(), Binder.getCallingUid());
9300 if (res == null) {
9301 return 0;
9302 }
9303 if (res.record == null) {
9304 return -1;
9305 }
9306 ServiceRecord s = res.record;
9307
9308 final long origId = Binder.clearCallingIdentity();
9309
9310 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009311 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009312 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009313 }
9314
9315 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9316 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009317 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009318
9319 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009320 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9321 if (clist == null) {
9322 clist = new ArrayList<ConnectionRecord>();
9323 s.connections.put(binder, clist);
9324 }
9325 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009326 b.connections.add(c);
9327 if (activity != null) {
9328 if (activity.connections == null) {
9329 activity.connections = new HashSet<ConnectionRecord>();
9330 }
9331 activity.connections.add(c);
9332 }
9333 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009334 clist = mServiceConnections.get(binder);
9335 if (clist == null) {
9336 clist = new ArrayList<ConnectionRecord>();
9337 mServiceConnections.put(binder, clist);
9338 }
9339 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340
9341 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9342 s.lastActivity = SystemClock.uptimeMillis();
9343 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9344 return 0;
9345 }
9346 }
9347
9348 if (s.app != null) {
9349 // This could have made the service more important.
9350 updateOomAdjLocked(s.app);
9351 }
9352
Joe Onorato8a9b2202010-02-26 18:56:32 -08009353 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009354 + ": received=" + b.intent.received
9355 + " apps=" + b.intent.apps.size()
9356 + " doRebind=" + b.intent.doRebind);
9357
9358 if (s.app != null && b.intent.received) {
9359 // Service is already running, so we can immediately
9360 // publish the connection.
9361 try {
9362 c.conn.connected(s.name, b.intent.binder);
9363 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009364 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009365 + " to connection " + c.conn.asBinder()
9366 + " (in " + c.binding.client.processName + ")", e);
9367 }
9368
9369 // If this is the first app connected back to this binding,
9370 // and the service had previously asked to be told when
9371 // rebound, then do so.
9372 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9373 requestServiceBindingLocked(s, b.intent, true);
9374 }
9375 } else if (!b.intent.requested) {
9376 requestServiceBindingLocked(s, b.intent, false);
9377 }
9378
9379 Binder.restoreCallingIdentity(origId);
9380 }
9381
9382 return 1;
9383 }
9384
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009385 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009386 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009387 IBinder binder = c.conn.asBinder();
9388 AppBindRecord b = c.binding;
9389 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009390 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9391 if (clist != null) {
9392 clist.remove(c);
9393 if (clist.size() == 0) {
9394 s.connections.remove(binder);
9395 }
9396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009397 b.connections.remove(c);
9398 if (c.activity != null && c.activity != skipAct) {
9399 if (c.activity.connections != null) {
9400 c.activity.connections.remove(c);
9401 }
9402 }
9403 if (b.client != skipApp) {
9404 b.client.connections.remove(c);
9405 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009406 clist = mServiceConnections.get(binder);
9407 if (clist != null) {
9408 clist.remove(c);
9409 if (clist.size() == 0) {
9410 mServiceConnections.remove(binder);
9411 }
9412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009413
9414 if (b.connections.size() == 0) {
9415 b.intent.apps.remove(b.client);
9416 }
9417
Joe Onorato8a9b2202010-02-26 18:56:32 -08009418 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009419 + ": shouldUnbind=" + b.intent.hasBound);
9420 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9421 && b.intent.hasBound) {
9422 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009423 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
9424 + " from " + b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009425 bumpServiceExecutingLocked(s);
9426 updateOomAdjLocked(s.app);
9427 b.intent.hasBound = false;
9428 // Assume the client doesn't want to know about a rebind;
9429 // we will deal with that later if it asks for one.
9430 b.intent.doRebind = false;
9431 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9432 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009433 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009434 serviceDoneExecutingLocked(s, true);
9435 }
9436 }
9437
9438 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9439 bringDownServiceLocked(s, false);
9440 }
9441 }
9442
9443 public boolean unbindService(IServiceConnection connection) {
9444 synchronized (this) {
9445 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009446 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009447 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9448 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009449 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009450 + connection.asBinder());
9451 return false;
9452 }
9453
9454 final long origId = Binder.clearCallingIdentity();
9455
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009456 while (clist.size() > 0) {
9457 ConnectionRecord r = clist.get(0);
9458 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009459
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009460 if (r.binding.service.app != null) {
9461 // This could have made the service less important.
9462 updateOomAdjLocked(r.binding.service.app);
9463 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009464 }
9465
9466 Binder.restoreCallingIdentity(origId);
9467 }
9468
9469 return true;
9470 }
9471
9472 public void publishService(IBinder token, Intent intent, IBinder service) {
9473 // Refuse possible leaked file descriptors
9474 if (intent != null && intent.hasFileDescriptors() == true) {
9475 throw new IllegalArgumentException("File descriptors passed in Intent");
9476 }
9477
9478 synchronized(this) {
9479 if (!(token instanceof ServiceRecord)) {
9480 throw new IllegalArgumentException("Invalid service token");
9481 }
9482 ServiceRecord r = (ServiceRecord)token;
9483
9484 final long origId = Binder.clearCallingIdentity();
9485
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009486 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009487 + " " + intent + ": " + service);
9488 if (r != null) {
9489 Intent.FilterComparison filter
9490 = new Intent.FilterComparison(intent);
9491 IntentBindRecord b = r.bindings.get(filter);
9492 if (b != null && !b.received) {
9493 b.binder = service;
9494 b.requested = true;
9495 b.received = true;
9496 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009497 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009498 = r.connections.values().iterator();
9499 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009500 ArrayList<ConnectionRecord> clist = it.next();
9501 for (int i=0; i<clist.size(); i++) {
9502 ConnectionRecord c = clist.get(i);
9503 if (!filter.equals(c.binding.intent.intent)) {
9504 if (DEBUG_SERVICE) Slog.v(
9505 TAG, "Not publishing to: " + c);
9506 if (DEBUG_SERVICE) Slog.v(
9507 TAG, "Bound intent: " + c.binding.intent.intent);
9508 if (DEBUG_SERVICE) Slog.v(
9509 TAG, "Published intent: " + intent);
9510 continue;
9511 }
9512 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9513 try {
9514 c.conn.connected(r.name, service);
9515 } catch (Exception e) {
9516 Slog.w(TAG, "Failure sending service " + r.name +
9517 " to connection " + c.conn.asBinder() +
9518 " (in " + c.binding.client.processName + ")", e);
9519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009520 }
9521 }
9522 }
9523 }
9524
9525 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9526
9527 Binder.restoreCallingIdentity(origId);
9528 }
9529 }
9530 }
9531
9532 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9533 // Refuse possible leaked file descriptors
9534 if (intent != null && intent.hasFileDescriptors() == true) {
9535 throw new IllegalArgumentException("File descriptors passed in Intent");
9536 }
9537
9538 synchronized(this) {
9539 if (!(token instanceof ServiceRecord)) {
9540 throw new IllegalArgumentException("Invalid service token");
9541 }
9542 ServiceRecord r = (ServiceRecord)token;
9543
9544 final long origId = Binder.clearCallingIdentity();
9545
9546 if (r != null) {
9547 Intent.FilterComparison filter
9548 = new Intent.FilterComparison(intent);
9549 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009550 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009551 + " at " + b + ": apps="
9552 + (b != null ? b.apps.size() : 0));
9553 if (b != null) {
9554 if (b.apps.size() > 0) {
9555 // Applications have already bound since the last
9556 // unbind, so just rebind right here.
9557 requestServiceBindingLocked(r, b, true);
9558 } else {
9559 // Note to tell the service the next time there is
9560 // a new client.
9561 b.doRebind = true;
9562 }
9563 }
9564
9565 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9566
9567 Binder.restoreCallingIdentity(origId);
9568 }
9569 }
9570 }
9571
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009572 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009573 synchronized(this) {
9574 if (!(token instanceof ServiceRecord)) {
9575 throw new IllegalArgumentException("Invalid service token");
9576 }
9577 ServiceRecord r = (ServiceRecord)token;
9578 boolean inStopping = mStoppingServices.contains(token);
9579 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009580 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009581 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009582 + " with incorrect token: given " + token
9583 + ", expected " + r);
9584 return;
9585 }
9586
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009587 if (type == 1) {
9588 // This is a call from a service start... take care of
9589 // book-keeping.
9590 r.callStart = true;
9591 switch (res) {
9592 case Service.START_STICKY_COMPATIBILITY:
9593 case Service.START_STICKY: {
9594 // We are done with the associated start arguments.
9595 r.findDeliveredStart(startId, true);
9596 // Don't stop if killed.
9597 r.stopIfKilled = false;
9598 break;
9599 }
9600 case Service.START_NOT_STICKY: {
9601 // We are done with the associated start arguments.
9602 r.findDeliveredStart(startId, true);
9603 if (r.lastStartId == startId) {
9604 // There is no more work, and this service
9605 // doesn't want to hang around if killed.
9606 r.stopIfKilled = true;
9607 }
9608 break;
9609 }
9610 case Service.START_REDELIVER_INTENT: {
9611 // We'll keep this item until they explicitly
9612 // call stop for it, but keep track of the fact
9613 // that it was delivered.
9614 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9615 if (si != null) {
9616 si.deliveryCount = 0;
9617 si.doneExecutingCount++;
9618 // Don't stop if killed.
9619 r.stopIfKilled = true;
9620 }
9621 break;
9622 }
9623 default:
9624 throw new IllegalArgumentException(
9625 "Unknown service start result: " + res);
9626 }
9627 if (res == Service.START_STICKY_COMPATIBILITY) {
9628 r.callStart = false;
9629 }
9630 }
9631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009632 final long origId = Binder.clearCallingIdentity();
9633 serviceDoneExecutingLocked(r, inStopping);
9634 Binder.restoreCallingIdentity(origId);
9635 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009636 Slog.w(TAG, "Done executing unknown service from pid "
9637 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009638 }
9639 }
9640 }
9641
9642 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009643 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9644 + ": nesting=" + r.executeNesting
9645 + ", inStopping=" + inStopping + ", app=" + r.app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009646 r.executeNesting--;
9647 if (r.executeNesting <= 0 && r.app != null) {
9648 r.app.executingServices.remove(r);
9649 if (r.app.executingServices.size() == 0) {
9650 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9651 }
9652 if (inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009653 if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009654 mStoppingServices.remove(r);
9655 }
9656 updateOomAdjLocked(r.app);
9657 }
9658 }
9659
9660 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009661 String anrMessage = null;
9662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009663 synchronized(this) {
9664 if (proc.executingServices.size() == 0 || proc.thread == null) {
9665 return;
9666 }
9667 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9668 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9669 ServiceRecord timeout = null;
9670 long nextTime = 0;
9671 while (it.hasNext()) {
9672 ServiceRecord sr = it.next();
9673 if (sr.executingStart < maxTime) {
9674 timeout = sr;
9675 break;
9676 }
9677 if (sr.executingStart > nextTime) {
9678 nextTime = sr.executingStart;
9679 }
9680 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009681 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009682 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009683 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009684 } else {
9685 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9686 msg.obj = proc;
9687 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9688 }
9689 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009690
9691 if (anrMessage != null) {
9692 appNotResponding(proc, null, null, anrMessage);
9693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009694 }
9695
9696 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009697 // BACKUP AND RESTORE
9698 // =========================================================
9699
9700 // Cause the target app to be launched if necessary and its backup agent
9701 // instantiated. The backup agent will invoke backupAgentCreated() on the
9702 // activity manager to announce its creation.
9703 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009704 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009705 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9706
9707 synchronized(this) {
9708 // !!! TODO: currently no check here that we're already bound
9709 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9710 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9711 synchronized (stats) {
9712 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9713 }
9714
9715 BackupRecord r = new BackupRecord(ss, app, backupMode);
9716 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9717 // startProcessLocked() returns existing proc's record if it's already running
9718 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009719 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009720 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009721 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009722 return false;
9723 }
9724
9725 r.app = proc;
9726 mBackupTarget = r;
9727 mBackupAppName = app.packageName;
9728
Christopher Tate6fa95972009-06-05 18:43:55 -07009729 // Try not to kill the process during backup
9730 updateOomAdjLocked(proc);
9731
Christopher Tate181fafa2009-05-14 11:12:14 -07009732 // If the process is already attached, schedule the creation of the backup agent now.
9733 // If it is not yet live, this will be done when it attaches to the framework.
9734 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009735 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009736 try {
9737 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9738 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009739 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009740 }
9741 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009742 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009743 }
9744 // Invariants: at this point, the target app process exists and the application
9745 // is either already running or in the process of coming up. mBackupTarget and
9746 // mBackupAppName describe the app, so that when it binds back to the AM we
9747 // know that it's scheduled for a backup-agent operation.
9748 }
9749
9750 return true;
9751 }
9752
9753 // A backup agent has just come up
9754 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009755 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009756 + " = " + agent);
9757
9758 synchronized(this) {
9759 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009760 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009761 return;
9762 }
9763
Christopher Tate043dadc2009-06-02 16:11:00 -07009764 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009765 try {
9766 IBackupManager bm = IBackupManager.Stub.asInterface(
9767 ServiceManager.getService(Context.BACKUP_SERVICE));
9768 bm.agentConnected(agentPackageName, agent);
9769 } catch (RemoteException e) {
9770 // can't happen; the backup manager service is local
9771 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009772 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009773 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009774 } finally {
9775 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009776 }
9777 }
9778 }
9779
9780 // done with this agent
9781 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009782 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009783 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009784 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009785 return;
9786 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009787
9788 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009789 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009790 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009791 return;
9792 }
9793
Christopher Tate181fafa2009-05-14 11:12:14 -07009794 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009795 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009796 return;
9797 }
9798
Christopher Tate6fa95972009-06-05 18:43:55 -07009799 ProcessRecord proc = mBackupTarget.app;
9800 mBackupTarget = null;
9801 mBackupAppName = null;
9802
9803 // Not backing this app up any more; reset its OOM adjustment
9804 updateOomAdjLocked(proc);
9805
Christopher Tatec7b31e32009-06-10 15:49:30 -07009806 // If the app crashed during backup, 'thread' will be null here
9807 if (proc.thread != null) {
9808 try {
9809 proc.thread.scheduleDestroyBackupAgent(appInfo);
9810 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009811 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009812 e.printStackTrace();
9813 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009814 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009815 }
9816 }
9817 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009818 // BROADCASTS
9819 // =========================================================
9820
Josh Bartel7f208742010-02-25 11:01:44 -06009821 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009822 List cur) {
9823 final ContentResolver resolver = mContext.getContentResolver();
9824 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9825 if (list == null) {
9826 return cur;
9827 }
9828 int N = list.size();
9829 for (int i=0; i<N; i++) {
9830 Intent intent = list.get(i);
9831 if (filter.match(resolver, intent, true, TAG) >= 0) {
9832 if (cur == null) {
9833 cur = new ArrayList<Intent>();
9834 }
9835 cur.add(intent);
9836 }
9837 }
9838 return cur;
9839 }
9840
9841 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009842 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009843 + mBroadcastsScheduled);
9844
9845 if (mBroadcastsScheduled) {
9846 return;
9847 }
9848 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9849 mBroadcastsScheduled = true;
9850 }
9851
9852 public Intent registerReceiver(IApplicationThread caller,
9853 IIntentReceiver receiver, IntentFilter filter, String permission) {
9854 synchronized(this) {
9855 ProcessRecord callerApp = null;
9856 if (caller != null) {
9857 callerApp = getRecordForAppLocked(caller);
9858 if (callerApp == null) {
9859 throw new SecurityException(
9860 "Unable to find app for caller " + caller
9861 + " (pid=" + Binder.getCallingPid()
9862 + ") when registering receiver " + receiver);
9863 }
9864 }
9865
9866 List allSticky = null;
9867
9868 // Look for any matching sticky broadcasts...
9869 Iterator actions = filter.actionsIterator();
9870 if (actions != null) {
9871 while (actions.hasNext()) {
9872 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009873 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009874 }
9875 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009876 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009877 }
9878
9879 // The first sticky in the list is returned directly back to
9880 // the client.
9881 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9882
Joe Onorato8a9b2202010-02-26 18:56:32 -08009883 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009884 + ": " + sticky);
9885
9886 if (receiver == null) {
9887 return sticky;
9888 }
9889
9890 ReceiverList rl
9891 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9892 if (rl == null) {
9893 rl = new ReceiverList(this, callerApp,
9894 Binder.getCallingPid(),
9895 Binder.getCallingUid(), receiver);
9896 if (rl.app != null) {
9897 rl.app.receivers.add(rl);
9898 } else {
9899 try {
9900 receiver.asBinder().linkToDeath(rl, 0);
9901 } catch (RemoteException e) {
9902 return sticky;
9903 }
9904 rl.linkedToDeath = true;
9905 }
9906 mRegisteredReceivers.put(receiver.asBinder(), rl);
9907 }
9908 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9909 rl.add(bf);
9910 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009911 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009912 }
9913 mReceiverResolver.addFilter(bf);
9914
9915 // Enqueue broadcasts for all existing stickies that match
9916 // this filter.
9917 if (allSticky != null) {
9918 ArrayList receivers = new ArrayList();
9919 receivers.add(bf);
9920
9921 int N = allSticky.size();
9922 for (int i=0; i<N; i++) {
9923 Intent intent = (Intent)allSticky.get(i);
9924 BroadcastRecord r = new BroadcastRecord(intent, null,
9925 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009926 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009927 if (mParallelBroadcasts.size() == 0) {
9928 scheduleBroadcastsLocked();
9929 }
9930 mParallelBroadcasts.add(r);
9931 }
9932 }
9933
9934 return sticky;
9935 }
9936 }
9937
9938 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009939 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009940
9941 boolean doNext = false;
9942
9943 synchronized(this) {
9944 ReceiverList rl
9945 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9946 if (rl != null) {
9947 if (rl.curBroadcast != null) {
9948 BroadcastRecord r = rl.curBroadcast;
9949 doNext = finishReceiverLocked(
9950 receiver.asBinder(), r.resultCode, r.resultData,
9951 r.resultExtras, r.resultAbort, true);
9952 }
9953
9954 if (rl.app != null) {
9955 rl.app.receivers.remove(rl);
9956 }
9957 removeReceiverLocked(rl);
9958 if (rl.linkedToDeath) {
9959 rl.linkedToDeath = false;
9960 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9961 }
9962 }
9963 }
9964
9965 if (!doNext) {
9966 return;
9967 }
9968
9969 final long origId = Binder.clearCallingIdentity();
9970 processNextBroadcast(false);
9971 trimApplications();
9972 Binder.restoreCallingIdentity(origId);
9973 }
9974
9975 void removeReceiverLocked(ReceiverList rl) {
9976 mRegisteredReceivers.remove(rl.receiver.asBinder());
9977 int N = rl.size();
9978 for (int i=0; i<N; i++) {
9979 mReceiverResolver.removeFilter(rl.get(i));
9980 }
9981 }
9982
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009983 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9984 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9985 ProcessRecord r = mLruProcesses.get(i);
9986 if (r.thread != null) {
9987 try {
9988 r.thread.dispatchPackageBroadcast(cmd, packages);
9989 } catch (RemoteException ex) {
9990 }
9991 }
9992 }
9993 }
9994
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009995 private final int broadcastIntentLocked(ProcessRecord callerApp,
9996 String callerPackage, Intent intent, String resolvedType,
9997 IIntentReceiver resultTo, int resultCode, String resultData,
9998 Bundle map, String requiredPermission,
9999 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10000 intent = new Intent(intent);
10001
Joe Onorato8a9b2202010-02-26 18:56:32 -080010002 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010003 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10004 + " ordered=" + ordered);
10005 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010006 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010007 }
10008
10009 // Handle special intents: if this broadcast is from the package
10010 // manager about a package being removed, we need to remove all of
10011 // its activities from the history stack.
10012 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10013 intent.getAction());
10014 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10015 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010016 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010017 || uidRemoved) {
10018 if (checkComponentPermission(
10019 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10020 callingPid, callingUid, -1)
10021 == PackageManager.PERMISSION_GRANTED) {
10022 if (uidRemoved) {
10023 final Bundle intentExtras = intent.getExtras();
10024 final int uid = intentExtras != null
10025 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10026 if (uid >= 0) {
10027 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10028 synchronized (bs) {
10029 bs.removeUidStatsLocked(uid);
10030 }
10031 }
10032 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010033 // If resources are unvailble just force stop all
10034 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010035 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010036 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10037 if (list != null && (list.length > 0)) {
10038 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010039 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010040 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010041 sendPackageBroadcastLocked(
10042 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010043 }
10044 } else {
10045 Uri data = intent.getData();
10046 String ssp;
10047 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10048 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10049 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010050 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010051 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010052 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10053 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10054 new String[] {ssp});
10055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010056 }
10057 }
10058 }
10059 } else {
10060 String msg = "Permission Denial: " + intent.getAction()
10061 + " broadcast from " + callerPackage + " (pid=" + callingPid
10062 + ", uid=" + callingUid + ")"
10063 + " requires "
10064 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010065 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 throw new SecurityException(msg);
10067 }
10068 }
10069
10070 /*
10071 * If this is the time zone changed action, queue up a message that will reset the timezone
10072 * of all currently running processes. This message will get queued up before the broadcast
10073 * happens.
10074 */
10075 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10076 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10077 }
10078
Dianne Hackborn854060af2009-07-09 18:14:31 -070010079 /*
10080 * Prevent non-system code (defined here to be non-persistent
10081 * processes) from sending protected broadcasts.
10082 */
10083 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10084 || callingUid == Process.SHELL_UID || callingUid == 0) {
10085 // Always okay.
10086 } else if (callerApp == null || !callerApp.persistent) {
10087 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010088 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010089 intent.getAction())) {
10090 String msg = "Permission Denial: not allowed to send broadcast "
10091 + intent.getAction() + " from pid="
10092 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010093 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010094 throw new SecurityException(msg);
10095 }
10096 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010097 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010098 return BROADCAST_SUCCESS;
10099 }
10100 }
10101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010102 // Add to the sticky list if requested.
10103 if (sticky) {
10104 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10105 callingPid, callingUid)
10106 != PackageManager.PERMISSION_GRANTED) {
10107 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10108 + callingPid + ", uid=" + callingUid
10109 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010110 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010111 throw new SecurityException(msg);
10112 }
10113 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010114 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010115 + " and enforce permission " + requiredPermission);
10116 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10117 }
10118 if (intent.getComponent() != null) {
10119 throw new SecurityException(
10120 "Sticky broadcasts can't target a specific component");
10121 }
10122 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10123 if (list == null) {
10124 list = new ArrayList<Intent>();
10125 mStickyBroadcasts.put(intent.getAction(), list);
10126 }
10127 int N = list.size();
10128 int i;
10129 for (i=0; i<N; i++) {
10130 if (intent.filterEquals(list.get(i))) {
10131 // This sticky already exists, replace it.
10132 list.set(i, new Intent(intent));
10133 break;
10134 }
10135 }
10136 if (i >= N) {
10137 list.add(new Intent(intent));
10138 }
10139 }
10140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010141 // Figure out who all will receive this broadcast.
10142 List receivers = null;
10143 List<BroadcastFilter> registeredReceivers = null;
10144 try {
10145 if (intent.getComponent() != null) {
10146 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010147 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010148 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010149 if (ai != null) {
10150 receivers = new ArrayList();
10151 ResolveInfo ri = new ResolveInfo();
10152 ri.activityInfo = ai;
10153 receivers.add(ri);
10154 }
10155 } else {
10156 // Need to resolve the intent to interested receivers...
10157 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10158 == 0) {
10159 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010160 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010161 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010162 }
Mihai Preda074edef2009-05-18 17:13:31 +020010163 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010164 }
10165 } catch (RemoteException ex) {
10166 // pm is in same process, this will never happen.
10167 }
10168
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010169 final boolean replacePending =
10170 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10171
Joe Onorato8a9b2202010-02-26 18:56:32 -080010172 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010173 + " replacePending=" + replacePending);
10174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010175 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10176 if (!ordered && NR > 0) {
10177 // If we are not serializing this broadcast, then send the
10178 // registered receivers separately so they don't wait for the
10179 // components to be launched.
10180 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10181 callerPackage, callingPid, callingUid, requiredPermission,
10182 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010183 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010184 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010185 TAG, "Enqueueing parallel broadcast " + r
10186 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010187 boolean replaced = false;
10188 if (replacePending) {
10189 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10190 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010191 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010192 "***** DROPPING PARALLEL: " + intent);
10193 mParallelBroadcasts.set(i, r);
10194 replaced = true;
10195 break;
10196 }
10197 }
10198 }
10199 if (!replaced) {
10200 mParallelBroadcasts.add(r);
10201 scheduleBroadcastsLocked();
10202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010203 registeredReceivers = null;
10204 NR = 0;
10205 }
10206
10207 // Merge into one list.
10208 int ir = 0;
10209 if (receivers != null) {
10210 // A special case for PACKAGE_ADDED: do not allow the package
10211 // being added to see this broadcast. This prevents them from
10212 // using this as a back door to get run as soon as they are
10213 // installed. Maybe in the future we want to have a special install
10214 // broadcast or such for apps, but we'd like to deliberately make
10215 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010216 String skipPackages[] = null;
10217 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10218 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10219 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10220 Uri data = intent.getData();
10221 if (data != null) {
10222 String pkgName = data.getSchemeSpecificPart();
10223 if (pkgName != null) {
10224 skipPackages = new String[] { pkgName };
10225 }
10226 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010227 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010228 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010229 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010230 if (skipPackages != null && (skipPackages.length > 0)) {
10231 for (String skipPackage : skipPackages) {
10232 if (skipPackage != null) {
10233 int NT = receivers.size();
10234 for (int it=0; it<NT; it++) {
10235 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10236 if (curt.activityInfo.packageName.equals(skipPackage)) {
10237 receivers.remove(it);
10238 it--;
10239 NT--;
10240 }
10241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 }
10243 }
10244 }
10245
10246 int NT = receivers != null ? receivers.size() : 0;
10247 int it = 0;
10248 ResolveInfo curt = null;
10249 BroadcastFilter curr = null;
10250 while (it < NT && ir < NR) {
10251 if (curt == null) {
10252 curt = (ResolveInfo)receivers.get(it);
10253 }
10254 if (curr == null) {
10255 curr = registeredReceivers.get(ir);
10256 }
10257 if (curr.getPriority() >= curt.priority) {
10258 // Insert this broadcast record into the final list.
10259 receivers.add(it, curr);
10260 ir++;
10261 curr = null;
10262 it++;
10263 NT++;
10264 } else {
10265 // Skip to the next ResolveInfo in the final list.
10266 it++;
10267 curt = null;
10268 }
10269 }
10270 }
10271 while (ir < NR) {
10272 if (receivers == null) {
10273 receivers = new ArrayList();
10274 }
10275 receivers.add(registeredReceivers.get(ir));
10276 ir++;
10277 }
10278
10279 if ((receivers != null && receivers.size() > 0)
10280 || resultTo != null) {
10281 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10282 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010283 receivers, resultTo, resultCode, resultData, map, ordered,
10284 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010285 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010286 TAG, "Enqueueing ordered broadcast " + r
10287 + ": prev had " + mOrderedBroadcasts.size());
10288 if (DEBUG_BROADCAST) {
10289 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010290 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010291 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010292 boolean replaced = false;
10293 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010294 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010295 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010296 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010297 "***** DROPPING ORDERED: " + intent);
10298 mOrderedBroadcasts.set(i, r);
10299 replaced = true;
10300 break;
10301 }
10302 }
10303 }
10304 if (!replaced) {
10305 mOrderedBroadcasts.add(r);
10306 scheduleBroadcastsLocked();
10307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010308 }
10309
10310 return BROADCAST_SUCCESS;
10311 }
10312
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010313 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 // Refuse possible leaked file descriptors
10315 if (intent != null && intent.hasFileDescriptors() == true) {
10316 throw new IllegalArgumentException("File descriptors passed in Intent");
10317 }
10318
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010319 int flags = intent.getFlags();
10320
10321 if (!mProcessesReady) {
10322 // if the caller really truly claims to know what they're doing, go
10323 // ahead and allow the broadcast without launching any receivers
10324 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10325 intent = new Intent(intent);
10326 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10327 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10328 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10329 + " before boot completion");
10330 throw new IllegalStateException("Cannot broadcast before boot completed");
10331 }
10332 }
10333
10334 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10335 throw new IllegalArgumentException(
10336 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10337 }
10338
10339 return intent;
10340 }
10341
10342 public final int broadcastIntent(IApplicationThread caller,
10343 Intent intent, String resolvedType, IIntentReceiver resultTo,
10344 int resultCode, String resultData, Bundle map,
10345 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010346 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010347 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010349 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10350 final int callingPid = Binder.getCallingPid();
10351 final int callingUid = Binder.getCallingUid();
10352 final long origId = Binder.clearCallingIdentity();
10353 int res = broadcastIntentLocked(callerApp,
10354 callerApp != null ? callerApp.info.packageName : null,
10355 intent, resolvedType, resultTo,
10356 resultCode, resultData, map, requiredPermission, serialized,
10357 sticky, callingPid, callingUid);
10358 Binder.restoreCallingIdentity(origId);
10359 return res;
10360 }
10361 }
10362
10363 int broadcastIntentInPackage(String packageName, int uid,
10364 Intent intent, String resolvedType, IIntentReceiver resultTo,
10365 int resultCode, String resultData, Bundle map,
10366 String requiredPermission, boolean serialized, boolean sticky) {
10367 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010368 intent = verifyBroadcastLocked(intent);
10369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010370 final long origId = Binder.clearCallingIdentity();
10371 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10372 resultTo, resultCode, resultData, map, requiredPermission,
10373 serialized, sticky, -1, uid);
10374 Binder.restoreCallingIdentity(origId);
10375 return res;
10376 }
10377 }
10378
10379 public final void unbroadcastIntent(IApplicationThread caller,
10380 Intent intent) {
10381 // Refuse possible leaked file descriptors
10382 if (intent != null && intent.hasFileDescriptors() == true) {
10383 throw new IllegalArgumentException("File descriptors passed in Intent");
10384 }
10385
10386 synchronized(this) {
10387 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10388 != PackageManager.PERMISSION_GRANTED) {
10389 String msg = "Permission Denial: unbroadcastIntent() from pid="
10390 + Binder.getCallingPid()
10391 + ", uid=" + Binder.getCallingUid()
10392 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010393 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010394 throw new SecurityException(msg);
10395 }
10396 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10397 if (list != null) {
10398 int N = list.size();
10399 int i;
10400 for (i=0; i<N; i++) {
10401 if (intent.filterEquals(list.get(i))) {
10402 list.remove(i);
10403 break;
10404 }
10405 }
10406 }
10407 }
10408 }
10409
10410 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10411 String resultData, Bundle resultExtras, boolean resultAbort,
10412 boolean explicit) {
10413 if (mOrderedBroadcasts.size() == 0) {
10414 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010415 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010416 }
10417 return false;
10418 }
10419 BroadcastRecord r = mOrderedBroadcasts.get(0);
10420 if (r.receiver == null) {
10421 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010422 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 }
10424 return false;
10425 }
10426 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010427 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010428 return false;
10429 }
10430 int state = r.state;
10431 r.state = r.IDLE;
10432 if (state == r.IDLE) {
10433 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010434 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435 }
10436 }
10437 r.receiver = null;
10438 r.intent.setComponent(null);
10439 if (r.curApp != null) {
10440 r.curApp.curReceiver = null;
10441 }
10442 if (r.curFilter != null) {
10443 r.curFilter.receiverList.curBroadcast = null;
10444 }
10445 r.curFilter = null;
10446 r.curApp = null;
10447 r.curComponent = null;
10448 r.curReceiver = null;
10449 mPendingBroadcast = null;
10450
10451 r.resultCode = resultCode;
10452 r.resultData = resultData;
10453 r.resultExtras = resultExtras;
10454 r.resultAbort = resultAbort;
10455
10456 // We will process the next receiver right now if this is finishing
10457 // an app receiver (which is always asynchronous) or after we have
10458 // come back from calling a receiver.
10459 return state == BroadcastRecord.APP_RECEIVE
10460 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10461 }
10462
10463 public void finishReceiver(IBinder who, int resultCode, String resultData,
10464 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010465 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010466
10467 // Refuse possible leaked file descriptors
10468 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10469 throw new IllegalArgumentException("File descriptors passed in Bundle");
10470 }
10471
10472 boolean doNext;
10473
10474 final long origId = Binder.clearCallingIdentity();
10475
10476 synchronized(this) {
10477 doNext = finishReceiverLocked(
10478 who, resultCode, resultData, resultExtras, resultAbort, true);
10479 }
10480
10481 if (doNext) {
10482 processNextBroadcast(false);
10483 }
10484 trimApplications();
10485
10486 Binder.restoreCallingIdentity(origId);
10487 }
10488
10489 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10490 if (r.nextReceiver > 0) {
10491 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10492 if (curReceiver instanceof BroadcastFilter) {
10493 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010494 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010495 System.identityHashCode(r),
10496 r.intent.getAction(),
10497 r.nextReceiver - 1,
10498 System.identityHashCode(bf));
10499 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010500 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010501 System.identityHashCode(r),
10502 r.intent.getAction(),
10503 r.nextReceiver - 1,
10504 ((ResolveInfo)curReceiver).toString());
10505 }
10506 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010507 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010508 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010509 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010510 System.identityHashCode(r),
10511 r.intent.getAction(),
10512 r.nextReceiver,
10513 "NONE");
10514 }
10515 }
10516
10517 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010518 ProcessRecord app = null;
10519 String anrMessage = null;
10520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010521 synchronized (this) {
10522 if (mOrderedBroadcasts.size() == 0) {
10523 return;
10524 }
10525 long now = SystemClock.uptimeMillis();
10526 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010527 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010528 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010529 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010530 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010531 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010532 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010533 return;
10534 }
10535
Joe Onorato8a9b2202010-02-26 18:56:32 -080010536 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010537 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010538 r.anrCount++;
10539
10540 // Current receiver has passed its expiration date.
10541 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010542 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010543 return;
10544 }
10545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010547 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 logBroadcastReceiverDiscard(r);
10549 if (curReceiver instanceof BroadcastFilter) {
10550 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10551 if (bf.receiverList.pid != 0
10552 && bf.receiverList.pid != MY_PID) {
10553 synchronized (this.mPidsSelfLocked) {
10554 app = this.mPidsSelfLocked.get(
10555 bf.receiverList.pid);
10556 }
10557 }
10558 } else {
10559 app = r.curApp;
10560 }
10561
10562 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010563 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010564 }
10565
10566 if (mPendingBroadcast == r) {
10567 mPendingBroadcast = null;
10568 }
10569
10570 // Move on to the next receiver.
10571 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10572 r.resultExtras, r.resultAbort, true);
10573 scheduleBroadcastsLocked();
10574 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010575
10576 if (anrMessage != null) {
10577 appNotResponding(app, null, null, anrMessage);
10578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010579 }
10580
10581 private final void processCurBroadcastLocked(BroadcastRecord r,
10582 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010583 if (DEBUG_BROADCAST) Slog.v(TAG,
10584 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 if (app.thread == null) {
10586 throw new RemoteException();
10587 }
10588 r.receiver = app.thread.asBinder();
10589 r.curApp = app;
10590 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010591 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010592
10593 // Tell the application to launch this receiver.
10594 r.intent.setComponent(r.curComponent);
10595
10596 boolean started = false;
10597 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010598 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010599 "Delivering to component " + r.curComponent
10600 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010601 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010602 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10603 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010604 if (DEBUG_BROADCAST) Slog.v(TAG,
10605 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010606 started = true;
10607 } finally {
10608 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010609 if (DEBUG_BROADCAST) Slog.v(TAG,
10610 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010611 r.receiver = null;
10612 r.curApp = null;
10613 app.curReceiver = null;
10614 }
10615 }
10616
10617 }
10618
10619 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010620 Intent intent, int resultCode, String data, Bundle extras,
10621 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010622 if (app != null && app.thread != null) {
10623 // If we have an app thread, do the call through that so it is
10624 // correctly ordered with other one-way calls.
10625 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010626 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010627 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010628 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010629 }
10630 }
10631
10632 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10633 BroadcastFilter filter, boolean ordered) {
10634 boolean skip = false;
10635 if (filter.requiredPermission != null) {
10636 int perm = checkComponentPermission(filter.requiredPermission,
10637 r.callingPid, r.callingUid, -1);
10638 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010639 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010640 + r.intent.toString()
10641 + " from " + r.callerPackage + " (pid="
10642 + r.callingPid + ", uid=" + r.callingUid + ")"
10643 + " requires " + filter.requiredPermission
10644 + " due to registered receiver " + filter);
10645 skip = true;
10646 }
10647 }
10648 if (r.requiredPermission != null) {
10649 int perm = checkComponentPermission(r.requiredPermission,
10650 filter.receiverList.pid, filter.receiverList.uid, -1);
10651 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010652 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010653 + r.intent.toString()
10654 + " to " + filter.receiverList.app
10655 + " (pid=" + filter.receiverList.pid
10656 + ", uid=" + filter.receiverList.uid + ")"
10657 + " requires " + r.requiredPermission
10658 + " due to sender " + r.callerPackage
10659 + " (uid " + r.callingUid + ")");
10660 skip = true;
10661 }
10662 }
10663
10664 if (!skip) {
10665 // If this is not being sent as an ordered broadcast, then we
10666 // don't want to touch the fields that keep track of the current
10667 // state of ordered broadcasts.
10668 if (ordered) {
10669 r.receiver = filter.receiverList.receiver.asBinder();
10670 r.curFilter = filter;
10671 filter.receiverList.curBroadcast = r;
10672 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010673 if (filter.receiverList.app != null) {
10674 // Bump hosting application to no longer be in background
10675 // scheduling class. Note that we can't do that if there
10676 // isn't an app... but we can only be in that case for
10677 // things that directly call the IActivityManager API, which
10678 // are already core system stuff so don't matter for this.
10679 r.curApp = filter.receiverList.app;
10680 filter.receiverList.app.curReceiver = r;
10681 updateOomAdjLocked();
10682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010683 }
10684 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010685 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010686 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010687 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010688 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010689 }
10690 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10691 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010692 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010693 if (ordered) {
10694 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10695 }
10696 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010697 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010698 if (ordered) {
10699 r.receiver = null;
10700 r.curFilter = null;
10701 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010702 if (filter.receiverList.app != null) {
10703 filter.receiverList.app.curReceiver = null;
10704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010705 }
10706 }
10707 }
10708 }
10709
Dianne Hackborn12527f92009-11-11 17:39:50 -080010710 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10711 if (r.callingUid < 0) {
10712 // This was from a registerReceiver() call; ignore it.
10713 return;
10714 }
10715 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10716 MAX_BROADCAST_HISTORY-1);
10717 r.finishTime = SystemClock.uptimeMillis();
10718 mBroadcastHistory[0] = r;
10719 }
10720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010721 private final void processNextBroadcast(boolean fromMsg) {
10722 synchronized(this) {
10723 BroadcastRecord r;
10724
Joe Onorato8a9b2202010-02-26 18:56:32 -080010725 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010726 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010727 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010728
10729 updateCpuStats();
10730
10731 if (fromMsg) {
10732 mBroadcastsScheduled = false;
10733 }
10734
10735 // First, deliver any non-serialized broadcasts right away.
10736 while (mParallelBroadcasts.size() > 0) {
10737 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010738 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010739 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010740 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010741 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010742 for (int i=0; i<N; i++) {
10743 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010744 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010745 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010746 + target + ": " + r);
10747 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10748 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010749 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010750 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010751 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010752 }
10753
10754 // Now take care of the next serialized one...
10755
10756 // If we are waiting for a process to come up to handle the next
10757 // broadcast, then do nothing at this point. Just in case, we
10758 // check that the process we're waiting for still exists.
10759 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010760 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010761 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010762 + mPendingBroadcast.curApp);
10763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010764
10765 boolean isDead;
10766 synchronized (mPidsSelfLocked) {
10767 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10768 }
10769 if (!isDead) {
10770 // It's still alive, so keep waiting
10771 return;
10772 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010773 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010774 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010775 mPendingBroadcast.state = BroadcastRecord.IDLE;
10776 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010777 mPendingBroadcast = null;
10778 }
10779 }
10780
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010781 boolean looped = false;
10782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010783 do {
10784 if (mOrderedBroadcasts.size() == 0) {
10785 // No more broadcasts pending, so all done!
10786 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010787 if (looped) {
10788 // If we had finished the last ordered broadcast, then
10789 // make sure all processes have correct oom and sched
10790 // adjustments.
10791 updateOomAdjLocked();
10792 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010793 return;
10794 }
10795 r = mOrderedBroadcasts.get(0);
10796 boolean forceReceive = false;
10797
10798 // Ensure that even if something goes awry with the timeout
10799 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010800 // and continue to make progress.
10801 //
10802 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10803 // receivers don't get executed with with timeouts. They're intended for
10804 // one time heavy lifting after system upgrades and can take
10805 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010806 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010807 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010808 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010809 if ((numReceivers > 0) &&
10810 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010811 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010812 + " now=" + now
10813 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010814 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010815 + " intent=" + r.intent
10816 + " numReceivers=" + numReceivers
10817 + " nextReceiver=" + r.nextReceiver
10818 + " state=" + r.state);
10819 broadcastTimeout(); // forcibly finish this broadcast
10820 forceReceive = true;
10821 r.state = BroadcastRecord.IDLE;
10822 }
10823 }
10824
10825 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010826 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 "processNextBroadcast() called when not idle (state="
10828 + r.state + ")");
10829 return;
10830 }
10831
10832 if (r.receivers == null || r.nextReceiver >= numReceivers
10833 || r.resultAbort || forceReceive) {
10834 // No more receivers for this broadcast! Send the final
10835 // result if requested...
10836 if (r.resultTo != null) {
10837 try {
10838 if (DEBUG_BROADCAST) {
10839 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010840 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010841 + " seq=" + seq + " app=" + r.callerApp);
10842 }
10843 performReceive(r.callerApp, r.resultTo,
10844 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010845 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010846 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010847 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010848 }
10849 }
10850
Joe Onorato8a9b2202010-02-26 18:56:32 -080010851 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010852 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10853
Joe Onorato8a9b2202010-02-26 18:56:32 -080010854 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010855 + r);
10856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010857 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010858 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 mOrderedBroadcasts.remove(0);
10860 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010861 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010862 continue;
10863 }
10864 } while (r == null);
10865
10866 // Get the next receiver...
10867 int recIdx = r.nextReceiver++;
10868
10869 // Keep track of when this receiver started, and make sure there
10870 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010871 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010872 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010873 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010874
Joe Onorato8a9b2202010-02-26 18:56:32 -080010875 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010876 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010877 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010878 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010879 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010880 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010881 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882 }
10883
10884 Object nextReceiver = r.receivers.get(recIdx);
10885 if (nextReceiver instanceof BroadcastFilter) {
10886 // Simple case: this is a registered receiver who gets
10887 // a direct call.
10888 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010889 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010890 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 + filter + ": " + r);
10892 deliverToRegisteredReceiver(r, filter, r.ordered);
10893 if (r.receiver == null || !r.ordered) {
10894 // The receiver has already finished, so schedule to
10895 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010896 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10897 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 r.state = BroadcastRecord.IDLE;
10899 scheduleBroadcastsLocked();
10900 }
10901 return;
10902 }
10903
10904 // Hard case: need to instantiate the receiver, possibly
10905 // starting its application process to host it.
10906
10907 ResolveInfo info =
10908 (ResolveInfo)nextReceiver;
10909
10910 boolean skip = false;
10911 int perm = checkComponentPermission(info.activityInfo.permission,
10912 r.callingPid, r.callingUid,
10913 info.activityInfo.exported
10914 ? -1 : info.activityInfo.applicationInfo.uid);
10915 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010916 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 + r.intent.toString()
10918 + " from " + r.callerPackage + " (pid=" + r.callingPid
10919 + ", uid=" + r.callingUid + ")"
10920 + " requires " + info.activityInfo.permission
10921 + " due to receiver " + info.activityInfo.packageName
10922 + "/" + info.activityInfo.name);
10923 skip = true;
10924 }
10925 if (r.callingUid != Process.SYSTEM_UID &&
10926 r.requiredPermission != null) {
10927 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010928 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 checkPermission(r.requiredPermission,
10930 info.activityInfo.applicationInfo.packageName);
10931 } catch (RemoteException e) {
10932 perm = PackageManager.PERMISSION_DENIED;
10933 }
10934 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010935 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010936 + r.intent + " to "
10937 + info.activityInfo.applicationInfo.packageName
10938 + " requires " + r.requiredPermission
10939 + " due to sender " + r.callerPackage
10940 + " (uid " + r.callingUid + ")");
10941 skip = true;
10942 }
10943 }
10944 if (r.curApp != null && r.curApp.crashing) {
10945 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010946 if (DEBUG_BROADCAST) Slog.v(TAG,
10947 "Skipping deliver ordered " + r + " to " + r.curApp
10948 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010949 skip = true;
10950 }
10951
10952 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010953 if (DEBUG_BROADCAST) Slog.v(TAG,
10954 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010955 r.receiver = null;
10956 r.curFilter = null;
10957 r.state = BroadcastRecord.IDLE;
10958 scheduleBroadcastsLocked();
10959 return;
10960 }
10961
10962 r.state = BroadcastRecord.APP_RECEIVE;
10963 String targetProcess = info.activityInfo.processName;
10964 r.curComponent = new ComponentName(
10965 info.activityInfo.applicationInfo.packageName,
10966 info.activityInfo.name);
10967 r.curReceiver = info.activityInfo;
10968
10969 // Is this receiver's application already running?
10970 ProcessRecord app = getProcessRecordLocked(targetProcess,
10971 info.activityInfo.applicationInfo.uid);
10972 if (app != null && app.thread != null) {
10973 try {
10974 processCurBroadcastLocked(r, app);
10975 return;
10976 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010977 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010978 + r.curComponent, e);
10979 }
10980
10981 // If a dead object exception was thrown -- fall through to
10982 // restart the application.
10983 }
10984
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010985 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010986 if (DEBUG_BROADCAST) Slog.v(TAG,
10987 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010988 if ((r.curApp=startProcessLocked(targetProcess,
10989 info.activityInfo.applicationInfo, true,
10990 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010991 "broadcast", r.curComponent,
10992 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10993 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010994 // Ah, this recipient is unavailable. Finish it if necessary,
10995 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010996 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010997 + info.activityInfo.applicationInfo.packageName + "/"
10998 + info.activityInfo.applicationInfo.uid + " for broadcast "
10999 + r.intent + ": process is bad");
11000 logBroadcastReceiverDiscard(r);
11001 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11002 r.resultExtras, r.resultAbort, true);
11003 scheduleBroadcastsLocked();
11004 r.state = BroadcastRecord.IDLE;
11005 return;
11006 }
11007
11008 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011009 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011010 }
11011 }
11012
11013 // =========================================================
11014 // INSTRUMENTATION
11015 // =========================================================
11016
11017 public boolean startInstrumentation(ComponentName className,
11018 String profileFile, int flags, Bundle arguments,
11019 IInstrumentationWatcher watcher) {
11020 // Refuse possible leaked file descriptors
11021 if (arguments != null && arguments.hasFileDescriptors()) {
11022 throw new IllegalArgumentException("File descriptors passed in Bundle");
11023 }
11024
11025 synchronized(this) {
11026 InstrumentationInfo ii = null;
11027 ApplicationInfo ai = null;
11028 try {
11029 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011030 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011031 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011032 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011033 } catch (PackageManager.NameNotFoundException e) {
11034 }
11035 if (ii == null) {
11036 reportStartInstrumentationFailure(watcher, className,
11037 "Unable to find instrumentation info for: " + className);
11038 return false;
11039 }
11040 if (ai == null) {
11041 reportStartInstrumentationFailure(watcher, className,
11042 "Unable to find instrumentation target package: " + ii.targetPackage);
11043 return false;
11044 }
11045
11046 int match = mContext.getPackageManager().checkSignatures(
11047 ii.targetPackage, ii.packageName);
11048 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11049 String msg = "Permission Denial: starting instrumentation "
11050 + className + " from pid="
11051 + Binder.getCallingPid()
11052 + ", uid=" + Binder.getCallingPid()
11053 + " not allowed because package " + ii.packageName
11054 + " does not have a signature matching the target "
11055 + ii.targetPackage;
11056 reportStartInstrumentationFailure(watcher, className, msg);
11057 throw new SecurityException(msg);
11058 }
11059
11060 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011061 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011062 ProcessRecord app = addAppLocked(ai);
11063 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011064 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 app.instrumentationProfileFile = profileFile;
11066 app.instrumentationArguments = arguments;
11067 app.instrumentationWatcher = watcher;
11068 app.instrumentationResultClass = className;
11069 Binder.restoreCallingIdentity(origId);
11070 }
11071
11072 return true;
11073 }
11074
11075 /**
11076 * Report errors that occur while attempting to start Instrumentation. Always writes the
11077 * error to the logs, but if somebody is watching, send the report there too. This enables
11078 * the "am" command to report errors with more information.
11079 *
11080 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11081 * @param cn The component name of the instrumentation.
11082 * @param report The error report.
11083 */
11084 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11085 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011086 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087 try {
11088 if (watcher != null) {
11089 Bundle results = new Bundle();
11090 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11091 results.putString("Error", report);
11092 watcher.instrumentationStatus(cn, -1, results);
11093 }
11094 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011095 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011096 }
11097 }
11098
11099 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11100 if (app.instrumentationWatcher != null) {
11101 try {
11102 // NOTE: IInstrumentationWatcher *must* be oneway here
11103 app.instrumentationWatcher.instrumentationFinished(
11104 app.instrumentationClass,
11105 resultCode,
11106 results);
11107 } catch (RemoteException e) {
11108 }
11109 }
11110 app.instrumentationWatcher = null;
11111 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011112 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011113 app.instrumentationProfileFile = null;
11114 app.instrumentationArguments = null;
11115
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011116 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 }
11118
11119 public void finishInstrumentation(IApplicationThread target,
11120 int resultCode, Bundle results) {
11121 // Refuse possible leaked file descriptors
11122 if (results != null && results.hasFileDescriptors()) {
11123 throw new IllegalArgumentException("File descriptors passed in Intent");
11124 }
11125
11126 synchronized(this) {
11127 ProcessRecord app = getRecordForAppLocked(target);
11128 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011129 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011130 return;
11131 }
11132 final long origId = Binder.clearCallingIdentity();
11133 finishInstrumentationLocked(app, resultCode, results);
11134 Binder.restoreCallingIdentity(origId);
11135 }
11136 }
11137
11138 // =========================================================
11139 // CONFIGURATION
11140 // =========================================================
11141
11142 public ConfigurationInfo getDeviceConfigurationInfo() {
11143 ConfigurationInfo config = new ConfigurationInfo();
11144 synchronized (this) {
11145 config.reqTouchScreen = mConfiguration.touchscreen;
11146 config.reqKeyboardType = mConfiguration.keyboard;
11147 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011148 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11149 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011150 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11151 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011152 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11153 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11155 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011156 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011157 }
11158 return config;
11159 }
11160
11161 public Configuration getConfiguration() {
11162 Configuration ci;
11163 synchronized(this) {
11164 ci = new Configuration(mConfiguration);
11165 }
11166 return ci;
11167 }
11168
11169 public void updateConfiguration(Configuration values) {
11170 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11171 "updateConfiguration()");
11172
11173 synchronized(this) {
11174 if (values == null && mWindowManager != null) {
11175 // sentinel: fetch the current configuration from the window manager
11176 values = mWindowManager.computeNewConfiguration();
11177 }
11178
11179 final long origId = Binder.clearCallingIdentity();
11180 updateConfigurationLocked(values, null);
11181 Binder.restoreCallingIdentity(origId);
11182 }
11183 }
11184
11185 /**
11186 * Do either or both things: (1) change the current configuration, and (2)
11187 * make sure the given activity is running with the (now) current
11188 * configuration. Returns true if the activity has been left running, or
11189 * false if <var>starting</var> is being destroyed to match the new
11190 * configuration.
11191 */
11192 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011193 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 int changes = 0;
11195
11196 boolean kept = true;
11197
11198 if (values != null) {
11199 Configuration newConfig = new Configuration(mConfiguration);
11200 changes = newConfig.updateFrom(values);
11201 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011202 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011203 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 }
11205
Doug Zongker2bec3d42009-12-04 12:52:44 -080011206 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011207
11208 if (values.locale != null) {
11209 saveLocaleLocked(values.locale,
11210 !values.locale.equals(mConfiguration.locale),
11211 values.userSetLocale);
11212 }
11213
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011214 mConfigurationSeq++;
11215 if (mConfigurationSeq <= 0) {
11216 mConfigurationSeq = 1;
11217 }
11218 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011219 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011220 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011221
11222 AttributeCache ac = AttributeCache.instance();
11223 if (ac != null) {
11224 ac.updateConfiguration(mConfiguration);
11225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011226
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011227 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11228 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11229 msg.obj = new Configuration(mConfiguration);
11230 mHandler.sendMessage(msg);
11231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011232
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011233 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11234 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 try {
11236 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011237 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011238 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011239 app.thread.scheduleConfigurationChanged(mConfiguration);
11240 }
11241 } catch (Exception e) {
11242 }
11243 }
11244 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011245 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11246 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011247 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11248 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011249 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11250 broadcastIntentLocked(null, null,
11251 new Intent(Intent.ACTION_LOCALE_CHANGED),
11252 null, null, 0, null, null,
11253 null, false, false, MY_PID, Process.SYSTEM_UID);
11254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011255 }
11256 }
11257
11258 if (changes != 0 && starting == null) {
11259 // If the configuration changed, and the caller is not already
11260 // in the process of starting an activity, then find the top
11261 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011262 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 }
11264
11265 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011266 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 if (kept) {
11268 // If this didn't result in the starting activity being
11269 // destroyed, then we need to make sure at this point that all
11270 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011271 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011272 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011273 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 }
11275 }
11276
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011277 if (values != null && mWindowManager != null) {
11278 mWindowManager.setNewConfiguration(mConfiguration);
11279 }
11280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011281 return kept;
11282 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011283
11284 /**
11285 * Save the locale. You must be inside a synchronized (this) block.
11286 */
11287 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11288 if(isDiff) {
11289 SystemProperties.set("user.language", l.getLanguage());
11290 SystemProperties.set("user.region", l.getCountry());
11291 }
11292
11293 if(isPersist) {
11294 SystemProperties.set("persist.sys.language", l.getLanguage());
11295 SystemProperties.set("persist.sys.country", l.getCountry());
11296 SystemProperties.set("persist.sys.localevar", l.getVariant());
11297 }
11298 }
11299
11300 // =========================================================
11301 // LIFETIME MANAGEMENT
11302 // =========================================================
11303
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011304 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11305 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011306 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011307 // This adjustment has already been computed. If we are calling
11308 // from the top, we may have already computed our adjustment with
11309 // an earlier hidden adjustment that isn't really for us... if
11310 // so, use the new hidden adjustment.
11311 if (!recursed && app.hidden) {
11312 app.curAdj = hiddenAdj;
11313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011314 return app.curAdj;
11315 }
11316
11317 if (app.thread == null) {
11318 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011319 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011320 return (app.curAdj=EMPTY_APP_ADJ);
11321 }
11322
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011323 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11324 // The max adjustment doesn't allow this app to be anything
11325 // below foreground, so it is not worth doing work for it.
11326 app.adjType = "fixed";
11327 app.adjSeq = mAdjSeq;
11328 app.curRawAdj = app.maxAdj;
11329 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11330 return (app.curAdj=app.maxAdj);
11331 }
11332
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011333 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011334 app.adjSource = null;
11335 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011336 app.empty = false;
11337 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011338
The Android Open Source Project4df24232009-03-05 14:34:35 -080011339 // Determine the importance of the process, starting with most
11340 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011342 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011343 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011344 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011345 // The last app on the list is the foreground app.
11346 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011347 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011348 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011349 } else if (app.instrumentationClass != null) {
11350 // Don't want to kill running instrumentation.
11351 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011352 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011353 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011354 } else if (app.persistentActivities > 0) {
11355 // Special persistent activities... shouldn't be used these days.
11356 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011357 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011358 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011359 } else if (app.curReceiver != null ||
11360 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11361 // An app that is currently receiving a broadcast also
11362 // counts as being in the foreground.
11363 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011364 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011365 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011366 } else if (app.executingServices.size() > 0) {
11367 // An app that is currently executing a service callback also
11368 // counts as being in the foreground.
11369 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011370 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011371 app.adjType = "exec-service";
11372 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011373 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011374 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011375 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011376 app.adjType = "foreground-service";
11377 } else if (app.forcingToForeground != null) {
11378 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011379 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011380 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011381 app.adjType = "force-foreground";
11382 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011383 } else if (app == mHeavyWeightProcess) {
11384 // We don't want to kill the current heavy-weight process.
11385 adj = HEAVY_WEIGHT_APP_ADJ;
11386 schedGroup = Process.THREAD_GROUP_DEFAULT;
11387 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011388 } else if (app == mHomeProcess) {
11389 // This process is hosting what we currently consider to be the
11390 // home app, so we don't want to let it go into the background.
11391 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011392 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011393 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011394 } else if ((N=app.activities.size()) != 0) {
11395 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011396 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011397 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011398 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011399 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011400 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011401 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011402 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011403 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011404 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011405 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011406 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011407 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408 break;
11409 }
11410 }
11411 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011412 // A very not-needed process. If this is lower in the lru list,
11413 // we will push it in to the empty bucket.
11414 app.hidden = true;
11415 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011416 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011417 adj = hiddenAdj;
11418 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011419 }
11420
Joe Onorato8a9b2202010-02-26 18:56:32 -080011421 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011422
The Android Open Source Project4df24232009-03-05 14:34:35 -080011423 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011424 // there are applications dependent on our services or providers, but
11425 // this gives us a baseline and makes sure we don't get into an
11426 // infinite recursion.
11427 app.adjSeq = mAdjSeq;
11428 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011429
Christopher Tate6fa95972009-06-05 18:43:55 -070011430 if (mBackupTarget != null && app == mBackupTarget.app) {
11431 // If possible we want to avoid killing apps while they're being backed up
11432 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011433 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011434 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011435 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011436 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011437 }
11438 }
11439
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011440 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11441 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011442 final long now = SystemClock.uptimeMillis();
11443 // This process is more important if the top activity is
11444 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011445 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011446 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011447 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011448 if (s.startRequested) {
11449 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11450 // This service has seen some activity within
11451 // recent memory, so we will keep its process ahead
11452 // of the background processes.
11453 if (adj > SECONDARY_SERVER_ADJ) {
11454 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011455 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011456 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011457 }
11458 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011459 // If we have let the service slide into the background
11460 // state, still have some text describing what it is doing
11461 // even though the service no longer has an impact.
11462 if (adj > SECONDARY_SERVER_ADJ) {
11463 app.adjType = "started-bg-services";
11464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011465 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011466 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11467 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011468 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011469 = s.connections.values().iterator();
11470 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011471 ArrayList<ConnectionRecord> clist = kt.next();
11472 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11473 // XXX should compute this based on the max of
11474 // all connected clients.
11475 ConnectionRecord cr = clist.get(i);
11476 if (cr.binding.client == app) {
11477 // Binding to ourself is not interesting.
11478 continue;
11479 }
11480 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11481 ProcessRecord client = cr.binding.client;
11482 int myHiddenAdj = hiddenAdj;
11483 if (myHiddenAdj > client.hiddenAdj) {
11484 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11485 myHiddenAdj = client.hiddenAdj;
11486 } else {
11487 myHiddenAdj = VISIBLE_APP_ADJ;
11488 }
11489 }
11490 int clientAdj = computeOomAdjLocked(
11491 client, myHiddenAdj, TOP_APP, true);
11492 if (adj > clientAdj) {
11493 adj = clientAdj >= VISIBLE_APP_ADJ
11494 ? clientAdj : VISIBLE_APP_ADJ;
11495 if (!client.hidden) {
11496 app.hidden = false;
11497 }
11498 app.adjType = "service";
11499 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11500 .REASON_SERVICE_IN_USE;
11501 app.adjSource = cr.binding.client;
11502 app.adjTarget = s.name;
11503 }
11504 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11505 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11506 schedGroup = Process.THREAD_GROUP_DEFAULT;
11507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011508 }
11509 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011510 ActivityRecord a = cr.activity;
11511 //if (a != null) {
11512 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11513 //}
11514 if (a != null && adj > FOREGROUND_APP_ADJ &&
11515 (a.state == ActivityState.RESUMED
11516 || a.state == ActivityState.PAUSING)) {
11517 adj = FOREGROUND_APP_ADJ;
11518 schedGroup = Process.THREAD_GROUP_DEFAULT;
11519 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011520 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011521 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11522 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011523 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011524 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011525 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011526 }
11527 }
11528 }
11529 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011530
11531 // Finally, f this process has active services running in it, we
11532 // would like to avoid killing it unless it would prevent the current
11533 // application from running. By default we put the process in
11534 // with the rest of the background processes; as we scan through
11535 // its services we may bump it up from there.
11536 if (adj > hiddenAdj) {
11537 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011538 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011539 app.adjType = "bg-services";
11540 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541 }
11542
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011543 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11544 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011545 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011546 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11547 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011548 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011549 if (cpr.clients.size() != 0) {
11550 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11551 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11552 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011553 if (client == app) {
11554 // Being our own client is not interesting.
11555 continue;
11556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011557 int myHiddenAdj = hiddenAdj;
11558 if (myHiddenAdj > client.hiddenAdj) {
11559 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11560 myHiddenAdj = client.hiddenAdj;
11561 } else {
11562 myHiddenAdj = FOREGROUND_APP_ADJ;
11563 }
11564 }
11565 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011566 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011567 if (adj > clientAdj) {
11568 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011569 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011570 if (!client.hidden) {
11571 app.hidden = false;
11572 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011573 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011574 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11575 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011576 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011577 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011579 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11580 schedGroup = Process.THREAD_GROUP_DEFAULT;
11581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011582 }
11583 }
11584 // If the provider has external (non-framework) process
11585 // dependencies, ensure that its adjustment is at least
11586 // FOREGROUND_APP_ADJ.
11587 if (cpr.externals != 0) {
11588 if (adj > FOREGROUND_APP_ADJ) {
11589 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011590 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011591 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011592 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011593 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 }
11595 }
11596 }
11597 }
11598
11599 app.curRawAdj = adj;
11600
Joe Onorato8a9b2202010-02-26 18:56:32 -080011601 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011602 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11603 if (adj > app.maxAdj) {
11604 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011605 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011606 schedGroup = Process.THREAD_GROUP_DEFAULT;
11607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011608 }
11609
11610 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011611 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011613 return adj;
11614 }
11615
11616 /**
11617 * Ask a given process to GC right now.
11618 */
11619 final void performAppGcLocked(ProcessRecord app) {
11620 try {
11621 app.lastRequestedGc = SystemClock.uptimeMillis();
11622 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011623 if (app.reportLowMemory) {
11624 app.reportLowMemory = false;
11625 app.thread.scheduleLowMemory();
11626 } else {
11627 app.thread.processInBackground();
11628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011629 }
11630 } catch (Exception e) {
11631 // whatever.
11632 }
11633 }
11634
11635 /**
11636 * Returns true if things are idle enough to perform GCs.
11637 */
Josh Bartel7f208742010-02-25 11:01:44 -060011638 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011639 return mParallelBroadcasts.size() == 0
11640 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011641 && (mSleeping || (mMainStack.mResumedActivity != null &&
11642 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 }
11644
11645 /**
11646 * Perform GCs on all processes that are waiting for it, but only
11647 * if things are idle.
11648 */
11649 final void performAppGcsLocked() {
11650 final int N = mProcessesToGc.size();
11651 if (N <= 0) {
11652 return;
11653 }
Josh Bartel7f208742010-02-25 11:01:44 -060011654 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011655 while (mProcessesToGc.size() > 0) {
11656 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011657 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011658 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11659 <= SystemClock.uptimeMillis()) {
11660 // To avoid spamming the system, we will GC processes one
11661 // at a time, waiting a few seconds between each.
11662 performAppGcLocked(proc);
11663 scheduleAppGcsLocked();
11664 return;
11665 } else {
11666 // It hasn't been long enough since we last GCed this
11667 // process... put it in the list to wait for its time.
11668 addProcessToGcListLocked(proc);
11669 break;
11670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011671 }
11672 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011673
11674 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011675 }
11676 }
11677
11678 /**
11679 * If all looks good, perform GCs on all processes waiting for them.
11680 */
11681 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011682 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011683 performAppGcsLocked();
11684 return;
11685 }
11686 // Still not idle, wait some more.
11687 scheduleAppGcsLocked();
11688 }
11689
11690 /**
11691 * Schedule the execution of all pending app GCs.
11692 */
11693 final void scheduleAppGcsLocked() {
11694 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011695
11696 if (mProcessesToGc.size() > 0) {
11697 // Schedule a GC for the time to the next process.
11698 ProcessRecord proc = mProcessesToGc.get(0);
11699 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11700
11701 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11702 long now = SystemClock.uptimeMillis();
11703 if (when < (now+GC_TIMEOUT)) {
11704 when = now + GC_TIMEOUT;
11705 }
11706 mHandler.sendMessageAtTime(msg, when);
11707 }
11708 }
11709
11710 /**
11711 * Add a process to the array of processes waiting to be GCed. Keeps the
11712 * list in sorted order by the last GC time. The process can't already be
11713 * on the list.
11714 */
11715 final void addProcessToGcListLocked(ProcessRecord proc) {
11716 boolean added = false;
11717 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11718 if (mProcessesToGc.get(i).lastRequestedGc <
11719 proc.lastRequestedGc) {
11720 added = true;
11721 mProcessesToGc.add(i+1, proc);
11722 break;
11723 }
11724 }
11725 if (!added) {
11726 mProcessesToGc.add(0, proc);
11727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011728 }
11729
11730 /**
11731 * Set up to ask a process to GC itself. This will either do it
11732 * immediately, or put it on the list of processes to gc the next
11733 * time things are idle.
11734 */
11735 final void scheduleAppGcLocked(ProcessRecord app) {
11736 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011737 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011738 return;
11739 }
11740 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011741 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011742 scheduleAppGcsLocked();
11743 }
11744 }
11745
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011746 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11747 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11748 if (mLastWakeLockCheckTime == 0) {
11749 doKills = false;
11750 }
11751 if (stats.isScreenOn()) {
11752 doKills = false;
11753 }
11754 final long curRealtime = SystemClock.elapsedRealtime();
11755 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11756 mLastWakeLockCheckTime = curRealtime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011757 if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011758 doKills = false;
11759 }
11760 int i = mLruProcesses.size();
11761 while (i > 0) {
11762 i--;
11763 ProcessRecord app = mLruProcesses.get(i);
11764 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11765 long wtime;
11766 synchronized (stats) {
11767 wtime = stats.getProcessWakeTime(app.info.uid,
11768 app.pid, curRealtime);
11769 }
11770 long timeUsed = wtime - app.lastWakeTime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011771 if (false) {
11772 StringBuilder sb = new StringBuilder(128);
11773 sb.append("Wake for ");
11774 app.toShortString(sb);
11775 sb.append(": over ");
11776 TimeUtils.formatDuration(timeSince, sb);
11777 sb.append(" used ");
11778 TimeUtils.formatDuration(timeUsed, sb);
11779 sb.append(" (");
11780 sb.append((timeUsed*100)/timeSince);
11781 sb.append("%)");
11782 Slog.i(TAG, sb.toString());
11783 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011784 // If a process has held a wake lock for more
11785 // than 50% of the time during this period,
11786 // that sounds pad. Kill!
11787 if (doKills && timeSince > 0
11788 && ((timeUsed*100)/timeSince) >= 50) {
11789 Slog.i(TAG, "Excessive wake lock in " + app.processName
11790 + " (pid " + app.pid + "): held " + timeUsed
11791 + " during " + timeSince);
11792 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11793 app.processName, app.setAdj, "excessive wake lock");
11794 Process.killProcessQuiet(app.pid);
11795 } else {
11796 app.lastWakeTime = wtime;
11797 }
11798 }
11799 }
11800 }
11801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011802 private final boolean updateOomAdjLocked(
11803 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11804 app.hiddenAdj = hiddenAdj;
11805
11806 if (app.thread == null) {
11807 return true;
11808 }
11809
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011810 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011811
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011812 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011813 if (app.curRawAdj != app.setRawAdj) {
11814 if (app.curRawAdj > FOREGROUND_APP_ADJ
11815 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11816 // If this app is transitioning from foreground to
11817 // non-foreground, have it do a gc.
11818 scheduleAppGcLocked(app);
11819 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11820 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11821 // Likewise do a gc when an app is moving in to the
11822 // background (such as a service stopping).
11823 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011824 // And note its current wake lock time.
11825 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11826 synchronized (stats) {
11827 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11828 app.pid, SystemClock.elapsedRealtime());
11829 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011830 }
11831 app.setRawAdj = app.curRawAdj;
11832 }
11833 if (adj != app.setAdj) {
11834 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011835 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011836 TAG, "Set app " + app.processName +
11837 " oom adj to " + adj);
11838 app.setAdj = adj;
11839 } else {
11840 return false;
11841 }
11842 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011843 if (app.setSchedGroup != app.curSchedGroup) {
11844 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011845 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011846 "Setting process group of " + app.processName
11847 + " to " + app.curSchedGroup);
11848 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011849 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011850 try {
11851 Process.setProcessGroup(app.pid, app.curSchedGroup);
11852 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011853 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011854 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011855 e.printStackTrace();
11856 } finally {
11857 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011858 }
11859 }
11860 if (false) {
11861 if (app.thread != null) {
11862 try {
11863 app.thread.setSchedulingGroup(app.curSchedGroup);
11864 } catch (RemoteException e) {
11865 }
11866 }
11867 }
11868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011869 }
11870
11871 return true;
11872 }
11873
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011874 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011875 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011876 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011877 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011878 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011879 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011880 }
11881 }
11882 return resumedActivity;
11883 }
11884
11885 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011886 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011887 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11888 int curAdj = app.curAdj;
11889 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11890 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11891
11892 mAdjSeq++;
11893
11894 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11895 if (res) {
11896 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11897 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11898 if (nowHidden != wasHidden) {
11899 // Changed to/from hidden state, so apps after it in the LRU
11900 // list may also be changed.
11901 updateOomAdjLocked();
11902 }
11903 }
11904 return res;
11905 }
11906
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011907 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011908 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011909 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011910 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11911
11912 if (false) {
11913 RuntimeException e = new RuntimeException();
11914 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011915 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011916 }
11917
11918 mAdjSeq++;
11919
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011920 // Let's determine how many processes we have running vs.
11921 // how many slots we have for background processes; we may want
11922 // to put multiple processes in a slot of there are enough of
11923 // them.
11924 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11925 int factor = (mLruProcesses.size()-4)/numSlots;
11926 if (factor < 1) factor = 1;
11927 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011928 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011930 // First try updating the OOM adjustment for each of the
11931 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011932 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011933 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11934 while (i > 0) {
11935 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011936 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011937 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011938 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011939 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011940 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011941 step++;
11942 if (step >= factor) {
11943 step = 0;
11944 curHiddenAdj++;
11945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011946 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011947 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011948 if (!app.killedBackground) {
11949 numHidden++;
11950 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011951 Slog.i(TAG, "No longer want " + app.processName
11952 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011953 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11954 app.processName, app.setAdj, "too many background");
11955 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011956 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011957 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011958 }
11959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011960 } else {
11961 didOomAdj = false;
11962 }
11963 }
11964
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011965 // If we return false, we will fall back on killing processes to
11966 // have a fixed limit. Do this if a limit has been requested; else
11967 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011968 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11969 }
11970
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011971 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011972 synchronized (this) {
11973 int i;
11974
11975 // First remove any unused application processes whose package
11976 // has been removed.
11977 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11978 final ProcessRecord app = mRemovedProcesses.get(i);
11979 if (app.activities.size() == 0
11980 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011981 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011982 TAG, "Exiting empty application process "
11983 + app.processName + " ("
11984 + (app.thread != null ? app.thread.asBinder() : null)
11985 + ")\n");
11986 if (app.pid > 0 && app.pid != MY_PID) {
11987 Process.killProcess(app.pid);
11988 } else {
11989 try {
11990 app.thread.scheduleExit();
11991 } catch (Exception e) {
11992 // Ignore exceptions.
11993 }
11994 }
11995 cleanUpApplicationRecordLocked(app, false, -1);
11996 mRemovedProcesses.remove(i);
11997
11998 if (app.persistent) {
11999 if (app.persistent) {
12000 addAppLocked(app.info);
12001 }
12002 }
12003 }
12004 }
12005
12006 // Now try updating the OOM adjustment for each of the
12007 // application processes based on their current state.
12008 // If the setOomAdj() API is not supported, then go with our
12009 // back-up plan...
12010 if (!updateOomAdjLocked()) {
12011
12012 // Count how many processes are running services.
12013 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012014 for (i=mLruProcesses.size()-1; i>=0; i--) {
12015 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012016
12017 if (app.persistent || app.services.size() != 0
12018 || app.curReceiver != null
12019 || app.persistentActivities > 0) {
12020 // Don't count processes holding services against our
12021 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012022 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012023 TAG, "Not trimming app " + app + " with services: "
12024 + app.services);
12025 numServiceProcs++;
12026 }
12027 }
12028
12029 int curMaxProcs = mProcessLimit;
12030 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12031 if (mAlwaysFinishActivities) {
12032 curMaxProcs = 1;
12033 }
12034 curMaxProcs += numServiceProcs;
12035
12036 // Quit as many processes as we can to get down to the desired
12037 // process count. First remove any processes that no longer
12038 // have activites running in them.
12039 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012040 i<mLruProcesses.size()
12041 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012042 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012043 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012044 // Quit an application only if it is not currently
12045 // running any activities.
12046 if (!app.persistent && app.activities.size() == 0
12047 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012048 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012049 TAG, "Exiting empty application process "
12050 + app.processName + " ("
12051 + (app.thread != null ? app.thread.asBinder() : null)
12052 + ")\n");
12053 if (app.pid > 0 && app.pid != MY_PID) {
12054 Process.killProcess(app.pid);
12055 } else {
12056 try {
12057 app.thread.scheduleExit();
12058 } catch (Exception e) {
12059 // Ignore exceptions.
12060 }
12061 }
12062 // todo: For now we assume the application is not buggy
12063 // or evil, and will quit as a result of our request.
12064 // Eventually we need to drive this off of the death
12065 // notification, and kill the process if it takes too long.
12066 cleanUpApplicationRecordLocked(app, false, i);
12067 i--;
12068 }
12069 }
12070
12071 // If we still have too many processes, now from the least
12072 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012073 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012074 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012075 " of " + curMaxProcs + " processes");
12076 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012077 i<mLruProcesses.size()
12078 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012079 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012080 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012081 // Quit the application only if we have a state saved for
12082 // all of its activities.
12083 boolean canQuit = !app.persistent && app.curReceiver == null
12084 && app.services.size() == 0
12085 && app.persistentActivities == 0;
12086 int NUMA = app.activities.size();
12087 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012088 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089 TAG, "Looking to quit " + app.processName);
12090 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012091 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012092 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012093 TAG, " " + r.intent.getComponent().flattenToShortString()
12094 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12095 canQuit = (r.haveState || !r.stateNotNeeded)
12096 && !r.visible && r.stopped;
12097 }
12098 if (canQuit) {
12099 // Finish all of the activities, and then the app itself.
12100 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012101 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012102 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012103 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012104 }
12105 r.resultTo = null;
12106 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012107 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012108 + app.processName + " ("
12109 + (app.thread != null ? app.thread.asBinder() : null)
12110 + ")\n");
12111 if (app.pid > 0 && app.pid != MY_PID) {
12112 Process.killProcess(app.pid);
12113 } else {
12114 try {
12115 app.thread.scheduleExit();
12116 } catch (Exception e) {
12117 // Ignore exceptions.
12118 }
12119 }
12120 // todo: For now we assume the application is not buggy
12121 // or evil, and will quit as a result of our request.
12122 // Eventually we need to drive this off of the death
12123 // notification, and kill the process if it takes too long.
12124 cleanUpApplicationRecordLocked(app, false, i);
12125 i--;
12126 //dump();
12127 }
12128 }
12129
12130 }
12131
12132 int curMaxActivities = MAX_ACTIVITIES;
12133 if (mAlwaysFinishActivities) {
12134 curMaxActivities = 1;
12135 }
12136
12137 // Finally, if there are too many activities now running, try to
12138 // finish as many as we can to get back down to the limit.
12139 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012140 i<mMainStack.mLRUActivities.size()
12141 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012142 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012143 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012144 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012145
12146 // We can finish this one if we have its icicle saved and
12147 // it is not persistent.
12148 if ((r.haveState || !r.stateNotNeeded) && !r.visible
12149 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012150 final int origSize = mMainStack.mLRUActivities.size();
12151 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012152
12153 // This will remove it from the LRU list, so keep
12154 // our index at the same value. Note that this check to
12155 // see if the size changes is just paranoia -- if
12156 // something unexpected happens, we don't want to end up
12157 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012158 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012159 i--;
12160 }
12161 }
12162 }
12163 }
12164 }
12165
12166 /** This method sends the specified signal to each of the persistent apps */
12167 public void signalPersistentProcesses(int sig) throws RemoteException {
12168 if (sig != Process.SIGNAL_USR1) {
12169 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12170 }
12171
12172 synchronized (this) {
12173 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12174 != PackageManager.PERMISSION_GRANTED) {
12175 throw new SecurityException("Requires permission "
12176 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12177 }
12178
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012179 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12180 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012181 if (r.thread != null && r.persistent) {
12182 Process.sendSignal(r.pid, sig);
12183 }
12184 }
12185 }
12186 }
12187
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012188 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012189 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012190
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012191 try {
12192 synchronized (this) {
12193 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12194 // its own permission.
12195 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12196 != PackageManager.PERMISSION_GRANTED) {
12197 throw new SecurityException("Requires permission "
12198 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012199 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012200
12201 if (start && fd == null) {
12202 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012203 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012204
12205 ProcessRecord proc = null;
12206 try {
12207 int pid = Integer.parseInt(process);
12208 synchronized (mPidsSelfLocked) {
12209 proc = mPidsSelfLocked.get(pid);
12210 }
12211 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012212 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012213
12214 if (proc == null) {
12215 HashMap<String, SparseArray<ProcessRecord>> all
12216 = mProcessNames.getMap();
12217 SparseArray<ProcessRecord> procs = all.get(process);
12218 if (procs != null && procs.size() > 0) {
12219 proc = procs.valueAt(0);
12220 }
12221 }
12222
12223 if (proc == null || proc.thread == null) {
12224 throw new IllegalArgumentException("Unknown process: " + process);
12225 }
12226
12227 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12228 if (isSecure) {
12229 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12230 throw new SecurityException("Process not debuggable: " + proc);
12231 }
12232 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012233
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012234 proc.thread.profilerControl(start, path, fd);
12235 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012236 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012237 }
12238 } catch (RemoteException e) {
12239 throw new IllegalStateException("Process disappeared");
12240 } finally {
12241 if (fd != null) {
12242 try {
12243 fd.close();
12244 } catch (IOException e) {
12245 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012246 }
12247 }
12248 }
Andy McFadden824c5102010-07-09 16:26:57 -070012249
12250 public boolean dumpHeap(String process, boolean managed,
12251 String path, ParcelFileDescriptor fd) throws RemoteException {
12252
12253 try {
12254 synchronized (this) {
12255 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12256 // its own permission (same as profileControl).
12257 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12258 != PackageManager.PERMISSION_GRANTED) {
12259 throw new SecurityException("Requires permission "
12260 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12261 }
12262
12263 if (fd == null) {
12264 throw new IllegalArgumentException("null fd");
12265 }
12266
12267 ProcessRecord proc = null;
12268 try {
12269 int pid = Integer.parseInt(process);
12270 synchronized (mPidsSelfLocked) {
12271 proc = mPidsSelfLocked.get(pid);
12272 }
12273 } catch (NumberFormatException e) {
12274 }
12275
12276 if (proc == null) {
12277 HashMap<String, SparseArray<ProcessRecord>> all
12278 = mProcessNames.getMap();
12279 SparseArray<ProcessRecord> procs = all.get(process);
12280 if (procs != null && procs.size() > 0) {
12281 proc = procs.valueAt(0);
12282 }
12283 }
12284
12285 if (proc == null || proc.thread == null) {
12286 throw new IllegalArgumentException("Unknown process: " + process);
12287 }
12288
12289 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12290 if (isSecure) {
12291 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12292 throw new SecurityException("Process not debuggable: " + proc);
12293 }
12294 }
12295
12296 proc.thread.dumpHeap(managed, path, fd);
12297 fd = null;
12298 return true;
12299 }
12300 } catch (RemoteException e) {
12301 throw new IllegalStateException("Process disappeared");
12302 } finally {
12303 if (fd != null) {
12304 try {
12305 fd.close();
12306 } catch (IOException e) {
12307 }
12308 }
12309 }
12310 }
12311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012312 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12313 public void monitor() {
12314 synchronized (this) { }
12315 }
12316}