blob: ba8d7d2e33d6717eeca3b60310ff7f3384df6ae0 [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
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700116import java.io.BufferedInputStream;
117import java.io.BufferedOutputStream;
118import java.io.DataInputStream;
119import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.File;
121import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700122import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200125import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800126import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127import java.io.PrintWriter;
128import java.lang.IllegalStateException;
129import java.lang.ref.WeakReference;
130import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700131import java.util.Collections;
132import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133import java.util.HashMap;
134import java.util.HashSet;
135import java.util.Iterator;
136import java.util.List;
137import java.util.Locale;
138import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700139import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700140import java.util.concurrent.atomic.AtomicBoolean;
141import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700143public final class ActivityManagerService extends ActivityManagerNative
144 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final String TAG = "ActivityManager";
146 static final boolean DEBUG = false;
147 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
148 static final boolean DEBUG_SWITCH = localLOGV || false;
149 static final boolean DEBUG_TASKS = localLOGV || false;
150 static final boolean DEBUG_PAUSE = localLOGV || false;
151 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
152 static final boolean DEBUG_TRANSITION = localLOGV || false;
153 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700154 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700156 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean DEBUG_VISBILITY = localLOGV || false;
158 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700159 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800160 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700162 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700163 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700164 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700165 static final boolean DEBUG_POWER = localLOGV || false;
166 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 static final boolean VALIDATE_TOKENS = false;
168 static final boolean SHOW_ACTIVITY_START_TIME = true;
169
170 // Control over CPU and battery monitoring.
171 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
172 static final boolean MONITOR_CPU_USAGE = true;
173 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
174 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
175 static final boolean MONITOR_THREAD_CPU_USAGE = false;
176
Dianne Hackborn1655be42009-05-08 14:29:01 -0700177 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700178 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 private static final String SYSTEM_SECURE = "ro.secure";
181
182 // This is the maximum number of application processes we would like
183 // to have running. Due to the asynchronous nature of things, we can
184 // temporarily go beyond this limit.
185 static final int MAX_PROCESSES = 2;
186
187 // Set to false to leave processes running indefinitely, relying on
188 // the kernel killing them as resources are required.
189 static final boolean ENFORCE_PROCESS_LIMIT = false;
190
191 // This is the maximum number of activities that we would like to have
192 // running at a given time.
193 static final int MAX_ACTIVITIES = 20;
194
195 // Maximum number of recent tasks that we can remember.
196 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700197
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700198 // Amount of time after a call to stopAppSwitches() during which we will
199 // prevent further untrusted switches from happening.
200 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201
202 // How long we wait for a launched process to attach to the activity manager
203 // before we decide it's never going to come up for real.
204 static final int PROC_START_TIMEOUT = 10*1000;
205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 // How long to wait after going idle before forcing apps to GC.
207 static final int GC_TIMEOUT = 5*1000;
208
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700209 // The minimum amount of time between successive GC requests for a process.
210 static final int GC_MIN_INTERVAL = 60*1000;
211
Dianne Hackborn287952c2010-09-22 22:34:31 -0700212 // The rate at which we check for apps using excessive power -- 15 mins.
213 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
214
215 // The minimum sample duration we will allow before deciding we have
216 // enough data on wake locks to start killing things.
217 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
218
219 // The minimum sample duration we will allow before deciding we have
220 // enough data on CPU usage to start killing things.
221 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 // How long we allow a receiver to run before giving up on it.
224 static final int BROADCAST_TIMEOUT = 10*1000;
225
226 // How long we wait for a service to finish executing.
227 static final int SERVICE_TIMEOUT = 20*1000;
228
229 // How long a service needs to be running until restarting its process
230 // is no longer considered to be a relaunch of the service.
231 static final int SERVICE_RESTART_DURATION = 5*1000;
232
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700233 // How long a service needs to be running until it will start back at
234 // SERVICE_RESTART_DURATION after being killed.
235 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
236
237 // Multiplying factor to increase restart duration time by, for each time
238 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
239 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
240
241 // The minimum amount of time between restarting services that we allow.
242 // That is, when multiple services are restarting, we won't allow each
243 // to restart less than this amount of time from the last one.
244 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 // Maximum amount of time for there to be no activity on a service before
247 // we consider it non-essential and allow its process to go on the
248 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700249 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250
251 // How long we wait until we timeout on key dispatching.
252 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
253
254 // The minimum time we allow between crashes, for us to consider this
255 // application to be bad and stop and its services and reject broadcasts.
256 static final int MIN_CRASH_INTERVAL = 60*1000;
257
258 // How long we wait until we timeout on key dispatching during instrumentation.
259 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
260
261 // OOM adjustments for processes in various states:
262
263 // This is a process without anything currently running in it. Definitely
264 // the first to go! Value set in system/rootdir/init.rc on startup.
265 // This value is initalized in the constructor, careful when refering to
266 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800267 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268
269 // This is a process only hosting activities that are not visible,
270 // so it can be killed without any disruption. Value set in
271 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800272 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 static int HIDDEN_APP_MIN_ADJ;
274
The Android Open Source Project4df24232009-03-05 14:34:35 -0800275 // This is a process holding the home application -- we want to try
276 // avoiding killing it, even if it would normally be in the background,
277 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800278 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800279
Christopher Tate6fa95972009-06-05 18:43:55 -0700280 // This is a process currently hosting a backup operation. Killing it
281 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 // This is a process holding a secondary server -- killing it will not
285 // have much of an impact as far as the user is concerned. Value set in
286 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700289 // This is a process with a heavy-weight application. It is in the
290 // background, but we want to try to avoid killing it. Value set in
291 // system/rootdir/init.rc on startup.
292 static final int HEAVY_WEIGHT_APP_ADJ;
293
294 // This is a process only hosting components that are perceptible to the
295 // user, and we really want to avoid killing them, but they are not
296 // immediately visible. An example is background music playback. Value set in
297 // system/rootdir/init.rc on startup.
298 static final int PERCEPTIBLE_APP_ADJ;
299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 // This is a process only hosting activities that are visible to the
301 // user, so we'd prefer they don't disappear. Value set in
302 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800303 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304
305 // This is the process running the current foreground app. We'd really
306 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800307 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308
309 // This is a process running a core server, such as telephony. Definitely
310 // don't want to kill it, but doing so is not completely fatal.
311 static final int CORE_SERVER_ADJ = -12;
312
313 // The system process runs at the default adjustment.
314 static final int SYSTEM_ADJ = -16;
315
316 // Memory pages are 4K.
317 static final int PAGE_SIZE = 4*1024;
318
319 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800320 static final int EMPTY_APP_MEM;
321 static final int HIDDEN_APP_MEM;
322 static final int HOME_APP_MEM;
323 static final int BACKUP_APP_MEM;
324 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700325 static final int HEAVY_WEIGHT_APP_MEM;
326 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800327 static final int VISIBLE_APP_MEM;
328 static final int FOREGROUND_APP_MEM;
329
330 // The minimum number of hidden apps we want to be able to keep around,
331 // without empty apps being able to push them out of memory.
332 static final int MIN_HIDDEN_APPS = 2;
333
Dianne Hackborn8633e682010-04-22 16:03:41 -0700334 // The maximum number of hidden processes we will keep around before
335 // killing them; this is just a control to not let us go too crazy with
336 // keeping around processes on devices with large amounts of RAM.
337 static final int MAX_HIDDEN_APPS = 15;
338
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800339 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700340 // been idle for less than 15 seconds.
341 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800342
343 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700344 // been idle for less than 120 seconds.
345 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800346
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700347 static int getIntProp(String name, boolean allowZero) {
348 String str = SystemProperties.get(name);
349 if (str == null) {
350 throw new IllegalArgumentException("Property not defined: " + name);
351 }
352 int val = Integer.valueOf(str);
353 if (val == 0 && !allowZero) {
354 throw new IllegalArgumentException("Property must not be zero: " + name);
355 }
356 return val;
357 }
358
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800359 static {
360 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700361 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
362 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
363 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
364 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
365 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
366 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
367 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
368 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
369 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
370 // These days we use the last empty slot for hidden apps as well.
371 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
372 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
373 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
374 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
375 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
376 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
377 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
378 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
379 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
380 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382
Dan Egnor42471dd2010-01-07 17:25:22 -0800383 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384
385 static final String[] EMPTY_STRING_ARRAY = new String[0];
386
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700387 public ActivityStack mMainStack;
388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700390 * Description of a request to start a new activity, which has been held
391 * due to app switches being disabled.
392 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700393 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700394 ActivityRecord r;
395 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700396 Uri[] grantedUriPermissions;
397 int grantedMode;
398 boolean onlyIfNeeded;
399 }
400
401 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
402 = new ArrayList<PendingActivityLaunch>();
403
404 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 * List of all active broadcasts that are to be executed immediately
406 * (without waiting for another broadcast to finish). Currently this only
407 * contains broadcasts to registered receivers, to avoid spinning up
408 * a bunch of processes to execute IntentReceiver components.
409 */
410 final ArrayList<BroadcastRecord> mParallelBroadcasts
411 = new ArrayList<BroadcastRecord>();
412
413 /**
414 * List of all active broadcasts that are to be executed one at a time.
415 * The object at the top of the list is the currently activity broadcasts;
416 * those after it are waiting for the top to finish..
417 */
418 final ArrayList<BroadcastRecord> mOrderedBroadcasts
419 = new ArrayList<BroadcastRecord>();
420
421 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800422 * Historical data of past broadcasts, for debugging.
423 */
424 static final int MAX_BROADCAST_HISTORY = 100;
425 final BroadcastRecord[] mBroadcastHistory
426 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
427
428 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 * Set when we current have a BROADCAST_INTENT_MSG in flight.
430 */
431 boolean mBroadcastsScheduled = false;
432
433 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 * Activity we have told the window manager to have key focus.
435 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700436 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * List of intents that were used to start the most recent tasks.
439 */
440 final ArrayList<TaskRecord> mRecentTasks
441 = new ArrayList<TaskRecord>();
442
443 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 * All of the applications we currently have running organized by name.
445 * The keys are strings of the application package name (as
446 * returned by the package manager), and the keys are ApplicationRecord
447 * objects.
448 */
449 final ProcessMap<ProcessRecord> mProcessNames
450 = new ProcessMap<ProcessRecord>();
451
452 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700453 * The currently running heavy-weight process, if any.
454 */
455 ProcessRecord mHeavyWeightProcess = null;
456
457 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 * The last time that various processes have crashed.
459 */
460 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
461
462 /**
463 * Set of applications that we consider to be bad, and will reject
464 * incoming broadcasts from (which the user has no control over).
465 * Processes are added to this set when they have crashed twice within
466 * a minimum amount of time; they are removed from it when they are
467 * later restarted (hopefully due to some user action). The value is the
468 * time it was added to the list.
469 */
470 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
471
472 /**
473 * All of the processes we currently have running organized by pid.
474 * The keys are the pid running the application.
475 *
476 * <p>NOTE: This object is protected by its own lock, NOT the global
477 * activity manager lock!
478 */
479 final SparseArray<ProcessRecord> mPidsSelfLocked
480 = new SparseArray<ProcessRecord>();
481
482 /**
483 * All of the processes that have been forced to be foreground. The key
484 * is the pid of the caller who requested it (we hold a death
485 * link on it).
486 */
487 abstract class ForegroundToken implements IBinder.DeathRecipient {
488 int pid;
489 IBinder token;
490 }
491 final SparseArray<ForegroundToken> mForegroundProcesses
492 = new SparseArray<ForegroundToken>();
493
494 /**
495 * List of records for processes that someone had tried to start before the
496 * system was ready. We don't start them at that point, but ensure they
497 * are started by the time booting is complete.
498 */
499 final ArrayList<ProcessRecord> mProcessesOnHold
500 = new ArrayList<ProcessRecord>();
501
502 /**
503 * List of records for processes that we have started and are waiting
504 * for them to call back. This is really only needed when running in
505 * single processes mode, in which case we do not have a unique pid for
506 * each process.
507 */
508 final ArrayList<ProcessRecord> mStartingProcesses
509 = new ArrayList<ProcessRecord>();
510
511 /**
512 * List of persistent applications that are in the process
513 * of being started.
514 */
515 final ArrayList<ProcessRecord> mPersistentStartingProcesses
516 = new ArrayList<ProcessRecord>();
517
518 /**
519 * Processes that are being forcibly torn down.
520 */
521 final ArrayList<ProcessRecord> mRemovedProcesses
522 = new ArrayList<ProcessRecord>();
523
524 /**
525 * List of running applications, sorted by recent usage.
526 * The first entry in the list is the least recently used.
527 * It contains ApplicationRecord objects. This list does NOT include
528 * any persistent application records (since we never want to exit them).
529 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800530 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 = new ArrayList<ProcessRecord>();
532
533 /**
534 * List of processes that should gc as soon as things are idle.
535 */
536 final ArrayList<ProcessRecord> mProcessesToGc
537 = new ArrayList<ProcessRecord>();
538
539 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800540 * This is the process holding what we currently consider to be
541 * the "home" activity.
542 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700543 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800544
545 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 * Set of PendingResultRecord objects that are currently active.
547 */
548 final HashSet mPendingResultRecords = new HashSet();
549
550 /**
551 * Set of IntentSenderRecord objects that are currently active.
552 */
553 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
554 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
555
556 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700557 * Fingerprints (String.hashCode()) of stack traces that we've
558 * already logged DropBox entries for. Guarded by itself. If
559 * something (rogue user app) forces this over
560 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
561 */
562 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
563 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
564
565 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700566 * Strict Mode background batched logging state.
567 *
568 * The string buffer is guarded by itself, and its lock is also
569 * used to determine if another batched write is already
570 * in-flight.
571 */
572 private final StringBuilder mStrictModeBuffer = new StringBuilder();
573
574 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700575 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
576 */
577 private boolean mPendingBroadcastTimeoutMessage;
578
579 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 * Intent broadcast that we have tried to start, but are
581 * waiting for its application's process to be created. We only
582 * need one (instead of a list) because we always process broadcasts
583 * one at a time, so no others can be started while waiting for this
584 * one.
585 */
586 BroadcastRecord mPendingBroadcast = null;
587
588 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700589 * The receiver index that is pending, to restart the broadcast if needed.
590 */
591 int mPendingBroadcastRecvIndex;
592
593 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 * Keeps track of all IIntentReceivers that have been registered for
595 * broadcasts. Hash keys are the receiver IBinder, hash value is
596 * a ReceiverList.
597 */
598 final HashMap mRegisteredReceivers = new HashMap();
599
600 /**
601 * Resolver for broadcast intents to registered receivers.
602 * Holds BroadcastFilter (subclass of IntentFilter).
603 */
604 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
605 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
606 @Override
607 protected boolean allowFilterResult(
608 BroadcastFilter filter, List<BroadcastFilter> dest) {
609 IBinder target = filter.receiverList.receiver.asBinder();
610 for (int i=dest.size()-1; i>=0; i--) {
611 if (dest.get(i).receiverList.receiver.asBinder() == target) {
612 return false;
613 }
614 }
615 return true;
616 }
617 };
618
619 /**
620 * State of all active sticky broadcasts. Keys are the action of the
621 * sticky Intent, values are an ArrayList of all broadcasted intents with
622 * that action (which should usually be one).
623 */
624 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
625 new HashMap<String, ArrayList<Intent>>();
626
627 /**
628 * All currently running services.
629 */
630 final HashMap<ComponentName, ServiceRecord> mServices =
631 new HashMap<ComponentName, ServiceRecord>();
632
633 /**
634 * All currently running services indexed by the Intent used to start them.
635 */
636 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
637 new HashMap<Intent.FilterComparison, ServiceRecord>();
638
639 /**
640 * All currently bound service connections. Keys are the IBinder of
641 * the client's IServiceConnection.
642 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700643 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
644 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645
646 /**
647 * List of services that we have been asked to start,
648 * but haven't yet been able to. It is used to hold start requests
649 * while waiting for their corresponding application thread to get
650 * going.
651 */
652 final ArrayList<ServiceRecord> mPendingServices
653 = new ArrayList<ServiceRecord>();
654
655 /**
656 * List of services that are scheduled to restart following a crash.
657 */
658 final ArrayList<ServiceRecord> mRestartingServices
659 = new ArrayList<ServiceRecord>();
660
661 /**
662 * List of services that are in the process of being stopped.
663 */
664 final ArrayList<ServiceRecord> mStoppingServices
665 = new ArrayList<ServiceRecord>();
666
667 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700668 * Backup/restore process management
669 */
670 String mBackupAppName = null;
671 BackupRecord mBackupTarget = null;
672
673 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 * List of PendingThumbnailsRecord objects of clients who are still
675 * waiting to receive all of the thumbnails for a task.
676 */
677 final ArrayList mPendingThumbnails = new ArrayList();
678
679 /**
680 * List of HistoryRecord objects that have been finished and must
681 * still report back to a pending thumbnail receiver.
682 */
683 final ArrayList mCancelledThumbnails = new ArrayList();
684
685 /**
686 * All of the currently running global content providers. Keys are a
687 * string containing the provider name and values are a
688 * ContentProviderRecord object containing the data about it. Note
689 * that a single provider may be published under multiple names, so
690 * there may be multiple entries here for a single one in mProvidersByClass.
691 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700692 final HashMap<String, ContentProviderRecord> mProvidersByName
693 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694
695 /**
696 * All of the currently running global content providers. Keys are a
697 * string containing the provider's implementation class and values are a
698 * ContentProviderRecord object containing the data about it.
699 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700700 final HashMap<String, ContentProviderRecord> mProvidersByClass
701 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702
703 /**
704 * List of content providers who have clients waiting for them. The
705 * application is currently being launched and the provider will be
706 * removed from this list once it is published.
707 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700708 final ArrayList<ContentProviderRecord> mLaunchingProviders
709 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710
711 /**
712 * Global set of specific Uri permissions that have been granted.
713 */
714 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
715 = new SparseArray<HashMap<Uri, UriPermission>>();
716
717 /**
718 * Thread-local storage used to carry caller permissions over through
719 * indirect content-provider access.
720 * @see #ActivityManagerService.openContentUri()
721 */
722 private class Identity {
723 public int pid;
724 public int uid;
725
726 Identity(int _pid, int _uid) {
727 pid = _pid;
728 uid = _uid;
729 }
730 }
731 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
732
733 /**
734 * All information we have collected about the runtime performance of
735 * any user id that can impact battery performance.
736 */
737 final BatteryStatsService mBatteryStatsService;
738
739 /**
740 * information about component usage
741 */
742 final UsageStatsService mUsageStatsService;
743
744 /**
745 * Current configuration information. HistoryRecord objects are given
746 * a reference to this object to indicate which configuration they are
747 * currently running in, so this object must be kept immutable.
748 */
749 Configuration mConfiguration = new Configuration();
750
751 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800752 * Current sequencing integer of the configuration, for skipping old
753 * configurations.
754 */
755 int mConfigurationSeq = 0;
756
757 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700758 * Hardware-reported OpenGLES version.
759 */
760 final int GL_ES_VERSION;
761
762 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 * List of initialization arguments to pass to all processes when binding applications to them.
764 * For example, references to the commonly used services.
765 */
766 HashMap<String, IBinder> mAppBindArgs;
767
768 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700769 * Temporary to avoid allocations. Protected by main lock.
770 */
771 final StringBuilder mStringBuilder = new StringBuilder(256);
772
773 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 * Used to control how we initialize the service.
775 */
776 boolean mStartRunning = false;
777 ComponentName mTopComponent;
778 String mTopAction;
779 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700780 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 boolean mSystemReady = false;
782 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700783 boolean mWaitingUpdate = false;
784 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700785 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700786 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787
788 Context mContext;
789
790 int mFactoryTest;
791
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700792 boolean mCheckedForSetup;
793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700795 * The time at which we will allow normal application switches again,
796 * after a call to {@link #stopAppSwitches()}.
797 */
798 long mAppSwitchesAllowedTime;
799
800 /**
801 * This is set to true after the first switch after mAppSwitchesAllowedTime
802 * is set; any switches after that will clear the time.
803 */
804 boolean mDidAppSwitch;
805
806 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700807 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700808 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700809 long mLastPowerCheckRealtime;
810
811 /**
812 * Last time (in uptime) at which we checked for power usage.
813 */
814 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700815
816 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 * Set while we are wanting to sleep, to prevent any
818 * activities from being started/resumed.
819 */
820 boolean mSleeping = false;
821
822 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700823 * Set if we are shutting down the system, similar to sleeping.
824 */
825 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826
827 /**
828 * Task identifier that activities are currently being started
829 * in. Incremented each time a new task is created.
830 * todo: Replace this with a TokenSpace class that generates non-repeating
831 * integers that won't wrap.
832 */
833 int mCurTask = 1;
834
835 /**
836 * Current sequence id for oom_adj computation traversal.
837 */
838 int mAdjSeq = 0;
839
840 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700841 * Current sequence id for process LRU updating.
842 */
843 int mLruSeq = 0;
844
845 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
847 * is set, indicating the user wants processes started in such a way
848 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
849 * running in each process (thus no pre-initialized process, etc).
850 */
851 boolean mSimpleProcessManagement = false;
852
853 /**
854 * System monitoring: number of processes that died since the last
855 * N procs were started.
856 */
857 int[] mProcDeaths = new int[20];
858
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700859 /**
860 * This is set if we had to do a delayed dexopt of an app before launching
861 * it, to increasing the ANR timeouts in that case.
862 */
863 boolean mDidDexOpt;
864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 String mDebugApp = null;
866 boolean mWaitForDebugger = false;
867 boolean mDebugTransient = false;
868 String mOrigDebugApp = null;
869 boolean mOrigWaitForDebugger = false;
870 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700871 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700873 final RemoteCallbackList<IActivityWatcher> mWatchers
874 = new RemoteCallbackList<IActivityWatcher>();
875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 /**
877 * Callback of last caller to {@link #requestPss}.
878 */
879 Runnable mRequestPssCallback;
880
881 /**
882 * Remaining processes for which we are waiting results from the last
883 * call to {@link #requestPss}.
884 */
885 final ArrayList<ProcessRecord> mRequestPssList
886 = new ArrayList<ProcessRecord>();
887
888 /**
889 * Runtime statistics collection thread. This object's lock is used to
890 * protect all related state.
891 */
892 final Thread mProcessStatsThread;
893
894 /**
895 * Used to collect process stats when showing not responding dialog.
896 * Protected by mProcessStatsThread.
897 */
898 final ProcessStats mProcessStats = new ProcessStats(
899 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700900 final AtomicLong mLastCpuTime = new AtomicLong(0);
901 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 long mLastWriteTime = 0;
904
905 /**
906 * Set to true after the system has finished booting.
907 */
908 boolean mBooted = false;
909
910 int mProcessLimit = 0;
911
912 WindowManagerService mWindowManager;
913
914 static ActivityManagerService mSelf;
915 static ActivityThread mSystemThread;
916
917 private final class AppDeathRecipient implements IBinder.DeathRecipient {
918 final ProcessRecord mApp;
919 final int mPid;
920 final IApplicationThread mAppThread;
921
922 AppDeathRecipient(ProcessRecord app, int pid,
923 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800924 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 TAG, "New death recipient " + this
926 + " for thread " + thread.asBinder());
927 mApp = app;
928 mPid = pid;
929 mAppThread = thread;
930 }
931
932 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800933 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 TAG, "Death received in " + this
935 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 synchronized(ActivityManagerService.this) {
937 appDiedLocked(mApp, mPid, mAppThread);
938 }
939 }
940 }
941
942 static final int SHOW_ERROR_MSG = 1;
943 static final int SHOW_NOT_RESPONDING_MSG = 2;
944 static final int SHOW_FACTORY_ERROR_MSG = 3;
945 static final int UPDATE_CONFIGURATION_MSG = 4;
946 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
947 static final int WAIT_FOR_DEBUGGER_MSG = 6;
948 static final int BROADCAST_INTENT_MSG = 7;
949 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 static final int SERVICE_TIMEOUT_MSG = 12;
951 static final int UPDATE_TIME_ZONE = 13;
952 static final int SHOW_UID_ERROR_MSG = 14;
953 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700955 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700956 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800957 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700958 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
959 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700960 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700961 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700962 static final int CLEAR_DNS_CACHE = 28;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963
964 AlertDialog mUidAlert;
965
966 final Handler mHandler = new Handler() {
967 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800968 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969 //}
970
971 public void handleMessage(Message msg) {
972 switch (msg.what) {
973 case SHOW_ERROR_MSG: {
974 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 synchronized (ActivityManagerService.this) {
976 ProcessRecord proc = (ProcessRecord)data.get("app");
977 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800978 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 return;
980 }
981 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700982 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800983 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 d.show();
985 proc.crashDialog = d;
986 } else {
987 // The device is asleep, so just pretend that the user
988 // saw a crash dialog and hit "force quit".
989 res.set(0);
990 }
991 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700992
993 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 } break;
995 case SHOW_NOT_RESPONDING_MSG: {
996 synchronized (ActivityManagerService.this) {
997 HashMap data = (HashMap) msg.obj;
998 ProcessRecord proc = (ProcessRecord)data.get("app");
999 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001000 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 return;
1002 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001003
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001004 Intent intent = new Intent("android.intent.action.ANR");
1005 if (!mProcessesReady) {
1006 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1007 }
1008 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001009 null, null, 0, null, null, null,
1010 false, false, MY_PID, Process.SYSTEM_UID);
1011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001013 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 d.show();
1015 proc.anrDialog = d;
1016 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001017
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001018 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001020 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1021 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1022 synchronized (ActivityManagerService.this) {
1023 ProcessRecord proc = (ProcessRecord) data.get("app");
1024 if (proc == null) {
1025 Slog.e(TAG, "App not found when showing strict mode dialog.");
1026 break;
1027 }
1028 if (proc.crashDialog != null) {
1029 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1030 return;
1031 }
1032 AppErrorResult res = (AppErrorResult) data.get("result");
1033 if (!mSleeping && !mShuttingDown) {
1034 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1035 d.show();
1036 proc.crashDialog = d;
1037 } else {
1038 // The device is asleep, so just pretend that the user
1039 // saw a crash dialog and hit "force quit".
1040 res.set(0);
1041 }
1042 }
1043 ensureBootCompleted();
1044 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 case SHOW_FACTORY_ERROR_MSG: {
1046 Dialog d = new FactoryErrorDialog(
1047 mContext, msg.getData().getCharSequence("msg"));
1048 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001049 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 } break;
1051 case UPDATE_CONFIGURATION_MSG: {
1052 final ContentResolver resolver = mContext.getContentResolver();
1053 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1054 } break;
1055 case GC_BACKGROUND_PROCESSES_MSG: {
1056 synchronized (ActivityManagerService.this) {
1057 performAppGcsIfAppropriateLocked();
1058 }
1059 } break;
1060 case WAIT_FOR_DEBUGGER_MSG: {
1061 synchronized (ActivityManagerService.this) {
1062 ProcessRecord app = (ProcessRecord)msg.obj;
1063 if (msg.arg1 != 0) {
1064 if (!app.waitedForDebugger) {
1065 Dialog d = new AppWaitingForDebuggerDialog(
1066 ActivityManagerService.this,
1067 mContext, app);
1068 app.waitDialog = d;
1069 app.waitedForDebugger = true;
1070 d.show();
1071 }
1072 } else {
1073 if (app.waitDialog != null) {
1074 app.waitDialog.dismiss();
1075 app.waitDialog = null;
1076 }
1077 }
1078 }
1079 } break;
1080 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001081 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 TAG, "Received BROADCAST_INTENT_MSG");
1083 processNextBroadcast(true);
1084 } break;
1085 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001086 synchronized (ActivityManagerService.this) {
1087 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001091 if (mDidDexOpt) {
1092 mDidDexOpt = false;
1093 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1094 nmsg.obj = msg.obj;
1095 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1096 return;
1097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 serviceTimeout((ProcessRecord)msg.obj);
1099 } break;
1100 case UPDATE_TIME_ZONE: {
1101 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001102 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1103 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 if (r.thread != null) {
1105 try {
1106 r.thread.updateTimeZone();
1107 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001108 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 }
1110 }
1111 }
1112 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001113 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001114 case CLEAR_DNS_CACHE: {
1115 synchronized (ActivityManagerService.this) {
1116 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1117 ProcessRecord r = mLruProcesses.get(i);
1118 if (r.thread != null) {
1119 try {
1120 r.thread.clearDnsCache();
1121 } catch (RemoteException ex) {
1122 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1123 }
1124 }
1125 }
1126 }
1127 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 case SHOW_UID_ERROR_MSG: {
1129 // XXX This is a temporary dialog, no need to localize.
1130 AlertDialog d = new BaseErrorDialog(mContext);
1131 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1132 d.setCancelable(false);
1133 d.setTitle("System UIDs Inconsistent");
1134 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 +02001135 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1137 mUidAlert = d;
1138 d.show();
1139 } break;
1140 case IM_FEELING_LUCKY_MSG: {
1141 if (mUidAlert != null) {
1142 mUidAlert.dismiss();
1143 mUidAlert = null;
1144 }
1145 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001147 if (mDidDexOpt) {
1148 mDidDexOpt = false;
1149 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1150 nmsg.obj = msg.obj;
1151 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1152 return;
1153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 ProcessRecord app = (ProcessRecord)msg.obj;
1155 synchronized (ActivityManagerService.this) {
1156 processStartTimedOutLocked(app);
1157 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001158 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001159 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1160 synchronized (ActivityManagerService.this) {
1161 doPendingActivityLaunchesLocked(true);
1162 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001163 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001164 case KILL_APPLICATION_MSG: {
1165 synchronized (ActivityManagerService.this) {
1166 int uid = msg.arg1;
1167 boolean restart = (msg.arg2 == 1);
1168 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001169 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001170 }
1171 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001172 case FINALIZE_PENDING_INTENT_MSG: {
1173 ((PendingIntentRecord)msg.obj).completeFinalize();
1174 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001175 case POST_HEAVY_NOTIFICATION_MSG: {
1176 INotificationManager inm = NotificationManager.getService();
1177 if (inm == null) {
1178 return;
1179 }
1180
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001181 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001182 ProcessRecord process = root.app;
1183 if (process == null) {
1184 return;
1185 }
1186
1187 try {
1188 Context context = mContext.createPackageContext(process.info.packageName, 0);
1189 String text = mContext.getString(R.string.heavy_weight_notification,
1190 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1191 Notification notification = new Notification();
1192 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1193 notification.when = 0;
1194 notification.flags = Notification.FLAG_ONGOING_EVENT;
1195 notification.tickerText = text;
1196 notification.defaults = 0; // please be quiet
1197 notification.sound = null;
1198 notification.vibrate = null;
1199 notification.setLatestEventInfo(context, text,
1200 mContext.getText(R.string.heavy_weight_notification_detail),
1201 PendingIntent.getActivity(mContext, 0, root.intent,
1202 PendingIntent.FLAG_CANCEL_CURRENT));
1203
1204 try {
1205 int[] outId = new int[1];
1206 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1207 notification, outId);
1208 } catch (RuntimeException e) {
1209 Slog.w(ActivityManagerService.TAG,
1210 "Error showing notification for heavy-weight app", e);
1211 } catch (RemoteException e) {
1212 }
1213 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001214 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001215 }
1216 } break;
1217 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1218 INotificationManager inm = NotificationManager.getService();
1219 if (inm == null) {
1220 return;
1221 }
1222 try {
1223 inm.cancelNotification("android",
1224 R.string.heavy_weight_notification);
1225 } catch (RuntimeException e) {
1226 Slog.w(ActivityManagerService.TAG,
1227 "Error canceling notification for service", e);
1228 } catch (RemoteException e) {
1229 }
1230 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001231 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1232 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001233 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001234 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001235 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1236 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001237 }
1238 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 }
1240 }
1241 };
1242
1243 public static void setSystemProcess() {
1244 try {
1245 ActivityManagerService m = mSelf;
1246
1247 ServiceManager.addService("activity", m);
1248 ServiceManager.addService("meminfo", new MemBinder(m));
1249 if (MONITOR_CPU_USAGE) {
1250 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 ServiceManager.addService("permission", new PermissionController(m));
1253
1254 ApplicationInfo info =
1255 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001256 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001257 mSystemThread.installSystemApplicationInfo(info);
1258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 synchronized (mSelf) {
1260 ProcessRecord app = mSelf.newProcessRecordLocked(
1261 mSystemThread.getApplicationThread(), info,
1262 info.processName);
1263 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001264 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265 app.maxAdj = SYSTEM_ADJ;
1266 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1267 synchronized (mSelf.mPidsSelfLocked) {
1268 mSelf.mPidsSelfLocked.put(app.pid, app);
1269 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001270 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001271 }
1272 } catch (PackageManager.NameNotFoundException e) {
1273 throw new RuntimeException(
1274 "Unable to find android system package", e);
1275 }
1276 }
1277
1278 public void setWindowManager(WindowManagerService wm) {
1279 mWindowManager = wm;
1280 }
1281
1282 public static final Context main(int factoryTest) {
1283 AThread thr = new AThread();
1284 thr.start();
1285
1286 synchronized (thr) {
1287 while (thr.mService == null) {
1288 try {
1289 thr.wait();
1290 } catch (InterruptedException e) {
1291 }
1292 }
1293 }
1294
1295 ActivityManagerService m = thr.mService;
1296 mSelf = m;
1297 ActivityThread at = ActivityThread.systemMain();
1298 mSystemThread = at;
1299 Context context = at.getSystemContext();
1300 m.mContext = context;
1301 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001302 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303
1304 m.mBatteryStatsService.publish(context);
1305 m.mUsageStatsService.publish(context);
1306
1307 synchronized (thr) {
1308 thr.mReady = true;
1309 thr.notifyAll();
1310 }
1311
1312 m.startRunning(null, null, null, null);
1313
1314 return context;
1315 }
1316
1317 public static ActivityManagerService self() {
1318 return mSelf;
1319 }
1320
1321 static class AThread extends Thread {
1322 ActivityManagerService mService;
1323 boolean mReady = false;
1324
1325 public AThread() {
1326 super("ActivityManager");
1327 }
1328
1329 public void run() {
1330 Looper.prepare();
1331
1332 android.os.Process.setThreadPriority(
1333 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001334 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335
1336 ActivityManagerService m = new ActivityManagerService();
1337
1338 synchronized (this) {
1339 mService = m;
1340 notifyAll();
1341 }
1342
1343 synchronized (this) {
1344 while (!mReady) {
1345 try {
1346 wait();
1347 } catch (InterruptedException e) {
1348 }
1349 }
1350 }
1351
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001352 // For debug builds, log event loop stalls to dropbox for analysis.
1353 if (StrictMode.conditionallyEnableDebugLogging()) {
1354 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1355 }
1356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 Looper.loop();
1358 }
1359 }
1360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 static class MemBinder extends Binder {
1362 ActivityManagerService mActivityManagerService;
1363 MemBinder(ActivityManagerService activityManagerService) {
1364 mActivityManagerService = activityManagerService;
1365 }
1366
1367 @Override
1368 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1369 ActivityManagerService service = mActivityManagerService;
1370 ArrayList<ProcessRecord> procs;
1371 synchronized (mActivityManagerService) {
1372 if (args != null && args.length > 0
1373 && args[0].charAt(0) != '-') {
1374 procs = new ArrayList<ProcessRecord>();
1375 int pid = -1;
1376 try {
1377 pid = Integer.parseInt(args[0]);
1378 } catch (NumberFormatException e) {
1379
1380 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001381 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1382 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 if (proc.pid == pid) {
1384 procs.add(proc);
1385 } else if (proc.processName.equals(args[0])) {
1386 procs.add(proc);
1387 }
1388 }
1389 if (procs.size() <= 0) {
1390 pw.println("No process found for: " + args[0]);
1391 return;
1392 }
1393 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001394 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 }
1396 }
1397 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1398 }
1399 }
1400
1401 static class CpuBinder extends Binder {
1402 ActivityManagerService mActivityManagerService;
1403 CpuBinder(ActivityManagerService activityManagerService) {
1404 mActivityManagerService = activityManagerService;
1405 }
1406
1407 @Override
1408 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1409 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001410 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1411 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1412 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 }
1414 }
1415 }
1416
1417 private ActivityManagerService() {
1418 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1419 if (v != null && Integer.getInteger(v) != 0) {
1420 mSimpleProcessManagement = true;
1421 }
1422 v = System.getenv("ANDROID_DEBUG_APP");
1423 if (v != null) {
1424 mSimpleProcessManagement = true;
1425 }
1426
Joe Onorato8a9b2202010-02-26 18:56:32 -08001427 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429 File dataDir = Environment.getDataDirectory();
1430 File systemDir = new File(dataDir, "system");
1431 systemDir.mkdirs();
1432 mBatteryStatsService = new BatteryStatsService(new File(
1433 systemDir, "batterystats.bin").toString());
1434 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001435 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001436 mOnBattery = DEBUG_POWER ? true
1437 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001438 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001440 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001441 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442
Jack Palevichb90d28c2009-07-22 15:35:24 -07001443 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1444 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1445
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001446 mConfiguration.setToDefaults();
1447 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 mProcessStats.init();
1449
1450 // Add ourself to the Watchdog monitors.
1451 Watchdog.getInstance().addMonitor(this);
1452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 mProcessStatsThread = new Thread("ProcessStats") {
1454 public void run() {
1455 while (true) {
1456 try {
1457 try {
1458 synchronized(this) {
1459 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001460 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001462 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 // + ", write delay=" + nextWriteDelay);
1464 if (nextWriteDelay < nextCpuDelay) {
1465 nextCpuDelay = nextWriteDelay;
1466 }
1467 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001468 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 this.wait(nextCpuDelay);
1470 }
1471 }
1472 } catch (InterruptedException e) {
1473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 updateCpuStatsNow();
1475 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001476 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 }
1478 }
1479 }
1480 };
1481 mProcessStatsThread.start();
1482 }
1483
1484 @Override
1485 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1486 throws RemoteException {
1487 try {
1488 return super.onTransact(code, data, reply, flags);
1489 } catch (RuntimeException e) {
1490 // The activity manager only throws security exceptions, so let's
1491 // log all others.
1492 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001493 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 }
1495 throw e;
1496 }
1497 }
1498
1499 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001500 final long now = SystemClock.uptimeMillis();
1501 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1502 return;
1503 }
1504 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1505 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 mProcessStatsThread.notify();
1507 }
1508 }
1509 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 void updateCpuStatsNow() {
1512 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001513 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 final long now = SystemClock.uptimeMillis();
1515 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001518 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1519 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 haveNewCpuStats = true;
1521 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001522 //Slog.i(TAG, mProcessStats.printCurrentState());
1523 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 // + mProcessStats.getTotalCpuPercent() + "%");
1525
Joe Onorato8a9b2202010-02-26 18:56:32 -08001526 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 if ("true".equals(SystemProperties.get("events.cpu"))) {
1528 int user = mProcessStats.getLastUserTime();
1529 int system = mProcessStats.getLastSystemTime();
1530 int iowait = mProcessStats.getLastIoWaitTime();
1531 int irq = mProcessStats.getLastIrqTime();
1532 int softIrq = mProcessStats.getLastSoftIrqTime();
1533 int idle = mProcessStats.getLastIdleTime();
1534
1535 int total = user + system + iowait + irq + softIrq + idle;
1536 if (total == 0) total = 1;
1537
Doug Zongker2bec3d42009-12-04 12:52:44 -08001538 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 ((user+system+iowait+irq+softIrq) * 100) / total,
1540 (user * 100) / total,
1541 (system * 100) / total,
1542 (iowait * 100) / total,
1543 (irq * 100) / total,
1544 (softIrq * 100) / total);
1545 }
1546 }
1547
Amith Yamasanie43530a2009-08-21 13:11:37 -07001548 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001549 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001550 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 synchronized(mPidsSelfLocked) {
1552 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001553 if (mOnBattery) {
1554 int perc = bstats.startAddingCpuLocked();
1555 int totalUTime = 0;
1556 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001557 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001559 ProcessStats.Stats st = mProcessStats.getStats(i);
1560 if (!st.working) {
1561 continue;
1562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001564 int otherUTime = (st.rel_utime*perc)/100;
1565 int otherSTime = (st.rel_stime*perc)/100;
1566 totalUTime += otherUTime;
1567 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 if (pr != null) {
1569 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001570 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1571 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001572 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001573 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001574 } else {
1575 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001576 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001577 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001578 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1579 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001580 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 }
1583 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001584 bstats.finishAddingCpuLocked(perc, totalUTime,
1585 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 }
1587 }
1588 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001590 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1591 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001592 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 }
1594 }
1595 }
1596 }
1597
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001598 @Override
1599 public void batteryNeedsCpuUpdate() {
1600 updateCpuStatsNow();
1601 }
1602
1603 @Override
1604 public void batteryPowerChanged(boolean onBattery) {
1605 // When plugging in, update the CPU stats first before changing
1606 // the plug state.
1607 updateCpuStatsNow();
1608 synchronized (this) {
1609 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001610 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001611 }
1612 }
1613 }
1614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 /**
1616 * Initialize the application bind args. These are passed to each
1617 * process when the bindApplication() IPC is sent to the process. They're
1618 * lazily setup to make sure the services are running when they're asked for.
1619 */
1620 private HashMap<String, IBinder> getCommonServicesLocked() {
1621 if (mAppBindArgs == null) {
1622 mAppBindArgs = new HashMap<String, IBinder>();
1623
1624 // Setup the application init args
1625 mAppBindArgs.put("package", ServiceManager.getService("package"));
1626 mAppBindArgs.put("window", ServiceManager.getService("window"));
1627 mAppBindArgs.put(Context.ALARM_SERVICE,
1628 ServiceManager.getService(Context.ALARM_SERVICE));
1629 }
1630 return mAppBindArgs;
1631 }
1632
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001633 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 if (mFocusedActivity != r) {
1635 mFocusedActivity = r;
1636 mWindowManager.setFocusedApp(r, true);
1637 }
1638 }
1639
Dianne Hackborn906497c2010-05-10 15:57:38 -07001640 private final void updateLruProcessInternalLocked(ProcessRecord app,
1641 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001643 int lrui = mLruProcesses.indexOf(app);
1644 if (lrui >= 0) mLruProcesses.remove(lrui);
1645
1646 int i = mLruProcesses.size()-1;
1647 int skipTop = 0;
1648
Dianne Hackborn906497c2010-05-10 15:57:38 -07001649 app.lruSeq = mLruSeq;
1650
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001651 // compute the new weight for this process.
1652 if (updateActivityTime) {
1653 app.lastActivityTime = SystemClock.uptimeMillis();
1654 }
1655 if (app.activities.size() > 0) {
1656 // If this process has activities, we more strongly want to keep
1657 // it around.
1658 app.lruWeight = app.lastActivityTime;
1659 } else if (app.pubProviders.size() > 0) {
1660 // If this process contains content providers, we want to keep
1661 // it a little more strongly.
1662 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1663 // Also don't let it kick out the first few "real" hidden processes.
1664 skipTop = MIN_HIDDEN_APPS;
1665 } else {
1666 // If this process doesn't have activities, we less strongly
1667 // want to keep it around, and generally want to avoid getting
1668 // in front of any very recently used activities.
1669 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1670 // Also don't let it kick out the first few "real" hidden processes.
1671 skipTop = MIN_HIDDEN_APPS;
1672 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001673
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001674 while (i >= 0) {
1675 ProcessRecord p = mLruProcesses.get(i);
1676 // If this app shouldn't be in front of the first N background
1677 // apps, then skip over that many that are currently hidden.
1678 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1679 skipTop--;
1680 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001681 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001682 mLruProcesses.add(i+1, app);
1683 break;
1684 }
1685 i--;
1686 }
1687 if (i < 0) {
1688 mLruProcesses.add(0, app);
1689 }
1690
Dianne Hackborn906497c2010-05-10 15:57:38 -07001691 // If the app is currently using a content provider or service,
1692 // bump those processes as well.
1693 if (app.connections.size() > 0) {
1694 for (ConnectionRecord cr : app.connections) {
1695 if (cr.binding != null && cr.binding.service != null
1696 && cr.binding.service.app != null
1697 && cr.binding.service.app.lruSeq != mLruSeq) {
1698 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1699 updateActivityTime, i+1);
1700 }
1701 }
1702 }
1703 if (app.conProviders.size() > 0) {
1704 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1705 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1706 updateLruProcessInternalLocked(cpr.app, oomAdj,
1707 updateActivityTime, i+1);
1708 }
1709 }
1710 }
1711
Joe Onorato8a9b2202010-02-26 18:56:32 -08001712 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 if (oomAdj) {
1714 updateOomAdjLocked();
1715 }
1716 }
1717
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001718 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001719 boolean oomAdj, boolean updateActivityTime) {
1720 mLruSeq++;
1721 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1722 }
1723
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001724 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 String processName, int uid) {
1726 if (uid == Process.SYSTEM_UID) {
1727 // The system gets to run in any process. If there are multiple
1728 // processes with the same uid, just pick the first (this
1729 // should never happen).
1730 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1731 processName);
1732 return procs != null ? procs.valueAt(0) : null;
1733 }
1734 ProcessRecord proc = mProcessNames.get(processName, uid);
1735 return proc;
1736 }
1737
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001738 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001739 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001740 try {
1741 if (pm.performDexOpt(packageName)) {
1742 mDidDexOpt = true;
1743 }
1744 } catch (RemoteException e) {
1745 }
1746 }
1747
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001748 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 int transit = mWindowManager.getPendingAppTransition();
1750 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1751 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1752 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1753 }
1754
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001755 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001757 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1759 // We don't have to do anything more if:
1760 // (1) There is an existing application record; and
1761 // (2) The caller doesn't think it is dead, OR there is no thread
1762 // object attached to it so we know it couldn't have crashed; and
1763 // (3) There is a pid assigned to it, so it is either starting or
1764 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001765 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 + " app=" + app + " knownToBeDead=" + knownToBeDead
1767 + " thread=" + (app != null ? app.thread : null)
1768 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001769 if (app != null && app.pid > 0) {
1770 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001771 // We already have the app running, or are waiting for it to
1772 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001773 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001774 return app;
1775 } else {
1776 // An application record is attached to a previous process,
1777 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001778 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001779 handleAppDiedLocked(app, true);
1780 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 String hostingNameStr = hostingName != null
1784 ? hostingName.flattenToShortString() : null;
1785
1786 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1787 // If we are in the background, then check to see if this process
1788 // is bad. If so, we will just silently fail.
1789 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001790 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1791 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 return null;
1793 }
1794 } else {
1795 // When the user is explicitly starting a process, then clear its
1796 // crash count so that we won't make it bad until they see at
1797 // least one crash dialog again, and make the process good again
1798 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001799 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1800 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 mProcessCrashTimes.remove(info.processName, info.uid);
1802 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001803 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 info.processName);
1805 mBadProcesses.remove(info.processName, info.uid);
1806 if (app != null) {
1807 app.bad = false;
1808 }
1809 }
1810 }
1811
1812 if (app == null) {
1813 app = newProcessRecordLocked(null, info, processName);
1814 mProcessNames.put(processName, info.uid, app);
1815 } else {
1816 // If this is a new package in the process, add the package to the list
1817 app.addPackage(info.packageName);
1818 }
1819
1820 // If the system is not ready yet, then hold off on starting this
1821 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001822 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001823 && !isAllowedWhileBooting(info)
1824 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 if (!mProcessesOnHold.contains(app)) {
1826 mProcessesOnHold.add(app);
1827 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001828 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 return app;
1830 }
1831
1832 startProcessLocked(app, hostingType, hostingNameStr);
1833 return (app.pid != 0) ? app : null;
1834 }
1835
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001836 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1837 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1838 }
1839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 private final void startProcessLocked(ProcessRecord app,
1841 String hostingType, String hostingNameStr) {
1842 if (app.pid > 0 && app.pid != MY_PID) {
1843 synchronized (mPidsSelfLocked) {
1844 mPidsSelfLocked.remove(app.pid);
1845 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1846 }
1847 app.pid = 0;
1848 }
1849
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001850 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1851 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 mProcessesOnHold.remove(app);
1853
1854 updateCpuStats();
1855
1856 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1857 mProcDeaths[0] = 0;
1858
1859 try {
1860 int uid = app.info.uid;
1861 int[] gids = null;
1862 try {
1863 gids = mContext.getPackageManager().getPackageGids(
1864 app.info.packageName);
1865 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001866 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 }
1868 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1869 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1870 && mTopComponent != null
1871 && app.processName.equals(mTopComponent.getPackageName())) {
1872 uid = 0;
1873 }
1874 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1875 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1876 uid = 0;
1877 }
1878 }
1879 int debugFlags = 0;
1880 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1881 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1882 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001883 // Run the app in safe mode if its manifest requests so or the
1884 // system is booted in safe mode.
1885 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1886 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001887 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001889 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1890 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1891 }
1892 if ("1".equals(SystemProperties.get("debug.assert"))) {
1893 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1894 }
1895 int pid = Process.start("android.app.ActivityThread",
1896 mSimpleProcessManagement ? app.processName : null, uid, uid,
1897 gids, debugFlags, null);
1898 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1899 synchronized (bs) {
1900 if (bs.isOnBattery()) {
1901 app.batteryStats.incStartsLocked();
1902 }
1903 }
1904
Doug Zongker2bec3d42009-12-04 12:52:44 -08001905 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906 app.processName, hostingType,
1907 hostingNameStr != null ? hostingNameStr : "");
1908
1909 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001910 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001911 }
1912
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001913 StringBuilder buf = mStringBuilder;
1914 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 buf.append("Start proc ");
1916 buf.append(app.processName);
1917 buf.append(" for ");
1918 buf.append(hostingType);
1919 if (hostingNameStr != null) {
1920 buf.append(" ");
1921 buf.append(hostingNameStr);
1922 }
1923 buf.append(": pid=");
1924 buf.append(pid);
1925 buf.append(" uid=");
1926 buf.append(uid);
1927 buf.append(" gids={");
1928 if (gids != null) {
1929 for (int gi=0; gi<gids.length; gi++) {
1930 if (gi != 0) buf.append(", ");
1931 buf.append(gids[gi]);
1932
1933 }
1934 }
1935 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001936 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 if (pid == 0 || pid == MY_PID) {
1938 // Processes are being emulated with threads.
1939 app.pid = MY_PID;
1940 app.removed = false;
1941 mStartingProcesses.add(app);
1942 } else if (pid > 0) {
1943 app.pid = pid;
1944 app.removed = false;
1945 synchronized (mPidsSelfLocked) {
1946 this.mPidsSelfLocked.put(pid, app);
1947 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1948 msg.obj = app;
1949 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1950 }
1951 } else {
1952 app.pid = 0;
1953 RuntimeException e = new RuntimeException(
1954 "Failure starting process " + app.processName
1955 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001956 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 }
1958 } catch (RuntimeException e) {
1959 // XXX do better error recovery.
1960 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001961 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001962 }
1963 }
1964
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001965 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 if (resumed) {
1967 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1968 } else {
1969 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1970 }
1971 }
1972
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001973 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001974 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1975 && mTopAction == null) {
1976 // We are running in factory test mode, but unable to find
1977 // the factory test app, so just sit around displaying the
1978 // error message and don't try to start anything.
1979 return false;
1980 }
1981 Intent intent = new Intent(
1982 mTopAction,
1983 mTopData != null ? Uri.parse(mTopData) : null);
1984 intent.setComponent(mTopComponent);
1985 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1986 intent.addCategory(Intent.CATEGORY_HOME);
1987 }
1988 ActivityInfo aInfo =
1989 intent.resolveActivityInfo(mContext.getPackageManager(),
1990 STOCK_PM_FLAGS);
1991 if (aInfo != null) {
1992 intent.setComponent(new ComponentName(
1993 aInfo.applicationInfo.packageName, aInfo.name));
1994 // Don't do this if the home app is currently being
1995 // instrumented.
1996 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1997 aInfo.applicationInfo.uid);
1998 if (app == null || app.instrumentationClass == null) {
1999 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002000 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002001 null, null, 0, 0, 0, false, false);
2002 }
2003 }
2004
2005
2006 return true;
2007 }
2008
2009 /**
2010 * Starts the "new version setup screen" if appropriate.
2011 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002012 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002013 // Only do this once per boot.
2014 if (mCheckedForSetup) {
2015 return;
2016 }
2017
2018 // We will show this screen if the current one is a different
2019 // version than the last one shown, and we are not running in
2020 // low-level factory test mode.
2021 final ContentResolver resolver = mContext.getContentResolver();
2022 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2023 Settings.Secure.getInt(resolver,
2024 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2025 mCheckedForSetup = true;
2026
2027 // See if we should be showing the platform update setup UI.
2028 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2029 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2030 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2031
2032 // We don't allow third party apps to replace this.
2033 ResolveInfo ri = null;
2034 for (int i=0; ris != null && i<ris.size(); i++) {
2035 if ((ris.get(i).activityInfo.applicationInfo.flags
2036 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2037 ri = ris.get(i);
2038 break;
2039 }
2040 }
2041
2042 if (ri != null) {
2043 String vers = ri.activityInfo.metaData != null
2044 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2045 : null;
2046 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2047 vers = ri.activityInfo.applicationInfo.metaData.getString(
2048 Intent.METADATA_SETUP_VERSION);
2049 }
2050 String lastVers = Settings.Secure.getString(
2051 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2052 if (vers != null && !vers.equals(lastVers)) {
2053 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2054 intent.setComponent(new ComponentName(
2055 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002056 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002057 null, null, 0, 0, 0, false, false);
2058 }
2059 }
2060 }
2061 }
2062
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002063 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002064 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002065
2066 final int identHash = System.identityHashCode(r);
2067 updateUsageStats(r, true);
2068
2069 int i = mWatchers.beginBroadcast();
2070 while (i > 0) {
2071 i--;
2072 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2073 if (w != null) {
2074 try {
2075 w.activityResuming(identHash);
2076 } catch (RemoteException e) {
2077 }
2078 }
2079 }
2080 mWatchers.finishBroadcast();
2081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002083 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002084 final int N = mPendingActivityLaunches.size();
2085 if (N <= 0) {
2086 return;
2087 }
2088 for (int i=0; i<N; i++) {
2089 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002090 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002091 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2092 doResume && i == (N-1));
2093 }
2094 mPendingActivityLaunches.clear();
2095 }
2096
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002097 public final int startActivity(IApplicationThread caller,
2098 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2099 int grantedMode, IBinder resultTo,
2100 String resultWho, int requestCode, boolean onlyIfNeeded,
2101 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002102 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002103 grantedUriPermissions, grantedMode, resultTo, resultWho,
2104 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002105 }
2106
2107 public final WaitResult startActivityAndWait(IApplicationThread caller,
2108 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2109 int grantedMode, IBinder resultTo,
2110 String resultWho, int requestCode, boolean onlyIfNeeded,
2111 boolean debug) {
2112 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002113 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002114 grantedUriPermissions, grantedMode, resultTo, resultWho,
2115 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002116 return res;
2117 }
2118
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002119 public final int startActivityWithConfig(IApplicationThread caller,
2120 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2121 int grantedMode, IBinder resultTo,
2122 String resultWho, int requestCode, boolean onlyIfNeeded,
2123 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002124 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002125 grantedUriPermissions, grantedMode, resultTo, resultWho,
2126 requestCode, onlyIfNeeded, debug, null, config);
2127 }
2128
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002129 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002130 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002131 IBinder resultTo, String resultWho, int requestCode,
2132 int flagsMask, int flagsValues) {
2133 // Refuse possible leaked file descriptors
2134 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2135 throw new IllegalArgumentException("File descriptors passed in Intent");
2136 }
2137
2138 IIntentSender sender = intent.getTarget();
2139 if (!(sender instanceof PendingIntentRecord)) {
2140 throw new IllegalArgumentException("Bad PendingIntent object");
2141 }
2142
2143 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002144
2145 synchronized (this) {
2146 // If this is coming from the currently resumed activity, it is
2147 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002148 if (mMainStack.mResumedActivity != null
2149 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002150 Binder.getCallingUid()) {
2151 mAppSwitchesAllowedTime = 0;
2152 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002153 }
2154
2155 return pir.sendInner(0, fillInIntent, resolvedType,
2156 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2157 }
2158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 public boolean startNextMatchingActivity(IBinder callingActivity,
2160 Intent intent) {
2161 // Refuse possible leaked file descriptors
2162 if (intent != null && intent.hasFileDescriptors() == true) {
2163 throw new IllegalArgumentException("File descriptors passed in Intent");
2164 }
2165
2166 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002167 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168 if (index < 0) {
2169 return false;
2170 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002171 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 if (r.app == null || r.app.thread == null) {
2173 // The caller is not running... d'oh!
2174 return false;
2175 }
2176 intent = new Intent(intent);
2177 // The caller is not allowed to change the data.
2178 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2179 // And we are resetting to find the next component...
2180 intent.setComponent(null);
2181
2182 ActivityInfo aInfo = null;
2183 try {
2184 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002185 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002187 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188
2189 // Look for the original activity in the list...
2190 final int N = resolves != null ? resolves.size() : 0;
2191 for (int i=0; i<N; i++) {
2192 ResolveInfo rInfo = resolves.get(i);
2193 if (rInfo.activityInfo.packageName.equals(r.packageName)
2194 && rInfo.activityInfo.name.equals(r.info.name)) {
2195 // We found the current one... the next matching is
2196 // after it.
2197 i++;
2198 if (i<N) {
2199 aInfo = resolves.get(i).activityInfo;
2200 }
2201 break;
2202 }
2203 }
2204 } catch (RemoteException e) {
2205 }
2206
2207 if (aInfo == null) {
2208 // Nobody who is next!
2209 return false;
2210 }
2211
2212 intent.setComponent(new ComponentName(
2213 aInfo.applicationInfo.packageName, aInfo.name));
2214 intent.setFlags(intent.getFlags()&~(
2215 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2216 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2217 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2218 Intent.FLAG_ACTIVITY_NEW_TASK));
2219
2220 // Okay now we need to start the new activity, replacing the
2221 // currently running activity. This is a little tricky because
2222 // we want to start the new one as if the current one is finished,
2223 // but not finish the current one first so that there is no flicker.
2224 // And thus...
2225 final boolean wasFinishing = r.finishing;
2226 r.finishing = true;
2227
2228 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002229 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002230 final String resultWho = r.resultWho;
2231 final int requestCode = r.requestCode;
2232 r.resultTo = null;
2233 if (resultTo != null) {
2234 resultTo.removeResultsLocked(r, resultWho, requestCode);
2235 }
2236
2237 final long origId = Binder.clearCallingIdentity();
2238 // XXX we are not dealing with propagating grantedUriPermissions...
2239 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002240 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002241 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002242 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243 Binder.restoreCallingIdentity(origId);
2244
2245 r.finishing = wasFinishing;
2246 if (res != START_SUCCESS) {
2247 return false;
2248 }
2249 return true;
2250 }
2251 }
2252
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002253 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 Intent intent, String resolvedType, IBinder resultTo,
2255 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002256
2257 // This is so super not safe, that only the system (or okay root)
2258 // can do it.
2259 final int callingUid = Binder.getCallingUid();
2260 if (callingUid != 0 && callingUid != Process.myUid()) {
2261 throw new SecurityException(
2262 "startActivityInPackage only available to the system");
2263 }
2264
The Android Open Source Project4df24232009-03-05 14:34:35 -08002265 final boolean componentSpecified = intent.getComponent() != null;
2266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 // Don't modify the client's object!
2268 intent = new Intent(intent);
2269
2270 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 ActivityInfo aInfo;
2272 try {
2273 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002274 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002276 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 aInfo = rInfo != null ? rInfo.activityInfo : null;
2278 } catch (RemoteException e) {
2279 aInfo = null;
2280 }
2281
2282 if (aInfo != null) {
2283 // Store the found target back into the intent, because now that
2284 // we have it we never want to do this again. For example, if the
2285 // user navigates back to this point in the history, we should
2286 // always restart the exact same activity.
2287 intent.setComponent(new ComponentName(
2288 aInfo.applicationInfo.packageName, aInfo.name));
2289 }
2290
2291 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002292 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002294 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 }
2296 }
2297
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002298 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002299 // Remove any existing entries that are the same kind of task.
2300 int N = mRecentTasks.size();
2301 for (int i=0; i<N; i++) {
2302 TaskRecord tr = mRecentTasks.get(i);
2303 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2304 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2305 mRecentTasks.remove(i);
2306 i--;
2307 N--;
2308 if (task.intent == null) {
2309 // If the new recent task we are adding is not fully
2310 // specified, then replace it with the existing recent task.
2311 task = tr;
2312 }
2313 }
2314 }
2315 if (N >= MAX_RECENT_TASKS) {
2316 mRecentTasks.remove(N-1);
2317 }
2318 mRecentTasks.add(0, task);
2319 }
2320
2321 public void setRequestedOrientation(IBinder token,
2322 int requestedOrientation) {
2323 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002324 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002325 if (index < 0) {
2326 return;
2327 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002328 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002329 final long origId = Binder.clearCallingIdentity();
2330 mWindowManager.setAppOrientation(r, requestedOrientation);
2331 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002332 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002333 r.mayFreezeScreenLocked(r.app) ? r : null);
2334 if (config != null) {
2335 r.frozenBeforeDestroy = true;
2336 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002337 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338 }
2339 }
2340 Binder.restoreCallingIdentity(origId);
2341 }
2342 }
2343
2344 public int getRequestedOrientation(IBinder token) {
2345 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002346 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002347 if (index < 0) {
2348 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2349 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002350 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 return mWindowManager.getAppOrientation(r);
2352 }
2353 }
2354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002355 /**
2356 * This is the internal entry point for handling Activity.finish().
2357 *
2358 * @param token The Binder token referencing the Activity we want to finish.
2359 * @param resultCode Result code, if any, from this Activity.
2360 * @param resultData Result data (Intent), if any, from this Activity.
2361 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002362 * @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 -08002363 */
2364 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2365 // Refuse possible leaked file descriptors
2366 if (resultData != null && resultData.hasFileDescriptors() == true) {
2367 throw new IllegalArgumentException("File descriptors passed in Intent");
2368 }
2369
2370 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002371 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002373 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 if (next != null) {
2375 // ask watcher if this is allowed
2376 boolean resumeOK = true;
2377 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002378 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002380 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002381 }
2382
2383 if (!resumeOK) {
2384 return false;
2385 }
2386 }
2387 }
2388 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002389 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 resultData, "app-request");
2391 Binder.restoreCallingIdentity(origId);
2392 return res;
2393 }
2394 }
2395
Dianne Hackborn860755f2010-06-03 18:47:52 -07002396 public final void finishHeavyWeightApp() {
2397 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2398 != PackageManager.PERMISSION_GRANTED) {
2399 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2400 + Binder.getCallingPid()
2401 + ", uid=" + Binder.getCallingUid()
2402 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2403 Slog.w(TAG, msg);
2404 throw new SecurityException(msg);
2405 }
2406
2407 synchronized(this) {
2408 if (mHeavyWeightProcess == null) {
2409 return;
2410 }
2411
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002412 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002413 mHeavyWeightProcess.activities);
2414 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002415 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002416 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002417 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002418 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002419 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002420 null, "finish-heavy");
2421 }
2422 }
2423 }
2424
2425 mHeavyWeightProcess = null;
2426 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2427 }
2428 }
2429
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002430 public void crashApplication(int uid, int initialPid, String packageName,
2431 String message) {
2432 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2433 != PackageManager.PERMISSION_GRANTED) {
2434 String msg = "Permission Denial: crashApplication() from pid="
2435 + Binder.getCallingPid()
2436 + ", uid=" + Binder.getCallingUid()
2437 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2438 Slog.w(TAG, msg);
2439 throw new SecurityException(msg);
2440 }
2441
2442 synchronized(this) {
2443 ProcessRecord proc = null;
2444
2445 // Figure out which process to kill. We don't trust that initialPid
2446 // still has any relation to current pids, so must scan through the
2447 // list.
2448 synchronized (mPidsSelfLocked) {
2449 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2450 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2451 if (p.info.uid != uid) {
2452 continue;
2453 }
2454 if (p.pid == initialPid) {
2455 proc = p;
2456 break;
2457 }
2458 for (String str : p.pkgList) {
2459 if (str.equals(packageName)) {
2460 proc = p;
2461 }
2462 }
2463 }
2464 }
2465
2466 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002467 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002468 + " initialPid=" + initialPid
2469 + " packageName=" + packageName);
2470 return;
2471 }
2472
2473 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002474 if (proc.pid == Process.myPid()) {
2475 Log.w(TAG, "crashApplication: trying to crash self!");
2476 return;
2477 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002478 long ident = Binder.clearCallingIdentity();
2479 try {
2480 proc.thread.scheduleCrash(message);
2481 } catch (RemoteException e) {
2482 }
2483 Binder.restoreCallingIdentity(ident);
2484 }
2485 }
2486 }
2487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002488 public final void finishSubActivity(IBinder token, String resultWho,
2489 int requestCode) {
2490 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002491 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492 if (index < 0) {
2493 return;
2494 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002495 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496
2497 final long origId = Binder.clearCallingIdentity();
2498
2499 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002500 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2501 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 if (r.resultTo == self && r.requestCode == requestCode) {
2503 if ((r.resultWho == null && resultWho == null) ||
2504 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002505 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 Activity.RESULT_CANCELED, null, "request-sub");
2507 }
2508 }
2509 }
2510
2511 Binder.restoreCallingIdentity(origId);
2512 }
2513 }
2514
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002515 public boolean willActivityBeVisible(IBinder token) {
2516 synchronized(this) {
2517 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002518 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2519 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002520 if (r == token) {
2521 return true;
2522 }
2523 if (r.fullscreen && !r.finishing) {
2524 return false;
2525 }
2526 }
2527 return true;
2528 }
2529 }
2530
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002531 public void overridePendingTransition(IBinder token, String packageName,
2532 int enterAnim, int exitAnim) {
2533 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002534 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002535 if (index < 0) {
2536 return;
2537 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002538 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002539
2540 final long origId = Binder.clearCallingIdentity();
2541
2542 if (self.state == ActivityState.RESUMED
2543 || self.state == ActivityState.PAUSING) {
2544 mWindowManager.overridePendingAppTransition(packageName,
2545 enterAnim, exitAnim);
2546 }
2547
2548 Binder.restoreCallingIdentity(origId);
2549 }
2550 }
2551
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 * Main function for removing an existing process from the activity manager
2554 * as a result of that process going away. Clears out all connections
2555 * to the process.
2556 */
2557 private final void handleAppDiedLocked(ProcessRecord app,
2558 boolean restarting) {
2559 cleanUpApplicationRecordLocked(app, restarting, -1);
2560 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002561 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 }
2563
2564 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002565 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2566 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2567 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002569 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2570 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 }
2572
2573 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002574 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575
2576 boolean atTop = true;
2577 boolean hasVisibleActivities = false;
2578
2579 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002580 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002581 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002582 TAG, "Removing app " + app + " from history with " + i + " entries");
2583 while (i > 0) {
2584 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002585 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002586 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2588 if (r.app == app) {
2589 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002590 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 TAG, "Removing this entry! frozen=" + r.haveState
2592 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002593 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594
2595 r.inHistory = false;
2596 mWindowManager.removeAppToken(r);
2597 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002598 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002600 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002601
2602 } else {
2603 // We have the current state for this activity, so
2604 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002605 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002606 TAG, "Keeping entry, setting app to null");
2607 if (r.visible) {
2608 hasVisibleActivities = true;
2609 }
2610 r.app = null;
2611 r.nowVisible = false;
2612 if (!r.haveState) {
2613 r.icicle = null;
2614 }
2615 }
2616
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002617 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618 r.state = ActivityState.STOPPED;
2619 }
2620 atTop = false;
2621 }
2622
2623 app.activities.clear();
2624
2625 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002626 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002627 + " running instrumentation " + app.instrumentationClass);
2628 Bundle info = new Bundle();
2629 info.putString("shortMsg", "Process crashed.");
2630 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2631 }
2632
2633 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002634 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 // If there was nothing to resume, and we are not already
2636 // restarting this process, but there is a visible activity that
2637 // is hosted by the process... then make sure all visible
2638 // activities are running, taking care of restarting this
2639 // process.
2640 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002641 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002642 }
2643 }
2644 }
2645 }
2646
2647 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2648 IBinder threadBinder = thread.asBinder();
2649
2650 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002651 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2652 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002653 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2654 return i;
2655 }
2656 }
2657 return -1;
2658 }
2659
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002660 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 IApplicationThread thread) {
2662 if (thread == null) {
2663 return null;
2664 }
2665
2666 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002667 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668 }
2669
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002670 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 IApplicationThread thread) {
2672
2673 mProcDeaths[0]++;
2674
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002675 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2676 synchronized (stats) {
2677 stats.noteProcessDiedLocked(app.info.uid, pid);
2678 }
2679
Magnus Edlund7bb25812010-02-24 15:45:06 +01002680 // Clean up already done if the process has been re-started.
2681 if (app.pid == pid && app.thread != null &&
2682 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002683 if (!app.killedBackground) {
2684 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2685 + ") has died.");
2686 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002687 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002688 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 TAG, "Dying app: " + app + ", pid: " + pid
2690 + ", thread: " + thread.asBinder());
2691 boolean doLowMem = app.instrumentationClass == null;
2692 handleAppDiedLocked(app, false);
2693
2694 if (doLowMem) {
2695 // If there are no longer any background processes running,
2696 // and the app that died was not running instrumentation,
2697 // then tell everyone we are now low on memory.
2698 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002699 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2700 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2702 haveBg = true;
2703 break;
2704 }
2705 }
2706
2707 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002708 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002709 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002710 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002711 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2712 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002713 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002714 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2715 // The low memory report is overriding any current
2716 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002717 // heavy/important/visible/foreground processes first.
2718 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002719 rec.lastRequestedGc = 0;
2720 } else {
2721 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002723 rec.reportLowMemory = true;
2724 rec.lastLowMemory = now;
2725 mProcessesToGc.remove(rec);
2726 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 }
2728 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002729 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730 }
2731 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002732 } else if (app.pid != pid) {
2733 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002734 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002735 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002736 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002737 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002738 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002739 + thread.asBinder());
2740 }
2741 }
2742
Dan Egnor42471dd2010-01-07 17:25:22 -08002743 /**
2744 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002745 * @param clearTraces causes the dump file to be erased prior to the new
2746 * traces being written, if true; when false, the new traces will be
2747 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002748 * @param firstPids of dalvik VM processes to dump stack traces for first
2749 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002750 * @return file containing stack traces, or null if no dump file is configured
2751 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002752 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2753 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002754 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2755 if (tracesPath == null || tracesPath.length() == 0) {
2756 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002757 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002758
2759 File tracesFile = new File(tracesPath);
2760 try {
2761 File tracesDir = tracesFile.getParentFile();
2762 if (!tracesDir.exists()) tracesFile.mkdirs();
2763 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2764
Christopher Tate6ee412d2010-05-28 12:01:56 -07002765 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002766 tracesFile.createNewFile();
2767 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2768 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002769 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002770 return null;
2771 }
2772
2773 // Use a FileObserver to detect when traces finish writing.
2774 // The order of traces is considered important to maintain for legibility.
2775 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2776 public synchronized void onEvent(int event, String path) { notify(); }
2777 };
2778
2779 try {
2780 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002781
2782 // First collect all of the stacks of the most important pids.
2783 try {
2784 int num = firstPids.size();
2785 for (int i = 0; i < num; i++) {
2786 synchronized (observer) {
2787 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2788 observer.wait(200); // Wait for write-close, give up after 200msec
2789 }
2790 }
2791 } catch (InterruptedException e) {
2792 Log.wtf(TAG, e);
2793 }
2794
2795 // Next measure CPU usage.
2796 if (processStats != null) {
2797 processStats.init();
2798 System.gc();
2799 processStats.update();
2800 try {
2801 synchronized (processStats) {
2802 processStats.wait(500); // measure over 1/2 second.
2803 }
2804 } catch (InterruptedException e) {
2805 }
2806 processStats.update();
2807
2808 // We'll take the stack crawls of just the top apps using CPU.
2809 final int N = processStats.countWorkingStats();
2810 int numProcs = 0;
2811 for (int i=0; i<N && numProcs<5; i++) {
2812 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2813 if (lastPids.indexOfKey(stats.pid) >= 0) {
2814 numProcs++;
2815 try {
2816 synchronized (observer) {
2817 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2818 observer.wait(200); // Wait for write-close, give up after 200msec
2819 }
2820 } catch (InterruptedException e) {
2821 Log.wtf(TAG, e);
2822 }
2823
2824 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002825 }
2826 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002827
2828 return tracesFile;
2829
Dan Egnor42471dd2010-01-07 17:25:22 -08002830 } finally {
2831 observer.stopWatching();
2832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002833 }
2834
Jeff Brown4d94a762010-09-23 11:33:28 -07002835 private final class AppNotResponding implements Runnable {
2836 private final ProcessRecord mApp;
2837 private final String mAnnotation;
2838
2839 public AppNotResponding(ProcessRecord app, String annotation) {
2840 mApp = app;
2841 mAnnotation = annotation;
2842 }
2843
2844 @Override
2845 public void run() {
2846 appNotResponding(mApp, null, null, mAnnotation);
2847 }
2848 }
2849
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002850 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2851 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002852 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2853 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2854
Dianne Hackborn287952c2010-09-22 22:34:31 -07002855 if (mController != null) {
2856 try {
2857 // 0 == continue, -1 = kill process immediately
2858 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2859 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2860 } catch (RemoteException e) {
2861 mController = null;
2862 }
2863 }
2864
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002865 long anrTime = SystemClock.uptimeMillis();
2866 if (MONITOR_CPU_USAGE) {
2867 updateCpuStatsNow();
2868 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002869
2870 synchronized (this) {
2871 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2872 if (mShuttingDown) {
2873 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2874 return;
2875 } else if (app.notResponding) {
2876 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2877 return;
2878 } else if (app.crashing) {
2879 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2880 return;
2881 }
2882
2883 // In case we come through here for the same app before completing
2884 // this one, mark as anring now so we will bail out.
2885 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002886
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002887 // Log the ANR to the event log.
2888 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2889 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002890
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002891 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002892 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002893
2894 int parentPid = app.pid;
2895 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002896 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002897
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002898 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002899
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002900 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2901 ProcessRecord r = mLruProcesses.get(i);
2902 if (r != null && r.thread != null) {
2903 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002904 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2905 if (r.persistent) {
2906 firstPids.add(pid);
2907 } else {
2908 lastPids.put(pid, Boolean.TRUE);
2909 }
2910 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912 }
2913 }
2914
Dan Egnor42471dd2010-01-07 17:25:22 -08002915 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002916 StringBuilder info = mStringBuilder;
2917 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002918 info.append("ANR in ").append(app.processName);
2919 if (activity != null && activity.shortComponentName != null) {
2920 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002921 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002922 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002924 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002926 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002927 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929
Dianne Hackborn287952c2010-09-22 22:34:31 -07002930 final ProcessStats processStats = new ProcessStats(true);
2931
2932 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2933
Dan Egnor42471dd2010-01-07 17:25:22 -08002934 String cpuInfo = null;
2935 if (MONITOR_CPU_USAGE) {
2936 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002937 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002938 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002939 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002940 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002941 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 }
2943
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002944 info.append(processStats.printCurrentState(anrTime));
2945
Joe Onorato8a9b2202010-02-26 18:56:32 -08002946 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002947 if (tracesFile == null) {
2948 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2949 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2950 }
2951
2952 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2953
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002954 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002956 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2957 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002959 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2960 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002961 }
2962 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002963 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 }
2965 }
2966
Dan Egnor42471dd2010-01-07 17:25:22 -08002967 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2968 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2969 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002970
2971 synchronized (this) {
2972 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2973 Process.killProcess(app.pid);
2974 return;
2975 }
2976
2977 // Set the app's notResponding state, and look up the errorReportReceiver
2978 makeAppNotRespondingLocked(app,
2979 activity != null ? activity.shortComponentName : null,
2980 annotation != null ? "ANR " + annotation : "ANR",
2981 info.toString());
2982
2983 // Bring up the infamous App Not Responding dialog
2984 Message msg = Message.obtain();
2985 HashMap map = new HashMap();
2986 msg.what = SHOW_NOT_RESPONDING_MSG;
2987 msg.obj = map;
2988 map.put("app", app);
2989 if (activity != null) {
2990 map.put("activity", activity);
2991 }
2992
2993 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002994 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002995 }
2996
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002997 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2998 if (!mLaunchWarningShown) {
2999 mLaunchWarningShown = true;
3000 mHandler.post(new Runnable() {
3001 @Override
3002 public void run() {
3003 synchronized (ActivityManagerService.this) {
3004 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3005 d.show();
3006 mHandler.postDelayed(new Runnable() {
3007 @Override
3008 public void run() {
3009 synchronized (ActivityManagerService.this) {
3010 d.dismiss();
3011 mLaunchWarningShown = false;
3012 }
3013 }
3014 }, 4000);
3015 }
3016 }
3017 });
3018 }
3019 }
3020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 public boolean clearApplicationUserData(final String packageName,
3022 final IPackageDataObserver observer) {
3023 int uid = Binder.getCallingUid();
3024 int pid = Binder.getCallingPid();
3025 long callingId = Binder.clearCallingIdentity();
3026 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003027 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003028 int pkgUid = -1;
3029 synchronized(this) {
3030 try {
3031 pkgUid = pm.getPackageUid(packageName);
3032 } catch (RemoteException e) {
3033 }
3034 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003035 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 return false;
3037 }
3038 if (uid == pkgUid || checkComponentPermission(
3039 android.Manifest.permission.CLEAR_APP_USER_DATA,
3040 pid, uid, -1)
3041 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003042 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 } else {
3044 throw new SecurityException(pid+" does not have permission:"+
3045 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3046 "for process:"+packageName);
3047 }
3048 }
3049
3050 try {
3051 //clear application user data
3052 pm.clearApplicationUserData(packageName, observer);
3053 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3054 Uri.fromParts("package", packageName, null));
3055 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003056 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3057 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003058 } catch (RemoteException e) {
3059 }
3060 } finally {
3061 Binder.restoreCallingIdentity(callingId);
3062 }
3063 return true;
3064 }
3065
Dianne Hackborn03abb812010-01-04 18:43:19 -08003066 public void killBackgroundProcesses(final String packageName) {
3067 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3068 != PackageManager.PERMISSION_GRANTED &&
3069 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3070 != PackageManager.PERMISSION_GRANTED) {
3071 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003072 + Binder.getCallingPid()
3073 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003074 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003075 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003076 throw new SecurityException(msg);
3077 }
3078
3079 long callingId = Binder.clearCallingIdentity();
3080 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003081 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 int pkgUid = -1;
3083 synchronized(this) {
3084 try {
3085 pkgUid = pm.getPackageUid(packageName);
3086 } catch (RemoteException e) {
3087 }
3088 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003089 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 return;
3091 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003092 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003093 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003094 }
3095 } finally {
3096 Binder.restoreCallingIdentity(callingId);
3097 }
3098 }
3099
3100 public void forceStopPackage(final String packageName) {
3101 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3102 != PackageManager.PERMISSION_GRANTED) {
3103 String msg = "Permission Denial: forceStopPackage() from pid="
3104 + Binder.getCallingPid()
3105 + ", uid=" + Binder.getCallingUid()
3106 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003107 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003108 throw new SecurityException(msg);
3109 }
3110
3111 long callingId = Binder.clearCallingIdentity();
3112 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003113 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003114 int pkgUid = -1;
3115 synchronized(this) {
3116 try {
3117 pkgUid = pm.getPackageUid(packageName);
3118 } catch (RemoteException e) {
3119 }
3120 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003121 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003122 return;
3123 }
3124 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003125 }
3126 } finally {
3127 Binder.restoreCallingIdentity(callingId);
3128 }
3129 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003130
3131 /*
3132 * The pkg name and uid have to be specified.
3133 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3134 */
3135 public void killApplicationWithUid(String pkg, int uid) {
3136 if (pkg == null) {
3137 return;
3138 }
3139 // Make sure the uid is valid.
3140 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003141 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003142 return;
3143 }
3144 int callerUid = Binder.getCallingUid();
3145 // Only the system server can kill an application
3146 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003147 // Post an aysnc message to kill the application
3148 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3149 msg.arg1 = uid;
3150 msg.arg2 = 0;
3151 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003152 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003153 } else {
3154 throw new SecurityException(callerUid + " cannot kill pkg: " +
3155 pkg);
3156 }
3157 }
3158
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003159 public void closeSystemDialogs(String reason) {
3160 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003161 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003162 if (reason != null) {
3163 intent.putExtra("reason", reason);
3164 }
3165
3166 final int uid = Binder.getCallingUid();
3167 final long origId = Binder.clearCallingIdentity();
3168 synchronized (this) {
3169 int i = mWatchers.beginBroadcast();
3170 while (i > 0) {
3171 i--;
3172 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3173 if (w != null) {
3174 try {
3175 w.closingSystemDialogs(reason);
3176 } catch (RemoteException e) {
3177 }
3178 }
3179 }
3180 mWatchers.finishBroadcast();
3181
Dianne Hackbornffa42482009-09-23 22:20:11 -07003182 mWindowManager.closeSystemDialogs(reason);
3183
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003184 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3185 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003186 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003187 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003188 Activity.RESULT_CANCELED, null, "close-sys");
3189 }
3190 }
3191
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003192 broadcastIntentLocked(null, null, intent, null,
3193 null, 0, null, null, null, false, false, -1, uid);
3194 }
3195 Binder.restoreCallingIdentity(origId);
3196 }
3197
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003198 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003199 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003200 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3201 for (int i=pids.length-1; i>=0; i--) {
3202 infos[i] = new Debug.MemoryInfo();
3203 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003204 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003205 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003206 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003207
3208 public void killApplicationProcess(String processName, int uid) {
3209 if (processName == null) {
3210 return;
3211 }
3212
3213 int callerUid = Binder.getCallingUid();
3214 // Only the system server can kill an application
3215 if (callerUid == Process.SYSTEM_UID) {
3216 synchronized (this) {
3217 ProcessRecord app = getProcessRecordLocked(processName, uid);
3218 if (app != null) {
3219 try {
3220 app.thread.scheduleSuicide();
3221 } catch (RemoteException e) {
3222 // If the other end already died, then our work here is done.
3223 }
3224 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003225 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003226 + processName + " / " + uid);
3227 }
3228 }
3229 } else {
3230 throw new SecurityException(callerUid + " cannot kill app process: " +
3231 processName);
3232 }
3233 }
3234
Dianne Hackborn03abb812010-01-04 18:43:19 -08003235 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003236 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3238 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003239 if (!mProcessesReady) {
3240 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003242 intent.putExtra(Intent.EXTRA_UID, uid);
3243 broadcastIntentLocked(null, null, intent,
3244 null, null, 0, null, null, null,
3245 false, false, MY_PID, Process.SYSTEM_UID);
3246 }
3247
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003248 private final boolean killPackageProcessesLocked(String packageName, int uid,
3249 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003250 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251
Dianne Hackborn03abb812010-01-04 18:43:19 -08003252 // Remove all processes this package may have touched: all with the
3253 // same UID (except for the system or root user), and all whose name
3254 // matches the package name.
3255 final String procNamePrefix = packageName + ":";
3256 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3257 final int NA = apps.size();
3258 for (int ia=0; ia<NA; ia++) {
3259 ProcessRecord app = apps.valueAt(ia);
3260 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003261 if (doit) {
3262 procs.add(app);
3263 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003264 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3265 || app.processName.equals(packageName)
3266 || app.processName.startsWith(procNamePrefix)) {
3267 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003268 if (!doit) {
3269 return true;
3270 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003271 app.removed = true;
3272 procs.add(app);
3273 }
3274 }
3275 }
3276 }
3277
3278 int N = procs.size();
3279 for (int i=0; i<N; i++) {
3280 removeProcessLocked(procs.get(i), callerWillRestart);
3281 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003282 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003283 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003284
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003285 private final boolean forceStopPackageLocked(String name, int uid,
3286 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 int i, N;
3288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 if (uid < 0) {
3290 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003291 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003292 } catch (RemoteException e) {
3293 }
3294 }
3295
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003296 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003297 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003298
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003299 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3300 while (badApps.hasNext()) {
3301 SparseArray<Long> ba = badApps.next();
3302 if (ba.get(uid) != null) {
3303 badApps.remove();
3304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 }
3306 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003307
3308 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3309 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003311 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3312 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003314 if (!doit) {
3315 return true;
3316 }
3317 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003318 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 if (r.app != null) {
3320 r.app.removed = true;
3321 }
3322 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003323 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 }
3325 }
3326
3327 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3328 for (ServiceRecord service : mServices.values()) {
3329 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003330 if (!doit) {
3331 return true;
3332 }
3333 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003334 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 if (service.app != null) {
3336 service.app.removed = true;
3337 }
3338 service.app = null;
3339 services.add(service);
3340 }
3341 }
3342
3343 N = services.size();
3344 for (i=0; i<N; i++) {
3345 bringDownServiceLocked(services.get(i), true);
3346 }
3347
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003348 if (doit) {
3349 if (purgeCache) {
3350 AttributeCache ac = AttributeCache.instance();
3351 if (ac != null) {
3352 ac.removePackage(name);
3353 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003354 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003355 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003356 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003357
3358 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 }
3360
3361 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3362 final String name = app.processName;
3363 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003364 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 TAG, "Force removing process " + app + " (" + name
3366 + "/" + uid + ")");
3367
3368 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003369 if (mHeavyWeightProcess == app) {
3370 mHeavyWeightProcess = null;
3371 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003373 boolean needRestart = false;
3374 if (app.pid > 0 && app.pid != MY_PID) {
3375 int pid = app.pid;
3376 synchronized (mPidsSelfLocked) {
3377 mPidsSelfLocked.remove(pid);
3378 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3379 }
3380 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003381 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 Process.killProcess(pid);
3383
3384 if (app.persistent) {
3385 if (!callerWillRestart) {
3386 addAppLocked(app.info);
3387 } else {
3388 needRestart = true;
3389 }
3390 }
3391 } else {
3392 mRemovedProcesses.add(app);
3393 }
3394
3395 return needRestart;
3396 }
3397
3398 private final void processStartTimedOutLocked(ProcessRecord app) {
3399 final int pid = app.pid;
3400 boolean gone = false;
3401 synchronized (mPidsSelfLocked) {
3402 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3403 if (knownApp != null && knownApp.thread == null) {
3404 mPidsSelfLocked.remove(pid);
3405 gone = true;
3406 }
3407 }
3408
3409 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003410 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003411 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003412 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003413 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003414 if (mHeavyWeightProcess == app) {
3415 mHeavyWeightProcess = null;
3416 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3417 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003418 // Take care of any launching providers waiting for this process.
3419 checkAppInLaunchingProvidersLocked(app, true);
3420 // Take care of any services that are waiting for the process.
3421 for (int i=0; i<mPendingServices.size(); i++) {
3422 ServiceRecord sr = mPendingServices.get(i);
3423 if (app.info.uid == sr.appInfo.uid
3424 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003425 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003426 mPendingServices.remove(i);
3427 i--;
3428 bringDownServiceLocked(sr, true);
3429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003431 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003432 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003433 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003434 try {
3435 IBackupManager bm = IBackupManager.Stub.asInterface(
3436 ServiceManager.getService(Context.BACKUP_SERVICE));
3437 bm.agentDisconnected(app.info.packageName);
3438 } catch (RemoteException e) {
3439 // Can't happen; the backup manager is local
3440 }
3441 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003442 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003443 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003444 mPendingBroadcast.state = BroadcastRecord.IDLE;
3445 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003446 mPendingBroadcast = null;
3447 scheduleBroadcastsLocked();
3448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003450 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451 }
3452 }
3453
3454 private final boolean attachApplicationLocked(IApplicationThread thread,
3455 int pid) {
3456
3457 // Find the application record that is being attached... either via
3458 // the pid if we are running in multiple processes, or just pull the
3459 // next app record if we are emulating process with anonymous threads.
3460 ProcessRecord app;
3461 if (pid != MY_PID && pid >= 0) {
3462 synchronized (mPidsSelfLocked) {
3463 app = mPidsSelfLocked.get(pid);
3464 }
3465 } else if (mStartingProcesses.size() > 0) {
3466 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003467 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 } else {
3469 app = null;
3470 }
3471
3472 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003473 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003475 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 if (pid > 0 && pid != MY_PID) {
3477 Process.killProcess(pid);
3478 } else {
3479 try {
3480 thread.scheduleExit();
3481 } catch (Exception e) {
3482 // Ignore exceptions.
3483 }
3484 }
3485 return false;
3486 }
3487
3488 // If this application record is still attached to a previous
3489 // process, clean it up now.
3490 if (app.thread != null) {
3491 handleAppDiedLocked(app, true);
3492 }
3493
3494 // Tell the process all about itself.
3495
Joe Onorato8a9b2202010-02-26 18:56:32 -08003496 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 TAG, "Binding process pid " + pid + " to record " + app);
3498
3499 String processName = app.processName;
3500 try {
3501 thread.asBinder().linkToDeath(new AppDeathRecipient(
3502 app, pid, thread), 0);
3503 } catch (RemoteException e) {
3504 app.resetPackageList();
3505 startProcessLocked(app, "link fail", processName);
3506 return false;
3507 }
3508
Doug Zongker2bec3d42009-12-04 12:52:44 -08003509 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510
3511 app.thread = thread;
3512 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003513 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3514 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 app.forcingToForeground = null;
3516 app.foregroundServices = false;
3517 app.debugging = false;
3518
3519 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3520
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003521 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003522 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003524 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003525 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003526 }
3527
Joe Onorato8a9b2202010-02-26 18:56:32 -08003528 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 TAG, "New app record " + app
3530 + " thread=" + thread.asBinder() + " pid=" + pid);
3531 try {
3532 int testMode = IApplicationThread.DEBUG_OFF;
3533 if (mDebugApp != null && mDebugApp.equals(processName)) {
3534 testMode = mWaitForDebugger
3535 ? IApplicationThread.DEBUG_WAIT
3536 : IApplicationThread.DEBUG_ON;
3537 app.debugging = true;
3538 if (mDebugTransient) {
3539 mDebugApp = mOrigDebugApp;
3540 mWaitForDebugger = mOrigWaitForDebugger;
3541 }
3542 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003543
Christopher Tate181fafa2009-05-14 11:12:14 -07003544 // If the app is being launched for restore or full backup, set it up specially
3545 boolean isRestrictedBackupMode = false;
3546 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3547 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3548 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3549 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003550
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003551 ensurePackageDexOpt(app.instrumentationInfo != null
3552 ? app.instrumentationInfo.packageName
3553 : app.info.packageName);
3554 if (app.instrumentationClass != null) {
3555 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003556 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003557 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003558 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003559 thread.bindApplication(processName, app.instrumentationInfo != null
3560 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003561 app.instrumentationClass, app.instrumentationProfileFile,
3562 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003563 isRestrictedBackupMode || !normalMode,
3564 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003565 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003566 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 } catch (Exception e) {
3568 // todo: Yikes! What should we do? For now we will try to
3569 // start another process, but that could easily get us in
3570 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003571 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572
3573 app.resetPackageList();
3574 startProcessLocked(app, "bind fail", processName);
3575 return false;
3576 }
3577
3578 // Remove this record from the list of starting applications.
3579 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003580 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3581 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 mProcessesOnHold.remove(app);
3583
3584 boolean badApp = false;
3585 boolean didSomething = false;
3586
3587 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003588 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003589 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3591 && processName.equals(hr.processName)) {
3592 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003593 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 didSomething = true;
3595 }
3596 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003597 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003598 + hr.intent.getComponent().flattenToShortString(), e);
3599 badApp = true;
3600 }
3601 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003602 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 }
3604 }
3605
3606 // Find any services that should be running in this process...
3607 if (!badApp && mPendingServices.size() > 0) {
3608 ServiceRecord sr = null;
3609 try {
3610 for (int i=0; i<mPendingServices.size(); i++) {
3611 sr = mPendingServices.get(i);
3612 if (app.info.uid != sr.appInfo.uid
3613 || !processName.equals(sr.processName)) {
3614 continue;
3615 }
3616
3617 mPendingServices.remove(i);
3618 i--;
3619 realStartServiceLocked(sr, app);
3620 didSomething = true;
3621 }
3622 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003623 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 + sr.shortName, e);
3625 badApp = true;
3626 }
3627 }
3628
3629 // Check if the next broadcast receiver is in this process...
3630 BroadcastRecord br = mPendingBroadcast;
3631 if (!badApp && br != null && br.curApp == app) {
3632 try {
3633 mPendingBroadcast = null;
3634 processCurBroadcastLocked(br, app);
3635 didSomething = true;
3636 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003637 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 + br.curComponent.flattenToShortString(), e);
3639 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003640 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3642 br.resultExtras, br.resultAbort, true);
3643 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003644 // We need to reset the state if we fails to start the receiver.
3645 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003646 }
3647 }
3648
Christopher Tate181fafa2009-05-14 11:12:14 -07003649 // Check whether the next backup agent is in this process...
3650 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003651 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003652 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003653 try {
3654 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3655 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003656 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003657 e.printStackTrace();
3658 }
3659 }
3660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 if (badApp) {
3662 // todo: Also need to kill application to deal with all
3663 // kinds of exceptions.
3664 handleAppDiedLocked(app, false);
3665 return false;
3666 }
3667
3668 if (!didSomething) {
3669 updateOomAdjLocked();
3670 }
3671
3672 return true;
3673 }
3674
3675 public final void attachApplication(IApplicationThread thread) {
3676 synchronized (this) {
3677 int callingPid = Binder.getCallingPid();
3678 final long origId = Binder.clearCallingIdentity();
3679 attachApplicationLocked(thread, callingPid);
3680 Binder.restoreCallingIdentity(origId);
3681 }
3682 }
3683
Dianne Hackborne88846e2009-09-30 21:34:25 -07003684 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003686 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003687 Binder.restoreCallingIdentity(origId);
3688 }
3689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003690 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003691 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003692 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 mWindowManager.enableScreenAfterBoot();
3694 }
3695
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003696 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003697 IntentFilter pkgFilter = new IntentFilter();
3698 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3699 pkgFilter.addDataScheme("package");
3700 mContext.registerReceiver(new BroadcastReceiver() {
3701 @Override
3702 public void onReceive(Context context, Intent intent) {
3703 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3704 if (pkgs != null) {
3705 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003706 synchronized (ActivityManagerService.this) {
3707 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3708 setResultCode(Activity.RESULT_OK);
3709 return;
3710 }
3711 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003712 }
3713 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003714 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003715 }, pkgFilter);
3716
3717 synchronized (this) {
3718 // Ensure that any processes we had put on hold are now started
3719 // up.
3720 final int NP = mProcessesOnHold.size();
3721 if (NP > 0) {
3722 ArrayList<ProcessRecord> procs =
3723 new ArrayList<ProcessRecord>(mProcessesOnHold);
3724 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003725 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3726 + procs.get(ip));
3727 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003728 }
3729 }
3730
3731 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003732 // Start looking for apps that are abusing wake locks.
3733 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003734 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003735 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003736 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003737 broadcastIntentLocked(null, null,
3738 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3739 null, null, 0, null, null,
3740 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3741 false, false, MY_PID, Process.SYSTEM_UID);
3742 }
3743 }
3744 }
3745
3746 final void ensureBootCompleted() {
3747 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003748 boolean enableScreen;
3749 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003750 booting = mBooting;
3751 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003752 enableScreen = !mBooted;
3753 mBooted = true;
3754 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003755
3756 if (booting) {
3757 finishBooting();
3758 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003759
3760 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003761 enableScreenAfterBoot();
3762 }
3763 }
3764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 public final void activityPaused(IBinder token, Bundle icicle) {
3766 // Refuse possible leaked file descriptors
3767 if (icicle != null && icicle.hasFileDescriptors()) {
3768 throw new IllegalArgumentException("File descriptors passed in Bundle");
3769 }
3770
3771 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003772 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 Binder.restoreCallingIdentity(origId);
3774 }
3775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 public final void activityStopped(IBinder token, Bitmap thumbnail,
3777 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003778 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003779 TAG, "Activity stopped: token=" + token);
3780
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003781 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782
3783 final long origId = Binder.clearCallingIdentity();
3784
3785 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003786 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003787 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003788 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003789 r.thumbnail = thumbnail;
3790 r.description = description;
3791 r.stopped = true;
3792 r.state = ActivityState.STOPPED;
3793 if (!r.finishing) {
3794 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003795 r.stack.destroyActivityLocked(r, true);
3796 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003797 }
3798 }
3799 }
3800 }
3801
3802 if (r != null) {
3803 sendPendingThumbnail(r, null, null, null, false);
3804 }
3805
3806 trimApplications();
3807
3808 Binder.restoreCallingIdentity(origId);
3809 }
3810
3811 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003812 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003813 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 }
3815
3816 public String getCallingPackage(IBinder token) {
3817 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003818 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003819 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 }
3821 }
3822
3823 public ComponentName getCallingActivity(IBinder token) {
3824 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003825 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 return r != null ? r.intent.getComponent() : null;
3827 }
3828 }
3829
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003830 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003831 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003833 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003834 if (r != null) {
3835 return r.resultTo;
3836 }
3837 }
3838 return null;
3839 }
3840
3841 public ComponentName getActivityClassForToken(IBinder token) {
3842 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003843 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003844 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003845 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003846 return r.intent.getComponent();
3847 }
3848 return null;
3849 }
3850 }
3851
3852 public String getPackageForToken(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.packageName;
3858 }
3859 return null;
3860 }
3861 }
3862
3863 public IIntentSender getIntentSender(int type,
3864 String packageName, IBinder token, String resultWho,
3865 int requestCode, Intent intent, String resolvedType, int flags) {
3866 // Refuse possible leaked file descriptors
3867 if (intent != null && intent.hasFileDescriptors() == true) {
3868 throw new IllegalArgumentException("File descriptors passed in Intent");
3869 }
3870
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003871 if (type == INTENT_SENDER_BROADCAST) {
3872 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3873 throw new IllegalArgumentException(
3874 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3875 }
3876 }
3877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003878 synchronized(this) {
3879 int callingUid = Binder.getCallingUid();
3880 try {
3881 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3882 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003883 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003884 .getPackageUid(packageName);
3885 if (uid != Binder.getCallingUid()) {
3886 String msg = "Permission Denial: getIntentSender() from pid="
3887 + Binder.getCallingPid()
3888 + ", uid=" + Binder.getCallingUid()
3889 + ", (need uid=" + uid + ")"
3890 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003891 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003892 throw new SecurityException(msg);
3893 }
3894 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003895
3896 return getIntentSenderLocked(type, packageName, callingUid,
3897 token, resultWho, requestCode, intent, resolvedType, flags);
3898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003899 } catch (RemoteException e) {
3900 throw new SecurityException(e);
3901 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003902 }
3903 }
3904
3905 IIntentSender getIntentSenderLocked(int type,
3906 String packageName, int callingUid, IBinder token, String resultWho,
3907 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003908 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003909 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003910 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003911 if (index < 0) {
3912 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003914 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003915 if (activity.finishing) {
3916 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003918 }
3919
3920 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3921 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3922 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3923 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3924 |PendingIntent.FLAG_UPDATE_CURRENT);
3925
3926 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3927 type, packageName, activity, resultWho,
3928 requestCode, intent, resolvedType, flags);
3929 WeakReference<PendingIntentRecord> ref;
3930 ref = mIntentSenderRecords.get(key);
3931 PendingIntentRecord rec = ref != null ? ref.get() : null;
3932 if (rec != null) {
3933 if (!cancelCurrent) {
3934 if (updateCurrent) {
3935 rec.key.requestIntent.replaceExtras(intent);
3936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 return rec;
3938 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003939 rec.canceled = true;
3940 mIntentSenderRecords.remove(key);
3941 }
3942 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 return rec;
3944 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003945 rec = new PendingIntentRecord(this, key, callingUid);
3946 mIntentSenderRecords.put(key, rec.ref);
3947 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3948 if (activity.pendingResults == null) {
3949 activity.pendingResults
3950 = new HashSet<WeakReference<PendingIntentRecord>>();
3951 }
3952 activity.pendingResults.add(rec.ref);
3953 }
3954 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003955 }
3956
3957 public void cancelIntentSender(IIntentSender sender) {
3958 if (!(sender instanceof PendingIntentRecord)) {
3959 return;
3960 }
3961 synchronized(this) {
3962 PendingIntentRecord rec = (PendingIntentRecord)sender;
3963 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003964 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003965 .getPackageUid(rec.key.packageName);
3966 if (uid != Binder.getCallingUid()) {
3967 String msg = "Permission Denial: cancelIntentSender() from pid="
3968 + Binder.getCallingPid()
3969 + ", uid=" + Binder.getCallingUid()
3970 + " is not allowed to cancel packges "
3971 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003972 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003973 throw new SecurityException(msg);
3974 }
3975 } catch (RemoteException e) {
3976 throw new SecurityException(e);
3977 }
3978 cancelIntentSenderLocked(rec, true);
3979 }
3980 }
3981
3982 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3983 rec.canceled = true;
3984 mIntentSenderRecords.remove(rec.key);
3985 if (cleanActivity && rec.key.activity != null) {
3986 rec.key.activity.pendingResults.remove(rec.ref);
3987 }
3988 }
3989
3990 public String getPackageForIntentSender(IIntentSender pendingResult) {
3991 if (!(pendingResult instanceof PendingIntentRecord)) {
3992 return null;
3993 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003994 try {
3995 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3996 return res.key.packageName;
3997 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003998 }
3999 return null;
4000 }
4001
4002 public void setProcessLimit(int max) {
4003 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4004 "setProcessLimit()");
4005 mProcessLimit = max;
4006 }
4007
4008 public int getProcessLimit() {
4009 return mProcessLimit;
4010 }
4011
4012 void foregroundTokenDied(ForegroundToken token) {
4013 synchronized (ActivityManagerService.this) {
4014 synchronized (mPidsSelfLocked) {
4015 ForegroundToken cur
4016 = mForegroundProcesses.get(token.pid);
4017 if (cur != token) {
4018 return;
4019 }
4020 mForegroundProcesses.remove(token.pid);
4021 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4022 if (pr == null) {
4023 return;
4024 }
4025 pr.forcingToForeground = null;
4026 pr.foregroundServices = false;
4027 }
4028 updateOomAdjLocked();
4029 }
4030 }
4031
4032 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4033 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4034 "setProcessForeground()");
4035 synchronized(this) {
4036 boolean changed = false;
4037
4038 synchronized (mPidsSelfLocked) {
4039 ProcessRecord pr = mPidsSelfLocked.get(pid);
4040 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004041 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004042 return;
4043 }
4044 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4045 if (oldToken != null) {
4046 oldToken.token.unlinkToDeath(oldToken, 0);
4047 mForegroundProcesses.remove(pid);
4048 pr.forcingToForeground = null;
4049 changed = true;
4050 }
4051 if (isForeground && token != null) {
4052 ForegroundToken newToken = new ForegroundToken() {
4053 public void binderDied() {
4054 foregroundTokenDied(this);
4055 }
4056 };
4057 newToken.pid = pid;
4058 newToken.token = token;
4059 try {
4060 token.linkToDeath(newToken, 0);
4061 mForegroundProcesses.put(pid, newToken);
4062 pr.forcingToForeground = token;
4063 changed = true;
4064 } catch (RemoteException e) {
4065 // If the process died while doing this, we will later
4066 // do the cleanup with the process death link.
4067 }
4068 }
4069 }
4070
4071 if (changed) {
4072 updateOomAdjLocked();
4073 }
4074 }
4075 }
4076
4077 // =========================================================
4078 // PERMISSIONS
4079 // =========================================================
4080
4081 static class PermissionController extends IPermissionController.Stub {
4082 ActivityManagerService mActivityManagerService;
4083 PermissionController(ActivityManagerService activityManagerService) {
4084 mActivityManagerService = activityManagerService;
4085 }
4086
4087 public boolean checkPermission(String permission, int pid, int uid) {
4088 return mActivityManagerService.checkPermission(permission, pid,
4089 uid) == PackageManager.PERMISSION_GRANTED;
4090 }
4091 }
4092
4093 /**
4094 * This can be called with or without the global lock held.
4095 */
4096 int checkComponentPermission(String permission, int pid, int uid,
4097 int reqUid) {
4098 // We might be performing an operation on behalf of an indirect binder
4099 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4100 // client identity accordingly before proceeding.
4101 Identity tlsIdentity = sCallerIdentity.get();
4102 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004103 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4105 uid = tlsIdentity.uid;
4106 pid = tlsIdentity.pid;
4107 }
4108
4109 // Root, system server and our own process get to do everything.
4110 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4111 !Process.supportsProcesses()) {
4112 return PackageManager.PERMISSION_GRANTED;
4113 }
4114 // If the target requires a specific UID, always fail for others.
4115 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004116 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004117 return PackageManager.PERMISSION_DENIED;
4118 }
4119 if (permission == null) {
4120 return PackageManager.PERMISSION_GRANTED;
4121 }
4122 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004123 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004124 .checkUidPermission(permission, uid);
4125 } catch (RemoteException e) {
4126 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004127 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 }
4129 return PackageManager.PERMISSION_DENIED;
4130 }
4131
4132 /**
4133 * As the only public entry point for permissions checking, this method
4134 * can enforce the semantic that requesting a check on a null global
4135 * permission is automatically denied. (Internally a null permission
4136 * string is used when calling {@link #checkComponentPermission} in cases
4137 * when only uid-based security is needed.)
4138 *
4139 * This can be called with or without the global lock held.
4140 */
4141 public int checkPermission(String permission, int pid, int uid) {
4142 if (permission == null) {
4143 return PackageManager.PERMISSION_DENIED;
4144 }
4145 return checkComponentPermission(permission, pid, uid, -1);
4146 }
4147
4148 /**
4149 * Binder IPC calls go through the public entry point.
4150 * This can be called with or without the global lock held.
4151 */
4152 int checkCallingPermission(String permission) {
4153 return checkPermission(permission,
4154 Binder.getCallingPid(),
4155 Binder.getCallingUid());
4156 }
4157
4158 /**
4159 * This can be called with or without the global lock held.
4160 */
4161 void enforceCallingPermission(String permission, String func) {
4162 if (checkCallingPermission(permission)
4163 == PackageManager.PERMISSION_GRANTED) {
4164 return;
4165 }
4166
4167 String msg = "Permission Denial: " + func + " from pid="
4168 + Binder.getCallingPid()
4169 + ", uid=" + Binder.getCallingUid()
4170 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004171 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 throw new SecurityException(msg);
4173 }
4174
4175 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004176 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4177 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4178 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4179 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4180 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004181 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004182 // Is the component private from the target uid?
4183 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4184
4185 // Acceptable if the there is no read permission needed from the
4186 // target or the target is holding the read permission.
4187 if (!readPerm) {
4188 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004190 == PackageManager.PERMISSION_GRANTED)) {
4191 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004192 }
4193 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004194
4195 // Acceptable if the there is no write permission needed from the
4196 // target or the target is holding the read permission.
4197 if (!writePerm) {
4198 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004199 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004200 == PackageManager.PERMISSION_GRANTED)) {
4201 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 }
4203 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004204
4205 // Acceptable if there is a path permission matching the URI that
4206 // the target holds the permission on.
4207 PathPermission[] pps = pi.pathPermissions;
4208 if (pps != null && (!readPerm || !writePerm)) {
4209 final String path = uri.getPath();
4210 int i = pps.length;
4211 while (i > 0 && (!readPerm || !writePerm)) {
4212 i--;
4213 PathPermission pp = pps[i];
4214 if (!readPerm) {
4215 final String pprperm = pp.getReadPermission();
4216 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4217 + pprperm + " for " + pp.getPath()
4218 + ": match=" + pp.match(path)
4219 + " check=" + pm.checkUidPermission(pprperm, uid));
4220 if (pprperm != null && pp.match(path) &&
4221 (pm.checkUidPermission(pprperm, uid)
4222 == PackageManager.PERMISSION_GRANTED)) {
4223 readPerm = true;
4224 }
4225 }
4226 if (!writePerm) {
4227 final String ppwperm = pp.getWritePermission();
4228 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4229 + ppwperm + " for " + pp.getPath()
4230 + ": match=" + pp.match(path)
4231 + " check=" + pm.checkUidPermission(ppwperm, uid));
4232 if (ppwperm != null && pp.match(path) &&
4233 (pm.checkUidPermission(ppwperm, uid)
4234 == PackageManager.PERMISSION_GRANTED)) {
4235 writePerm = true;
4236 }
4237 }
4238 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 } catch (RemoteException e) {
4241 return false;
4242 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004243
4244 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 }
4246
4247 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4248 int modeFlags) {
4249 // Root gets to do everything.
4250 if (uid == 0 || !Process.supportsProcesses()) {
4251 return true;
4252 }
4253 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4254 if (perms == null) return false;
4255 UriPermission perm = perms.get(uri);
4256 if (perm == null) return false;
4257 return (modeFlags&perm.modeFlags) == modeFlags;
4258 }
4259
4260 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4261 // Another redirected-binder-call permissions check as in
4262 // {@link checkComponentPermission}.
4263 Identity tlsIdentity = sCallerIdentity.get();
4264 if (tlsIdentity != null) {
4265 uid = tlsIdentity.uid;
4266 pid = tlsIdentity.pid;
4267 }
4268
4269 // Our own process gets to do everything.
4270 if (pid == MY_PID) {
4271 return PackageManager.PERMISSION_GRANTED;
4272 }
4273 synchronized(this) {
4274 return checkUriPermissionLocked(uri, uid, modeFlags)
4275 ? PackageManager.PERMISSION_GRANTED
4276 : PackageManager.PERMISSION_DENIED;
4277 }
4278 }
4279
Dianne Hackborn39792d22010-08-19 18:01:52 -07004280 /**
4281 * Check if the targetPkg can be granted permission to access uri by
4282 * the callingUid using the given modeFlags. Throws a security exception
4283 * if callingUid is not allowed to do this. Returns the uid of the target
4284 * if the URI permission grant should be performed; returns -1 if it is not
4285 * needed (for example targetPkg already has permission to access the URI).
4286 */
4287 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4288 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4290 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4291 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004292 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004293 }
4294
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004295 if (targetPkg != null) {
4296 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4297 "Checking grant " + targetPkg + " permission to " + uri);
4298 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004299
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004300 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301
4302 // If this is not a content: uri, we can't do anything with it.
4303 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004304 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004305 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004306 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 }
4308
4309 String name = uri.getAuthority();
4310 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004311 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004312 if (cpr != null) {
4313 pi = cpr.info;
4314 } else {
4315 try {
4316 pi = pm.resolveContentProvider(name,
4317 PackageManager.GET_URI_PERMISSION_PATTERNS);
4318 } catch (RemoteException ex) {
4319 }
4320 }
4321 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004322 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004323 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004324 }
4325
4326 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004327 if (targetPkg != null) {
4328 try {
4329 targetUid = pm.getPackageUid(targetPkg);
4330 if (targetUid < 0) {
4331 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4332 "Can't grant URI permission no uid for: " + targetPkg);
4333 return -1;
4334 }
4335 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004336 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004337 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004338 } else {
4339 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 }
4341
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004342 if (targetUid >= 0) {
4343 // First... does the target actually need this permission?
4344 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4345 // No need to grant the target this permission.
4346 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4347 "Target " + targetPkg + " already has full permission to " + uri);
4348 return -1;
4349 }
4350 } else {
4351 // First... there is no target package, so can anyone access it?
4352 boolean allowed = pi.exported;
4353 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4354 if (pi.readPermission != null) {
4355 allowed = false;
4356 }
4357 }
4358 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4359 if (pi.writePermission != null) {
4360 allowed = false;
4361 }
4362 }
4363 if (allowed) {
4364 return -1;
4365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 }
4367
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004368 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 if (!pi.grantUriPermissions) {
4370 throw new SecurityException("Provider " + pi.packageName
4371 + "/" + pi.name
4372 + " does not allow granting of Uri permissions (uri "
4373 + uri + ")");
4374 }
4375 if (pi.uriPermissionPatterns != null) {
4376 final int N = pi.uriPermissionPatterns.length;
4377 boolean allowed = false;
4378 for (int i=0; i<N; i++) {
4379 if (pi.uriPermissionPatterns[i] != null
4380 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4381 allowed = true;
4382 break;
4383 }
4384 }
4385 if (!allowed) {
4386 throw new SecurityException("Provider " + pi.packageName
4387 + "/" + pi.name
4388 + " does not allow granting of permission to path of Uri "
4389 + uri);
4390 }
4391 }
4392
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004393 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004395 if (callingUid != Process.myUid()) {
4396 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4397 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4398 throw new SecurityException("Uid " + callingUid
4399 + " does not have permission to uri " + uri);
4400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004401 }
4402 }
4403
Dianne Hackborn39792d22010-08-19 18:01:52 -07004404 return targetUid;
4405 }
4406
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004407 public int checkGrantUriPermission(int callingUid, String targetPkg,
4408 Uri uri, int modeFlags) {
4409 synchronized(this) {
4410 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4411 }
4412 }
4413
Dianne Hackborn39792d22010-08-19 18:01:52 -07004414 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4415 Uri uri, int modeFlags, UriPermissionOwner owner) {
4416 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4417 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4418 if (modeFlags == 0) {
4419 return;
4420 }
4421
4422 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 // to the uri, and the target doesn't. Let's now give this to
4424 // the target.
4425
Joe Onorato8a9b2202010-02-26 18:56:32 -08004426 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004427 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004429 HashMap<Uri, UriPermission> targetUris
4430 = mGrantedUriPermissions.get(targetUid);
4431 if (targetUris == null) {
4432 targetUris = new HashMap<Uri, UriPermission>();
4433 mGrantedUriPermissions.put(targetUid, targetUris);
4434 }
4435
4436 UriPermission perm = targetUris.get(uri);
4437 if (perm == null) {
4438 perm = new UriPermission(targetUid, uri);
4439 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004442 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004443 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 perm.globalModeFlags |= modeFlags;
4445 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004446 perm.readOwners.add(owner);
4447 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004448 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004449 perm.writeOwners.add(owner);
4450 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 }
4452 }
4453
Dianne Hackborn39792d22010-08-19 18:01:52 -07004454 void grantUriPermissionLocked(int callingUid,
4455 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004456 if (targetPkg == null) {
4457 throw new NullPointerException("targetPkg");
4458 }
4459
Dianne Hackborn39792d22010-08-19 18:01:52 -07004460 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4461 if (targetUid < 0) {
4462 return;
4463 }
4464
4465 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4466 }
4467
4468 /**
4469 * Like checkGrantUriPermissionLocked, but takes an Intent.
4470 */
4471 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4472 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004473 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004474 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004475 + " from " + intent + "; flags=0x"
4476 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4477
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004478 if (targetPkg == null) {
4479 throw new NullPointerException("targetPkg");
4480 }
4481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004483 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 }
4485 Uri data = intent.getData();
4486 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004487 return -1;
4488 }
4489 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4490 intent.getFlags());
4491 }
4492
4493 /**
4494 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4495 */
4496 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4497 String targetPkg, Intent intent, UriPermissionOwner owner) {
4498 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4499 intent.getFlags(), owner);
4500 }
4501
4502 void grantUriPermissionFromIntentLocked(int callingUid,
4503 String targetPkg, Intent intent, UriPermissionOwner owner) {
4504 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4505 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 return;
4507 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004508
4509 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 }
4511
4512 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4513 Uri uri, int modeFlags) {
4514 synchronized(this) {
4515 final ProcessRecord r = getRecordForAppLocked(caller);
4516 if (r == null) {
4517 throw new SecurityException("Unable to find app for caller "
4518 + caller
4519 + " when granting permission to uri " + uri);
4520 }
4521 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004522 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004523 }
4524 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004525 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004526 }
4527
4528 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4529 null);
4530 }
4531 }
4532
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004533 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4535 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4536 HashMap<Uri, UriPermission> perms
4537 = mGrantedUriPermissions.get(perm.uid);
4538 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004539 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004540 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004541 perms.remove(perm.uri);
4542 if (perms.size() == 0) {
4543 mGrantedUriPermissions.remove(perm.uid);
4544 }
4545 }
4546 }
4547 }
4548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004549 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4550 int modeFlags) {
4551 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4552 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4553 if (modeFlags == 0) {
4554 return;
4555 }
4556
Joe Onorato8a9b2202010-02-26 18:56:32 -08004557 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004558 "Revoking all granted permissions to " + uri);
4559
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004560 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561
4562 final String authority = uri.getAuthority();
4563 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004564 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565 if (cpr != null) {
4566 pi = cpr.info;
4567 } else {
4568 try {
4569 pi = pm.resolveContentProvider(authority,
4570 PackageManager.GET_URI_PERMISSION_PATTERNS);
4571 } catch (RemoteException ex) {
4572 }
4573 }
4574 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004575 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 return;
4577 }
4578
4579 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004580 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 // Right now, if you are not the original owner of the permission,
4582 // you are not allowed to revoke it.
4583 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4584 throw new SecurityException("Uid " + callingUid
4585 + " does not have permission to uri " + uri);
4586 //}
4587 }
4588
4589 // Go through all of the permissions and remove any that match.
4590 final List<String> SEGMENTS = uri.getPathSegments();
4591 if (SEGMENTS != null) {
4592 final int NS = SEGMENTS.size();
4593 int N = mGrantedUriPermissions.size();
4594 for (int i=0; i<N; i++) {
4595 HashMap<Uri, UriPermission> perms
4596 = mGrantedUriPermissions.valueAt(i);
4597 Iterator<UriPermission> it = perms.values().iterator();
4598 toploop:
4599 while (it.hasNext()) {
4600 UriPermission perm = it.next();
4601 Uri targetUri = perm.uri;
4602 if (!authority.equals(targetUri.getAuthority())) {
4603 continue;
4604 }
4605 List<String> targetSegments = targetUri.getPathSegments();
4606 if (targetSegments == null) {
4607 continue;
4608 }
4609 if (targetSegments.size() < NS) {
4610 continue;
4611 }
4612 for (int j=0; j<NS; j++) {
4613 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4614 continue toploop;
4615 }
4616 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004617 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004618 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 perm.clearModes(modeFlags);
4620 if (perm.modeFlags == 0) {
4621 it.remove();
4622 }
4623 }
4624 if (perms.size() == 0) {
4625 mGrantedUriPermissions.remove(
4626 mGrantedUriPermissions.keyAt(i));
4627 N--;
4628 i--;
4629 }
4630 }
4631 }
4632 }
4633
4634 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4635 int modeFlags) {
4636 synchronized(this) {
4637 final ProcessRecord r = getRecordForAppLocked(caller);
4638 if (r == null) {
4639 throw new SecurityException("Unable to find app for caller "
4640 + caller
4641 + " when revoking permission to uri " + uri);
4642 }
4643 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004644 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 return;
4646 }
4647
4648 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4649 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4650 if (modeFlags == 0) {
4651 return;
4652 }
4653
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004654 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655
4656 final String authority = uri.getAuthority();
4657 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004658 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 if (cpr != null) {
4660 pi = cpr.info;
4661 } else {
4662 try {
4663 pi = pm.resolveContentProvider(authority,
4664 PackageManager.GET_URI_PERMISSION_PATTERNS);
4665 } catch (RemoteException ex) {
4666 }
4667 }
4668 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004669 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 return;
4671 }
4672
4673 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4674 }
4675 }
4676
Dianne Hackborn7e269642010-08-25 19:50:20 -07004677 @Override
4678 public IBinder newUriPermissionOwner(String name) {
4679 synchronized(this) {
4680 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4681 return owner.getExternalTokenLocked();
4682 }
4683 }
4684
4685 @Override
4686 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4687 Uri uri, int modeFlags) {
4688 synchronized(this) {
4689 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4690 if (owner == null) {
4691 throw new IllegalArgumentException("Unknown owner: " + token);
4692 }
4693 if (fromUid != Binder.getCallingUid()) {
4694 if (Binder.getCallingUid() != Process.myUid()) {
4695 // Only system code can grant URI permissions on behalf
4696 // of other users.
4697 throw new SecurityException("nice try");
4698 }
4699 }
4700 if (targetPkg == null) {
4701 throw new IllegalArgumentException("null target");
4702 }
4703 if (uri == null) {
4704 throw new IllegalArgumentException("null uri");
4705 }
4706
4707 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4708 }
4709 }
4710
4711 @Override
4712 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4713 synchronized(this) {
4714 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4715 if (owner == null) {
4716 throw new IllegalArgumentException("Unknown owner: " + token);
4717 }
4718
4719 if (uri == null) {
4720 owner.removeUriPermissionsLocked(mode);
4721 } else {
4722 owner.removeUriPermissionLocked(uri, mode);
4723 }
4724 }
4725 }
4726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4728 synchronized (this) {
4729 ProcessRecord app =
4730 who != null ? getRecordForAppLocked(who) : null;
4731 if (app == null) return;
4732
4733 Message msg = Message.obtain();
4734 msg.what = WAIT_FOR_DEBUGGER_MSG;
4735 msg.obj = app;
4736 msg.arg1 = waiting ? 1 : 0;
4737 mHandler.sendMessage(msg);
4738 }
4739 }
4740
4741 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4742 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004743 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004744 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004745 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 }
4747
4748 // =========================================================
4749 // TASK MANAGEMENT
4750 // =========================================================
4751
4752 public List getTasks(int maxNum, int flags,
4753 IThumbnailReceiver receiver) {
4754 ArrayList list = new ArrayList();
4755
4756 PendingThumbnailsRecord pending = null;
4757 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004758 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759
4760 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004761 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004762 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4763 + ", receiver=" + receiver);
4764
4765 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4766 != PackageManager.PERMISSION_GRANTED) {
4767 if (receiver != null) {
4768 // If the caller wants to wait for pending thumbnails,
4769 // it ain't gonna get them.
4770 try {
4771 receiver.finished();
4772 } catch (RemoteException ex) {
4773 }
4774 }
4775 String msg = "Permission Denial: getTasks() from pid="
4776 + Binder.getCallingPid()
4777 + ", uid=" + Binder.getCallingUid()
4778 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004779 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 throw new SecurityException(msg);
4781 }
4782
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004783 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004784 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004785 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004786 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004787 CharSequence topDescription = null;
4788 TaskRecord curTask = null;
4789 int numActivities = 0;
4790 int numRunning = 0;
4791 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004792 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004793 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004794 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004795
4796 // Initialize state for next task if needed.
4797 if (top == null ||
4798 (top.state == ActivityState.INITIALIZING
4799 && top.task == r.task)) {
4800 top = r;
4801 topDescription = r.description;
4802 curTask = r.task;
4803 numActivities = numRunning = 0;
4804 }
4805
4806 // Add 'r' into the current task.
4807 numActivities++;
4808 if (r.app != null && r.app.thread != null) {
4809 numRunning++;
4810 }
4811 if (topDescription == null) {
4812 topDescription = r.description;
4813 }
4814
Joe Onorato8a9b2202010-02-26 18:56:32 -08004815 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816 TAG, r.intent.getComponent().flattenToShortString()
4817 + ": task=" + r.task);
4818
4819 // If the next one is a different task, generate a new
4820 // TaskInfo entry for what we have.
4821 if (next == null || next.task != curTask) {
4822 ActivityManager.RunningTaskInfo ci
4823 = new ActivityManager.RunningTaskInfo();
4824 ci.id = curTask.taskId;
4825 ci.baseActivity = r.intent.getComponent();
4826 ci.topActivity = top.intent.getComponent();
4827 ci.thumbnail = top.thumbnail;
4828 ci.description = topDescription;
4829 ci.numActivities = numActivities;
4830 ci.numRunning = numRunning;
4831 //System.out.println(
4832 // "#" + maxNum + ": " + " descr=" + ci.description);
4833 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004834 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 TAG, "State=" + top.state + "Idle=" + top.idle
4836 + " app=" + top.app
4837 + " thr=" + (top.app != null ? top.app.thread : null));
4838 if (top.state == ActivityState.RESUMED
4839 || top.state == ActivityState.PAUSING) {
4840 if (top.idle && top.app != null
4841 && top.app.thread != null) {
4842 topRecord = top;
4843 topThumbnail = top.app.thread;
4844 } else {
4845 top.thumbnailNeeded = true;
4846 }
4847 }
4848 if (pending == null) {
4849 pending = new PendingThumbnailsRecord(receiver);
4850 }
4851 pending.pendingRecords.add(top);
4852 }
4853 list.add(ci);
4854 maxNum--;
4855 top = null;
4856 }
4857 }
4858
4859 if (pending != null) {
4860 mPendingThumbnails.add(pending);
4861 }
4862 }
4863
Joe Onorato8a9b2202010-02-26 18:56:32 -08004864 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865
4866 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004867 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 try {
4869 topThumbnail.requestThumbnail(topRecord);
4870 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004871 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004872 sendPendingThumbnail(null, topRecord, null, null, true);
4873 }
4874 }
4875
4876 if (pending == null && receiver != null) {
4877 // In this case all thumbnails were available and the client
4878 // is being asked to be told when the remaining ones come in...
4879 // which is unusually, since the top-most currently running
4880 // activity should never have a canned thumbnail! Oh well.
4881 try {
4882 receiver.finished();
4883 } catch (RemoteException ex) {
4884 }
4885 }
4886
4887 return list;
4888 }
4889
4890 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4891 int flags) {
4892 synchronized (this) {
4893 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4894 "getRecentTasks()");
4895
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004896 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004898 final int N = mRecentTasks.size();
4899 ArrayList<ActivityManager.RecentTaskInfo> res
4900 = new ArrayList<ActivityManager.RecentTaskInfo>(
4901 maxNum < N ? maxNum : N);
4902 for (int i=0; i<N && maxNum > 0; i++) {
4903 TaskRecord tr = mRecentTasks.get(i);
4904 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4905 || (tr.intent == null)
4906 || ((tr.intent.getFlags()
4907 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4908 ActivityManager.RecentTaskInfo rti
4909 = new ActivityManager.RecentTaskInfo();
4910 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4911 rti.baseIntent = new Intent(
4912 tr.intent != null ? tr.intent : tr.affinityIntent);
4913 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004914
4915 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4916 // Check whether this activity is currently available.
4917 try {
4918 if (rti.origActivity != null) {
4919 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4920 continue;
4921 }
4922 } else if (rti.baseIntent != null) {
4923 if (pm.queryIntentActivities(rti.baseIntent,
4924 null, 0) == null) {
4925 continue;
4926 }
4927 }
4928 } catch (RemoteException e) {
4929 // Will never happen.
4930 }
4931 }
4932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 res.add(rti);
4934 maxNum--;
4935 }
4936 }
4937 return res;
4938 }
4939 }
4940
4941 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4942 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004943 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 TaskRecord jt = startTask;
4945
4946 // First look backwards
4947 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004948 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949 if (r.task != jt) {
4950 jt = r.task;
4951 if (affinity.equals(jt.affinity)) {
4952 return j;
4953 }
4954 }
4955 }
4956
4957 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004958 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 jt = startTask;
4960 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004961 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004962 if (r.task != jt) {
4963 if (affinity.equals(jt.affinity)) {
4964 return j;
4965 }
4966 jt = r.task;
4967 }
4968 }
4969
4970 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004971 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004972 return N-1;
4973 }
4974
4975 return -1;
4976 }
4977
4978 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004979 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980 */
4981 public void moveTaskToFront(int task) {
4982 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4983 "moveTaskToFront()");
4984
4985 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004986 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4987 Binder.getCallingUid(), "Task to front")) {
4988 return;
4989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 final long origId = Binder.clearCallingIdentity();
4991 try {
4992 int N = mRecentTasks.size();
4993 for (int i=0; i<N; i++) {
4994 TaskRecord tr = mRecentTasks.get(i);
4995 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004996 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004997 return;
4998 }
4999 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005000 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5001 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005002 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005003 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005004 return;
5005 }
5006 }
5007 } finally {
5008 Binder.restoreCallingIdentity(origId);
5009 }
5010 }
5011 }
5012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 public void moveTaskToBack(int task) {
5014 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5015 "moveTaskToBack()");
5016
5017 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005018 if (mMainStack.mResumedActivity != null
5019 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005020 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5021 Binder.getCallingUid(), "Task to back")) {
5022 return;
5023 }
5024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005026 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005027 Binder.restoreCallingIdentity(origId);
5028 }
5029 }
5030
5031 /**
5032 * Moves an activity, and all of the other activities within the same task, to the bottom
5033 * of the history stack. The activity's order within the task is unchanged.
5034 *
5035 * @param token A reference to the activity we wish to move
5036 * @param nonRoot If false then this only works if the activity is the root
5037 * of a task; if true it will work for any activity in a task.
5038 * @return Returns true if the move completed, false if not.
5039 */
5040 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5041 synchronized(this) {
5042 final long origId = Binder.clearCallingIdentity();
5043 int taskId = getTaskForActivityLocked(token, !nonRoot);
5044 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005045 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 }
5047 Binder.restoreCallingIdentity(origId);
5048 }
5049 return false;
5050 }
5051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005052 public void moveTaskBackwards(int task) {
5053 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5054 "moveTaskBackwards()");
5055
5056 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005057 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5058 Binder.getCallingUid(), "Task backwards")) {
5059 return;
5060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005061 final long origId = Binder.clearCallingIdentity();
5062 moveTaskBackwardsLocked(task);
5063 Binder.restoreCallingIdentity(origId);
5064 }
5065 }
5066
5067 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005068 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005069 }
5070
5071 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5072 synchronized(this) {
5073 return getTaskForActivityLocked(token, onlyRoot);
5074 }
5075 }
5076
5077 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005078 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 TaskRecord lastTask = null;
5080 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005081 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005082 if (r == token) {
5083 if (!onlyRoot || lastTask != r.task) {
5084 return r.task.taskId;
5085 }
5086 return -1;
5087 }
5088 lastTask = r.task;
5089 }
5090
5091 return -1;
5092 }
5093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005094 public void finishOtherInstances(IBinder token, ComponentName className) {
5095 synchronized(this) {
5096 final long origId = Binder.clearCallingIdentity();
5097
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005098 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 TaskRecord lastTask = null;
5100 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005101 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 if (r.realActivity.equals(className)
5103 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005104 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 null, "others")) {
5106 i--;
5107 N--;
5108 }
5109 }
5110 lastTask = r.task;
5111 }
5112
5113 Binder.restoreCallingIdentity(origId);
5114 }
5115 }
5116
5117 // =========================================================
5118 // THUMBNAILS
5119 // =========================================================
5120
5121 public void reportThumbnail(IBinder token,
5122 Bitmap thumbnail, CharSequence description) {
5123 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5124 final long origId = Binder.clearCallingIdentity();
5125 sendPendingThumbnail(null, token, thumbnail, description, true);
5126 Binder.restoreCallingIdentity(origId);
5127 }
5128
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005129 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 Bitmap thumbnail, CharSequence description, boolean always) {
5131 TaskRecord task = null;
5132 ArrayList receivers = null;
5133
5134 //System.out.println("Send pending thumbnail: " + r);
5135
5136 synchronized(this) {
5137 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005138 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 if (index < 0) {
5140 return;
5141 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005142 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005143 }
5144 if (thumbnail == null) {
5145 thumbnail = r.thumbnail;
5146 description = r.description;
5147 }
5148 if (thumbnail == null && !always) {
5149 // If there is no thumbnail, and this entry is not actually
5150 // going away, then abort for now and pick up the next
5151 // thumbnail we get.
5152 return;
5153 }
5154 task = r.task;
5155
5156 int N = mPendingThumbnails.size();
5157 int i=0;
5158 while (i<N) {
5159 PendingThumbnailsRecord pr =
5160 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5161 //System.out.println("Looking in " + pr.pendingRecords);
5162 if (pr.pendingRecords.remove(r)) {
5163 if (receivers == null) {
5164 receivers = new ArrayList();
5165 }
5166 receivers.add(pr);
5167 if (pr.pendingRecords.size() == 0) {
5168 pr.finished = true;
5169 mPendingThumbnails.remove(i);
5170 N--;
5171 continue;
5172 }
5173 }
5174 i++;
5175 }
5176 }
5177
5178 if (receivers != null) {
5179 final int N = receivers.size();
5180 for (int i=0; i<N; i++) {
5181 try {
5182 PendingThumbnailsRecord pr =
5183 (PendingThumbnailsRecord)receivers.get(i);
5184 pr.receiver.newThumbnail(
5185 task != null ? task.taskId : -1, thumbnail, description);
5186 if (pr.finished) {
5187 pr.receiver.finished();
5188 }
5189 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005190 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 }
5192 }
5193 }
5194 }
5195
5196 // =========================================================
5197 // CONTENT PROVIDERS
5198 // =========================================================
5199
5200 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5201 List providers = null;
5202 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005203 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005204 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005205 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 } catch (RemoteException ex) {
5207 }
5208 if (providers != null) {
5209 final int N = providers.size();
5210 for (int i=0; i<N; i++) {
5211 ProviderInfo cpi =
5212 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005213 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005214 if (cpr == null) {
5215 cpr = new ContentProviderRecord(cpi, app.info);
5216 mProvidersByClass.put(cpi.name, cpr);
5217 }
5218 app.pubProviders.put(cpi.name, cpr);
5219 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005220 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005221 }
5222 }
5223 return providers;
5224 }
5225
5226 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005227 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5229 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5230 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5231 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005232 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 return null;
5234 }
5235 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5236 cpi.exported ? -1 : cpi.applicationInfo.uid)
5237 == PackageManager.PERMISSION_GRANTED) {
5238 return null;
5239 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005240
5241 PathPermission[] pps = cpi.pathPermissions;
5242 if (pps != null) {
5243 int i = pps.length;
5244 while (i > 0) {
5245 i--;
5246 PathPermission pp = pps[i];
5247 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5248 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005249 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005250 return null;
5251 }
5252 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5253 cpi.exported ? -1 : cpi.applicationInfo.uid)
5254 == PackageManager.PERMISSION_GRANTED) {
5255 return null;
5256 }
5257 }
5258 }
5259
Dianne Hackbornb424b632010-08-18 15:59:05 -07005260 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5261 if (perms != null) {
5262 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5263 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5264 return null;
5265 }
5266 }
5267 }
5268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 String msg = "Permission Denial: opening provider " + cpi.name
5270 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5271 + ", uid=" + callingUid + ") requires "
5272 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005273 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 return msg;
5275 }
5276
5277 private final ContentProviderHolder getContentProviderImpl(
5278 IApplicationThread caller, String name) {
5279 ContentProviderRecord cpr;
5280 ProviderInfo cpi = null;
5281
5282 synchronized(this) {
5283 ProcessRecord r = null;
5284 if (caller != null) {
5285 r = getRecordForAppLocked(caller);
5286 if (r == null) {
5287 throw new SecurityException(
5288 "Unable to find app for caller " + caller
5289 + " (pid=" + Binder.getCallingPid()
5290 + ") when getting content provider " + name);
5291 }
5292 }
5293
5294 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005295 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 if (cpr != null) {
5297 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005298 String msg;
5299 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5300 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 }
5302
5303 if (r != null && cpr.canRunHere(r)) {
5304 // This provider has been published or is in the process
5305 // of being published... but it is also allowed to run
5306 // in the caller's process, so don't make a connection
5307 // and just let the caller instantiate its own instance.
5308 if (cpr.provider != null) {
5309 // don't give caller the provider object, it needs
5310 // to make its own.
5311 cpr = new ContentProviderRecord(cpr);
5312 }
5313 return cpr;
5314 }
5315
5316 final long origId = Binder.clearCallingIdentity();
5317
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005318 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005319 // return it right away.
5320 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005321 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005322 "Adding provider requested by "
5323 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005324 + cpr.info.processName);
5325 Integer cnt = r.conProviders.get(cpr);
5326 if (cnt == null) {
5327 r.conProviders.put(cpr, new Integer(1));
5328 } else {
5329 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5330 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005332 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5333 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005334 // make sure to count it as being accessed and thus
5335 // back up on the LRU list. This is good because
5336 // content providers are often expensive to start.
5337 updateLruProcessLocked(cpr.app, false, true);
5338 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005339 } else {
5340 cpr.externals++;
5341 }
5342
5343 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 updateOomAdjLocked(cpr.app);
5345 }
5346
5347 Binder.restoreCallingIdentity(origId);
5348
5349 } else {
5350 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005351 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005352 resolveContentProvider(name,
5353 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 } catch (RemoteException ex) {
5355 }
5356 if (cpi == null) {
5357 return null;
5358 }
5359
Dianne Hackbornb424b632010-08-18 15:59:05 -07005360 String msg;
5361 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5362 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 }
5364
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005365 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005366 && !cpi.processName.equals("system")) {
5367 // If this content provider does not run in the system
5368 // process, and the system is not yet ready to run other
5369 // processes, then fail fast instead of hanging.
5370 throw new IllegalArgumentException(
5371 "Attempt to launch content provider before system ready");
5372 }
5373
Dianne Hackborn860755f2010-06-03 18:47:52 -07005374 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 final boolean firstClass = cpr == null;
5376 if (firstClass) {
5377 try {
5378 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005379 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005380 getApplicationInfo(
5381 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005382 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005383 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005384 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005385 + cpi.name);
5386 return null;
5387 }
5388 cpr = new ContentProviderRecord(cpi, ai);
5389 } catch (RemoteException ex) {
5390 // pm is in same process, this will never happen.
5391 }
5392 }
5393
5394 if (r != null && cpr.canRunHere(r)) {
5395 // If this is a multiprocess provider, then just return its
5396 // info and allow the caller to instantiate it. Only do
5397 // this if the provider is the same user as the caller's
5398 // process, or can run as root (so can be in any process).
5399 return cpr;
5400 }
5401
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005402 if (DEBUG_PROVIDER) {
5403 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005404 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005405 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005406 }
5407
5408 // This is single process, and our app is now connecting to it.
5409 // See if we are already in the process of launching this
5410 // provider.
5411 final int N = mLaunchingProviders.size();
5412 int i;
5413 for (i=0; i<N; i++) {
5414 if (mLaunchingProviders.get(i) == cpr) {
5415 break;
5416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005417 }
5418
5419 // If the provider is not already being launched, then get it
5420 // started.
5421 if (i >= N) {
5422 final long origId = Binder.clearCallingIdentity();
5423 ProcessRecord proc = startProcessLocked(cpi.processName,
5424 cpr.appInfo, false, 0, "content provider",
5425 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005426 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005428 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 + cpi.applicationInfo.packageName + "/"
5430 + cpi.applicationInfo.uid + " for provider "
5431 + name + ": process is bad");
5432 return null;
5433 }
5434 cpr.launchingApp = proc;
5435 mLaunchingProviders.add(cpr);
5436 Binder.restoreCallingIdentity(origId);
5437 }
5438
5439 // Make sure the provider is published (the same provider class
5440 // may be published under multiple names).
5441 if (firstClass) {
5442 mProvidersByClass.put(cpi.name, cpr);
5443 }
5444 mProvidersByName.put(name, cpr);
5445
5446 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005447 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005448 "Adding provider requested by "
5449 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005450 + cpr.info.processName);
5451 Integer cnt = r.conProviders.get(cpr);
5452 if (cnt == null) {
5453 r.conProviders.put(cpr, new Integer(1));
5454 } else {
5455 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005457 cpr.clients.add(r);
5458 } else {
5459 cpr.externals++;
5460 }
5461 }
5462 }
5463
5464 // Wait for the provider to be published...
5465 synchronized (cpr) {
5466 while (cpr.provider == null) {
5467 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005468 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 + cpi.applicationInfo.packageName + "/"
5470 + cpi.applicationInfo.uid + " for provider "
5471 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005472 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005473 cpi.applicationInfo.packageName,
5474 cpi.applicationInfo.uid, name);
5475 return null;
5476 }
5477 try {
5478 cpr.wait();
5479 } catch (InterruptedException ex) {
5480 }
5481 }
5482 }
5483 return cpr;
5484 }
5485
5486 public final ContentProviderHolder getContentProvider(
5487 IApplicationThread caller, String name) {
5488 if (caller == null) {
5489 String msg = "null IApplicationThread when getting content provider "
5490 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005491 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005492 throw new SecurityException(msg);
5493 }
5494
5495 return getContentProviderImpl(caller, name);
5496 }
5497
5498 private ContentProviderHolder getContentProviderExternal(String name) {
5499 return getContentProviderImpl(null, name);
5500 }
5501
5502 /**
5503 * Drop a content provider from a ProcessRecord's bookkeeping
5504 * @param cpr
5505 */
5506 public void removeContentProvider(IApplicationThread caller, String name) {
5507 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005508 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005510 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005511 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005512 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 return;
5514 }
5515 final ProcessRecord r = getRecordForAppLocked(caller);
5516 if (r == null) {
5517 throw new SecurityException(
5518 "Unable to find app for caller " + caller +
5519 " when removing content provider " + name);
5520 }
5521 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005522 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005523 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005524 + r.info.processName + " from process "
5525 + localCpr.appInfo.processName);
5526 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005528 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005529 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 return;
5531 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005532 Integer cnt = r.conProviders.get(localCpr);
5533 if (cnt == null || cnt.intValue() <= 1) {
5534 localCpr.clients.remove(r);
5535 r.conProviders.remove(localCpr);
5536 } else {
5537 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005539 }
5540 updateOomAdjLocked();
5541 }
5542 }
5543
5544 private void removeContentProviderExternal(String name) {
5545 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005546 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005547 if(cpr == null) {
5548 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005549 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005550 return;
5551 }
5552
5553 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005554 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005555 localCpr.externals--;
5556 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005557 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 }
5559 updateOomAdjLocked();
5560 }
5561 }
5562
5563 public final void publishContentProviders(IApplicationThread caller,
5564 List<ContentProviderHolder> providers) {
5565 if (providers == null) {
5566 return;
5567 }
5568
5569 synchronized(this) {
5570 final ProcessRecord r = getRecordForAppLocked(caller);
5571 if (r == null) {
5572 throw new SecurityException(
5573 "Unable to find app for caller " + caller
5574 + " (pid=" + Binder.getCallingPid()
5575 + ") when publishing content providers");
5576 }
5577
5578 final long origId = Binder.clearCallingIdentity();
5579
5580 final int N = providers.size();
5581 for (int i=0; i<N; i++) {
5582 ContentProviderHolder src = providers.get(i);
5583 if (src == null || src.info == null || src.provider == null) {
5584 continue;
5585 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005586 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005587 if (dst != null) {
5588 mProvidersByClass.put(dst.info.name, dst);
5589 String names[] = dst.info.authority.split(";");
5590 for (int j = 0; j < names.length; j++) {
5591 mProvidersByName.put(names[j], dst);
5592 }
5593
5594 int NL = mLaunchingProviders.size();
5595 int j;
5596 for (j=0; j<NL; j++) {
5597 if (mLaunchingProviders.get(j) == dst) {
5598 mLaunchingProviders.remove(j);
5599 j--;
5600 NL--;
5601 }
5602 }
5603 synchronized (dst) {
5604 dst.provider = src.provider;
5605 dst.app = r;
5606 dst.notifyAll();
5607 }
5608 updateOomAdjLocked(r);
5609 }
5610 }
5611
5612 Binder.restoreCallingIdentity(origId);
5613 }
5614 }
5615
5616 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005617 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005618 synchronized (mSelf) {
5619 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5620 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005621 if (providers != null) {
5622 for (int i=providers.size()-1; i>=0; i--) {
5623 ProviderInfo pi = (ProviderInfo)providers.get(i);
5624 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5625 Slog.w(TAG, "Not installing system proc provider " + pi.name
5626 + ": not system .apk");
5627 providers.remove(i);
5628 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005629 }
5630 }
5631 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005632 if (providers != null) {
5633 mSystemThread.installSystemProviders(providers);
5634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005635 }
5636
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005637 /**
5638 * Allows app to retrieve the MIME type of a URI without having permission
5639 * to access its content provider.
5640 *
5641 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5642 *
5643 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5644 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5645 */
5646 public String getProviderMimeType(Uri uri) {
5647 final String name = uri.getAuthority();
5648 final long ident = Binder.clearCallingIdentity();
5649 ContentProviderHolder holder = null;
5650
5651 try {
5652 holder = getContentProviderExternal(name);
5653 if (holder != null) {
5654 return holder.provider.getType(uri);
5655 }
5656 } catch (RemoteException e) {
5657 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5658 return null;
5659 } finally {
5660 if (holder != null) {
5661 removeContentProviderExternal(name);
5662 }
5663 Binder.restoreCallingIdentity(ident);
5664 }
5665
5666 return null;
5667 }
5668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005669 // =========================================================
5670 // GLOBAL MANAGEMENT
5671 // =========================================================
5672
5673 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5674 ApplicationInfo info, String customProcess) {
5675 String proc = customProcess != null ? customProcess : info.processName;
5676 BatteryStatsImpl.Uid.Proc ps = null;
5677 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5678 synchronized (stats) {
5679 ps = stats.getProcessStatsLocked(info.uid, proc);
5680 }
5681 return new ProcessRecord(ps, thread, info, proc);
5682 }
5683
5684 final ProcessRecord addAppLocked(ApplicationInfo info) {
5685 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5686
5687 if (app == null) {
5688 app = newProcessRecordLocked(null, info, null);
5689 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005690 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005691 }
5692
5693 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5694 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5695 app.persistent = true;
5696 app.maxAdj = CORE_SERVER_ADJ;
5697 }
5698 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5699 mPersistentStartingProcesses.add(app);
5700 startProcessLocked(app, "added application", app.processName);
5701 }
5702
5703 return app;
5704 }
5705
5706 public void unhandledBack() {
5707 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5708 "unhandledBack()");
5709
5710 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005711 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005712 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005713 TAG, "Performing unhandledBack(): stack size = " + count);
5714 if (count > 1) {
5715 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005716 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5718 Binder.restoreCallingIdentity(origId);
5719 }
5720 }
5721 }
5722
5723 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5724 String name = uri.getAuthority();
5725 ContentProviderHolder cph = getContentProviderExternal(name);
5726 ParcelFileDescriptor pfd = null;
5727 if (cph != null) {
5728 // We record the binder invoker's uid in thread-local storage before
5729 // going to the content provider to open the file. Later, in the code
5730 // that handles all permissions checks, we look for this uid and use
5731 // that rather than the Activity Manager's own uid. The effect is that
5732 // we do the check against the caller's permissions even though it looks
5733 // to the content provider like the Activity Manager itself is making
5734 // the request.
5735 sCallerIdentity.set(new Identity(
5736 Binder.getCallingPid(), Binder.getCallingUid()));
5737 try {
5738 pfd = cph.provider.openFile(uri, "r");
5739 } catch (FileNotFoundException e) {
5740 // do nothing; pfd will be returned null
5741 } finally {
5742 // Ensure that whatever happens, we clean up the identity state
5743 sCallerIdentity.remove();
5744 }
5745
5746 // We've got the fd now, so we're done with the provider.
5747 removeContentProviderExternal(name);
5748 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005749 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005750 }
5751 return pfd;
5752 }
5753
5754 public void goingToSleep() {
5755 synchronized(this) {
5756 mSleeping = true;
5757 mWindowManager.setEventDispatching(false);
5758
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005759 if (mMainStack.mResumedActivity != null) {
5760 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005761 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005762 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005763 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005764
5765 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005766 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005767 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5768 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005769 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005770 }
5771 }
5772
Dianne Hackborn55280a92009-05-07 15:53:46 -07005773 public boolean shutdown(int timeout) {
5774 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5775 != PackageManager.PERMISSION_GRANTED) {
5776 throw new SecurityException("Requires permission "
5777 + android.Manifest.permission.SHUTDOWN);
5778 }
5779
5780 boolean timedout = false;
5781
5782 synchronized(this) {
5783 mShuttingDown = true;
5784 mWindowManager.setEventDispatching(false);
5785
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005786 if (mMainStack.mResumedActivity != null) {
5787 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005788 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005789 while (mMainStack.mResumedActivity != null
5790 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005791 long delay = endTime - System.currentTimeMillis();
5792 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005793 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005794 timedout = true;
5795 break;
5796 }
5797 try {
5798 this.wait();
5799 } catch (InterruptedException e) {
5800 }
5801 }
5802 }
5803 }
5804
5805 mUsageStatsService.shutdown();
5806 mBatteryStatsService.shutdown();
5807
5808 return timedout;
5809 }
5810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005811 public void wakingUp() {
5812 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005813 if (mMainStack.mGoingToSleep.isHeld()) {
5814 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005815 }
5816 mWindowManager.setEventDispatching(true);
5817 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005818 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005819 }
5820 }
5821
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005822 public void stopAppSwitches() {
5823 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5824 != PackageManager.PERMISSION_GRANTED) {
5825 throw new SecurityException("Requires permission "
5826 + android.Manifest.permission.STOP_APP_SWITCHES);
5827 }
5828
5829 synchronized(this) {
5830 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5831 + APP_SWITCH_DELAY_TIME;
5832 mDidAppSwitch = false;
5833 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5834 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5835 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5836 }
5837 }
5838
5839 public void resumeAppSwitches() {
5840 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5841 != PackageManager.PERMISSION_GRANTED) {
5842 throw new SecurityException("Requires permission "
5843 + android.Manifest.permission.STOP_APP_SWITCHES);
5844 }
5845
5846 synchronized(this) {
5847 // Note that we don't execute any pending app switches... we will
5848 // let those wait until either the timeout, or the next start
5849 // activity request.
5850 mAppSwitchesAllowedTime = 0;
5851 }
5852 }
5853
5854 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5855 String name) {
5856 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5857 return true;
5858 }
5859
5860 final int perm = checkComponentPermission(
5861 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5862 callingUid, -1);
5863 if (perm == PackageManager.PERMISSION_GRANTED) {
5864 return true;
5865 }
5866
Joe Onorato8a9b2202010-02-26 18:56:32 -08005867 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005868 return false;
5869 }
5870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005871 public void setDebugApp(String packageName, boolean waitForDebugger,
5872 boolean persistent) {
5873 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5874 "setDebugApp()");
5875
5876 // Note that this is not really thread safe if there are multiple
5877 // callers into it at the same time, but that's not a situation we
5878 // care about.
5879 if (persistent) {
5880 final ContentResolver resolver = mContext.getContentResolver();
5881 Settings.System.putString(
5882 resolver, Settings.System.DEBUG_APP,
5883 packageName);
5884 Settings.System.putInt(
5885 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5886 waitForDebugger ? 1 : 0);
5887 }
5888
5889 synchronized (this) {
5890 if (!persistent) {
5891 mOrigDebugApp = mDebugApp;
5892 mOrigWaitForDebugger = mWaitForDebugger;
5893 }
5894 mDebugApp = packageName;
5895 mWaitForDebugger = waitForDebugger;
5896 mDebugTransient = !persistent;
5897 if (packageName != null) {
5898 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005899 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005900 Binder.restoreCallingIdentity(origId);
5901 }
5902 }
5903 }
5904
5905 public void setAlwaysFinish(boolean enabled) {
5906 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5907 "setAlwaysFinish()");
5908
5909 Settings.System.putInt(
5910 mContext.getContentResolver(),
5911 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5912
5913 synchronized (this) {
5914 mAlwaysFinishActivities = enabled;
5915 }
5916 }
5917
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005918 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005919 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005920 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005921 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005922 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005923 }
5924 }
5925
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005926 public boolean isUserAMonkey() {
5927 // For now the fact that there is a controller implies
5928 // we have a monkey.
5929 synchronized (this) {
5930 return mController != null;
5931 }
5932 }
5933
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005934 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005935 synchronized (this) {
5936 mWatchers.register(watcher);
5937 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005938 }
5939
5940 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005941 synchronized (this) {
5942 mWatchers.unregister(watcher);
5943 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005944 }
5945
Daniel Sandler69a48172010-06-23 16:29:36 -04005946 public void setImmersive(IBinder token, boolean immersive) {
5947 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005948 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005949 if (index < 0) {
5950 throw new IllegalArgumentException();
5951 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005952 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005953 r.immersive = immersive;
5954 }
5955 }
5956
5957 public boolean isImmersive(IBinder token) {
5958 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005959 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005960 if (index < 0) {
5961 throw new IllegalArgumentException();
5962 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005963 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005964 return r.immersive;
5965 }
5966 }
5967
5968 public boolean isTopActivityImmersive() {
5969 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005970 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005971 return (r != null) ? r.immersive : false;
5972 }
5973 }
5974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005975 public final void enterSafeMode() {
5976 synchronized(this) {
5977 // It only makes sense to do this before the system is ready
5978 // and started launching other packages.
5979 if (!mSystemReady) {
5980 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005981 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005982 } catch (RemoteException e) {
5983 }
5984
5985 View v = LayoutInflater.from(mContext).inflate(
5986 com.android.internal.R.layout.safe_mode, null);
5987 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown3b2b3542010-10-15 00:54:27 -07005988 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005989 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5990 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5991 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5992 lp.format = v.getBackground().getOpacity();
5993 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5994 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5995 ((WindowManager)mContext.getSystemService(
5996 Context.WINDOW_SERVICE)).addView(v, lp);
5997 }
5998 }
5999 }
6000
6001 public void noteWakeupAlarm(IIntentSender sender) {
6002 if (!(sender instanceof PendingIntentRecord)) {
6003 return;
6004 }
6005 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6006 synchronized (stats) {
6007 if (mBatteryStatsService.isOnBattery()) {
6008 mBatteryStatsService.enforceCallingPermission();
6009 PendingIntentRecord rec = (PendingIntentRecord)sender;
6010 int MY_UID = Binder.getCallingUid();
6011 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6012 BatteryStatsImpl.Uid.Pkg pkg =
6013 stats.getPackageStatsLocked(uid, rec.key.packageName);
6014 pkg.incWakeupsLocked();
6015 }
6016 }
6017 }
6018
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006019 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006021 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006022 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006023 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006024 // XXX Note: don't acquire main activity lock here, because the window
6025 // manager calls in with its locks held.
6026
6027 boolean killed = false;
6028 synchronized (mPidsSelfLocked) {
6029 int[] types = new int[pids.length];
6030 int worstType = 0;
6031 for (int i=0; i<pids.length; i++) {
6032 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6033 if (proc != null) {
6034 int type = proc.setAdj;
6035 types[i] = type;
6036 if (type > worstType) {
6037 worstType = type;
6038 }
6039 }
6040 }
6041
6042 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6043 // then constrain it so we will kill all hidden procs.
6044 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6045 worstType = HIDDEN_APP_MIN_ADJ;
6046 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006047 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 for (int i=0; i<pids.length; i++) {
6049 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6050 if (proc == null) {
6051 continue;
6052 }
6053 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006054 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006055 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006056 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6057 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006058 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006059 proc.killedBackground = true;
6060 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006061 }
6062 }
6063 }
6064 return killed;
6065 }
6066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006067 public final void startRunning(String pkg, String cls, String action,
6068 String data) {
6069 synchronized(this) {
6070 if (mStartRunning) {
6071 return;
6072 }
6073 mStartRunning = true;
6074 mTopComponent = pkg != null && cls != null
6075 ? new ComponentName(pkg, cls) : null;
6076 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6077 mTopData = data;
6078 if (!mSystemReady) {
6079 return;
6080 }
6081 }
6082
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006083 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006084 }
6085
6086 private void retrieveSettings() {
6087 final ContentResolver resolver = mContext.getContentResolver();
6088 String debugApp = Settings.System.getString(
6089 resolver, Settings.System.DEBUG_APP);
6090 boolean waitForDebugger = Settings.System.getInt(
6091 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6092 boolean alwaysFinishActivities = Settings.System.getInt(
6093 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6094
6095 Configuration configuration = new Configuration();
6096 Settings.System.getConfiguration(resolver, configuration);
6097
6098 synchronized (this) {
6099 mDebugApp = mOrigDebugApp = debugApp;
6100 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6101 mAlwaysFinishActivities = alwaysFinishActivities;
6102 // This happens before any activities are started, so we can
6103 // change mConfiguration in-place.
6104 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006105 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006106 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006107 }
6108 }
6109
6110 public boolean testIsSystemReady() {
6111 // no need to synchronize(this) just to read & return the value
6112 return mSystemReady;
6113 }
6114
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006115 private static File getCalledPreBootReceiversFile() {
6116 File dataDir = Environment.getDataDirectory();
6117 File systemDir = new File(dataDir, "system");
6118 File fname = new File(systemDir, "called_pre_boots.dat");
6119 return fname;
6120 }
6121
6122 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6123 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6124 File file = getCalledPreBootReceiversFile();
6125 FileInputStream fis = null;
6126 try {
6127 fis = new FileInputStream(file);
6128 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6129 int vers = dis.readInt();
6130 String codename = dis.readUTF();
6131 if (vers == android.os.Build.VERSION.SDK_INT
6132 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6133 int num = dis.readInt();
6134 while (num > 0) {
6135 num--;
6136 String pkg = dis.readUTF();
6137 String cls = dis.readUTF();
6138 lastDoneReceivers.add(new ComponentName(pkg, cls));
6139 }
6140 }
6141 } catch (FileNotFoundException e) {
6142 } catch (IOException e) {
6143 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6144 } finally {
6145 if (fis != null) {
6146 try {
6147 fis.close();
6148 } catch (IOException e) {
6149 }
6150 }
6151 }
6152 return lastDoneReceivers;
6153 }
6154
6155 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6156 File file = getCalledPreBootReceiversFile();
6157 FileOutputStream fos = null;
6158 DataOutputStream dos = null;
6159 try {
6160 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6161 fos = new FileOutputStream(file);
6162 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6163 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6164 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6165 dos.writeInt(list.size());
6166 for (int i=0; i<list.size(); i++) {
6167 dos.writeUTF(list.get(i).getPackageName());
6168 dos.writeUTF(list.get(i).getClassName());
6169 }
6170 } catch (IOException e) {
6171 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6172 file.delete();
6173 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006174 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006175 if (dos != null) {
6176 try {
6177 dos.close();
6178 } catch (IOException e) {
6179 // TODO Auto-generated catch block
6180 e.printStackTrace();
6181 }
6182 }
6183 }
6184 }
6185
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006186 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006187 // In the simulator, startRunning will never have been called, which
6188 // normally sets a few crucial variables. Do it here instead.
6189 if (!Process.supportsProcesses()) {
6190 mStartRunning = true;
6191 mTopAction = Intent.ACTION_MAIN;
6192 }
6193
6194 synchronized(this) {
6195 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006196 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006197 return;
6198 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006199
6200 // Check to see if there are any update receivers to run.
6201 if (!mDidUpdate) {
6202 if (mWaitingUpdate) {
6203 return;
6204 }
6205 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6206 List<ResolveInfo> ris = null;
6207 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006208 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006209 intent, null, 0);
6210 } catch (RemoteException e) {
6211 }
6212 if (ris != null) {
6213 for (int i=ris.size()-1; i>=0; i--) {
6214 if ((ris.get(i).activityInfo.applicationInfo.flags
6215 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6216 ris.remove(i);
6217 }
6218 }
6219 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006220
6221 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6222
6223 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006224 for (int i=0; i<ris.size(); i++) {
6225 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006226 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6227 if (lastDoneReceivers.contains(comp)) {
6228 ris.remove(i);
6229 i--;
6230 }
6231 }
6232
6233 for (int i=0; i<ris.size(); i++) {
6234 ActivityInfo ai = ris.get(i).activityInfo;
6235 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6236 doneReceivers.add(comp);
6237 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006238 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006239 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006240 finisher = new IIntentReceiver.Stub() {
6241 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006242 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006243 boolean sticky) {
6244 // The raw IIntentReceiver interface is called
6245 // with the AM lock held, so redispatch to
6246 // execute our code without the lock.
6247 mHandler.post(new Runnable() {
6248 public void run() {
6249 synchronized (ActivityManagerService.this) {
6250 mDidUpdate = true;
6251 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006252 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006253 systemReady(goingCallback);
6254 }
6255 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006256 }
6257 };
6258 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006259 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006260 broadcastIntentLocked(null, null, intent, null, finisher,
6261 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006262 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006263 mWaitingUpdate = true;
6264 }
6265 }
6266 }
6267 if (mWaitingUpdate) {
6268 return;
6269 }
6270 mDidUpdate = true;
6271 }
6272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006273 mSystemReady = true;
6274 if (!mStartRunning) {
6275 return;
6276 }
6277 }
6278
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006279 ArrayList<ProcessRecord> procsToKill = null;
6280 synchronized(mPidsSelfLocked) {
6281 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6282 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6283 if (!isAllowedWhileBooting(proc.info)){
6284 if (procsToKill == null) {
6285 procsToKill = new ArrayList<ProcessRecord>();
6286 }
6287 procsToKill.add(proc);
6288 }
6289 }
6290 }
6291
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006292 synchronized(this) {
6293 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006294 for (int i=procsToKill.size()-1; i>=0; i--) {
6295 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006296 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006297 removeProcessLocked(proc, true);
6298 }
6299 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006300
6301 // Now that we have cleaned up any update processes, we
6302 // are ready to start launching real processes and know that
6303 // we won't trample on them any more.
6304 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006305 }
6306
Joe Onorato8a9b2202010-02-26 18:56:32 -08006307 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006308 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006309 SystemClock.uptimeMillis());
6310
6311 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006312 // Make sure we have no pre-ready processes sitting around.
6313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006314 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6315 ResolveInfo ri = mContext.getPackageManager()
6316 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006317 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006318 CharSequence errorMsg = null;
6319 if (ri != null) {
6320 ActivityInfo ai = ri.activityInfo;
6321 ApplicationInfo app = ai.applicationInfo;
6322 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6323 mTopAction = Intent.ACTION_FACTORY_TEST;
6324 mTopData = null;
6325 mTopComponent = new ComponentName(app.packageName,
6326 ai.name);
6327 } else {
6328 errorMsg = mContext.getResources().getText(
6329 com.android.internal.R.string.factorytest_not_system);
6330 }
6331 } else {
6332 errorMsg = mContext.getResources().getText(
6333 com.android.internal.R.string.factorytest_no_action);
6334 }
6335 if (errorMsg != null) {
6336 mTopAction = null;
6337 mTopData = null;
6338 mTopComponent = null;
6339 Message msg = Message.obtain();
6340 msg.what = SHOW_FACTORY_ERROR_MSG;
6341 msg.getData().putCharSequence("msg", errorMsg);
6342 mHandler.sendMessage(msg);
6343 }
6344 }
6345 }
6346
6347 retrieveSettings();
6348
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006349 if (goingCallback != null) goingCallback.run();
6350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 synchronized (this) {
6352 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6353 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006354 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006355 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 if (apps != null) {
6357 int N = apps.size();
6358 int i;
6359 for (i=0; i<N; i++) {
6360 ApplicationInfo info
6361 = (ApplicationInfo)apps.get(i);
6362 if (info != null &&
6363 !info.packageName.equals("android")) {
6364 addAppLocked(info);
6365 }
6366 }
6367 }
6368 } catch (RemoteException ex) {
6369 // pm is in same process, this will never happen.
6370 }
6371 }
6372
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006373 // Start up initial activity.
6374 mBooting = true;
6375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006376 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006377 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006378 Message msg = Message.obtain();
6379 msg.what = SHOW_UID_ERROR_MSG;
6380 mHandler.sendMessage(msg);
6381 }
6382 } catch (RemoteException e) {
6383 }
6384
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006385 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006386 }
6387 }
6388
Dan Egnorb7f03672009-12-09 16:22:32 -08006389 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006390 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006391 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006392 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006393 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006394 startAppProblemLocked(app);
6395 app.stopFreezingAllLocked();
6396 return handleAppCrashLocked(app);
6397 }
6398
Dan Egnorb7f03672009-12-09 16:22:32 -08006399 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006400 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006401 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006402 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006403 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6404 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006405 startAppProblemLocked(app);
6406 app.stopFreezingAllLocked();
6407 }
6408
6409 /**
6410 * Generate a process error record, suitable for attachment to a ProcessRecord.
6411 *
6412 * @param app The ProcessRecord in which the error occurred.
6413 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6414 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006415 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416 * @param shortMsg Short message describing the crash.
6417 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006418 * @param stackTrace Full crash stack trace, may be null.
6419 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420 * @return Returns a fully-formed AppErrorStateInfo record.
6421 */
6422 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006423 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006424 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006426 report.condition = condition;
6427 report.processName = app.processName;
6428 report.pid = app.pid;
6429 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006430 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006431 report.shortMsg = shortMsg;
6432 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006433 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006434
6435 return report;
6436 }
6437
Dan Egnor42471dd2010-01-07 17:25:22 -08006438 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006439 synchronized (this) {
6440 app.crashing = false;
6441 app.crashingReport = null;
6442 app.notResponding = false;
6443 app.notRespondingReport = null;
6444 if (app.anrDialog == fromDialog) {
6445 app.anrDialog = null;
6446 }
6447 if (app.waitDialog == fromDialog) {
6448 app.waitDialog = null;
6449 }
6450 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006451 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006452 Slog.i(ActivityManagerService.TAG, "Killing "
6453 + app.processName + " (pid=" + app.pid + "): user's request");
6454 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6455 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006456 Process.killProcess(app.pid);
6457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006458 }
6459 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006460
Dan Egnorb7f03672009-12-09 16:22:32 -08006461 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006462 long now = SystemClock.uptimeMillis();
6463
6464 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6465 app.info.uid);
6466 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6467 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006468 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006469 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006470 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006471 app.info.processName, app.info.uid);
6472 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006473 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6474 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006475 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006476 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006477 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006478 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006479 }
6480 }
6481 if (!app.persistent) {
6482 // We don't want to start this process again until the user
6483 // explicitly does so... but for persistent process, we really
6484 // need to keep it running. If a persistent process is actually
6485 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006486 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006487 app.info.processName);
6488 mBadProcesses.put(app.info.processName, app.info.uid, now);
6489 app.bad = true;
6490 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6491 app.removed = true;
6492 removeProcessLocked(app, false);
6493 return false;
6494 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006495 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006496 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006497 if (r.app == app) {
6498 // If the top running activity is from this crashing
6499 // process, then terminate it to avoid getting in a loop.
6500 Slog.w(TAG, " Force finishing activity "
6501 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006502 int index = mMainStack.indexOfTokenLocked(r);
6503 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006504 Activity.RESULT_CANCELED, null, "crashed");
6505 // Also terminate an activities below it that aren't yet
6506 // stopped, to avoid a situation where one will get
6507 // re-start our crashing activity once it gets resumed again.
6508 index--;
6509 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006510 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006511 if (r.state == ActivityState.RESUMED
6512 || r.state == ActivityState.PAUSING
6513 || r.state == ActivityState.PAUSED) {
6514 if (!r.isHomeActivity) {
6515 Slog.w(TAG, " Force finishing activity "
6516 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006517 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006518 Activity.RESULT_CANCELED, null, "crashed");
6519 }
6520 }
6521 }
6522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 }
6524
6525 // Bump up the crash count of any services currently running in the proc.
6526 if (app.services.size() != 0) {
6527 // Any services running in the application need to be placed
6528 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006529 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006530 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006531 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006532 sr.crashCount++;
6533 }
6534 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006535
6536 // If the crashing process is what we consider to be the "home process" and it has been
6537 // replaced by a third-party app, clear the package preferred activities from packages
6538 // with a home activity running in the process to prevent a repeatedly crashing app
6539 // from blocking the user to manually clear the list.
6540 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6541 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6542 Iterator it = mHomeProcess.activities.iterator();
6543 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006544 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006545 if (r.isHomeActivity) {
6546 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6547 try {
6548 ActivityThread.getPackageManager()
6549 .clearPackagePreferredActivities(r.packageName);
6550 } catch (RemoteException c) {
6551 // pm is in same process, this will never happen.
6552 }
6553 }
6554 }
6555 }
6556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006557 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6558 return true;
6559 }
6560
6561 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006562 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6563 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 skipCurrentReceiverLocked(app);
6565 }
6566
6567 void skipCurrentReceiverLocked(ProcessRecord app) {
6568 boolean reschedule = false;
6569 BroadcastRecord r = app.curReceiver;
6570 if (r != null) {
6571 // The current broadcast is waiting for this app's receiver
6572 // to be finished. Looks like that's not going to happen, so
6573 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006574 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006575 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6576 r.resultExtras, r.resultAbort, true);
6577 reschedule = true;
6578 }
6579 r = mPendingBroadcast;
6580 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006581 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006582 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006583 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6585 r.resultExtras, r.resultAbort, true);
6586 reschedule = true;
6587 }
6588 if (reschedule) {
6589 scheduleBroadcastsLocked();
6590 }
6591 }
6592
Dan Egnor60d87622009-12-16 16:32:58 -08006593 /**
6594 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6595 * The application process will exit immediately after this call returns.
6596 * @param app object of the crashing app, null for the system server
6597 * @param crashInfo describing the exception
6598 */
6599 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6600 ProcessRecord r = findAppProcess(app);
6601
6602 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6603 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006604 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006605 crashInfo.exceptionClassName,
6606 crashInfo.exceptionMessage,
6607 crashInfo.throwFileName,
6608 crashInfo.throwLineNumber);
6609
Dan Egnor42471dd2010-01-07 17:25:22 -08006610 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006611
6612 crashApplication(r, crashInfo);
6613 }
6614
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006615 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006616 IBinder app,
6617 int violationMask,
6618 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006619 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006620
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006621 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006622 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006623 boolean logIt = true;
6624 synchronized (mAlreadyLoggedViolatedStacks) {
6625 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6626 logIt = false;
6627 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006628 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006629 // the relative pain numbers, without logging all
6630 // the stack traces repeatedly. We'd want to do
6631 // likewise in the client code, which also does
6632 // dup suppression, before the Binder call.
6633 } else {
6634 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6635 mAlreadyLoggedViolatedStacks.clear();
6636 }
6637 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6638 }
6639 }
6640 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006641 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006642 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006643 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006644
6645 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6646 AppErrorResult result = new AppErrorResult();
6647 synchronized (this) {
6648 final long origId = Binder.clearCallingIdentity();
6649
6650 Message msg = Message.obtain();
6651 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6652 HashMap<String, Object> data = new HashMap<String, Object>();
6653 data.put("result", result);
6654 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006655 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006656 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006657 msg.obj = data;
6658 mHandler.sendMessage(msg);
6659
6660 Binder.restoreCallingIdentity(origId);
6661 }
6662 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006663 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006664 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006665 }
6666
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006667 // Depending on the policy in effect, there could be a bunch of
6668 // these in quick succession so we try to batch these together to
6669 // minimize disk writes, number of dropbox entries, and maximize
6670 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006671 private void logStrictModeViolationToDropBox(
6672 ProcessRecord process,
6673 StrictMode.ViolationInfo info) {
6674 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006675 return;
6676 }
6677 final boolean isSystemApp = process == null ||
6678 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6679 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6680 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6681 final DropBoxManager dbox = (DropBoxManager)
6682 mContext.getSystemService(Context.DROPBOX_SERVICE);
6683
6684 // Exit early if the dropbox isn't configured to accept this report type.
6685 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6686
6687 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006688 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006689 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6690 synchronized (sb) {
6691 bufferWasEmpty = sb.length() == 0;
6692 appendDropBoxProcessHeaders(process, sb);
6693 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6694 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006695 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6696 if (info.violationNumThisLoop != 0) {
6697 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6698 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006699 if (info.numAnimationsRunning != 0) {
6700 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6701 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006702 if (info.broadcastIntentAction != null) {
6703 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6704 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006705 if (info != null && info.durationMillis != -1) {
6706 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006707 }
6708 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006709 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6710 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006711 }
6712 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006713
6714 // Only buffer up to ~64k. Various logging bits truncate
6715 // things at 128k.
6716 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006717 }
6718
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006719 // Flush immediately if the buffer's grown too large, or this
6720 // is a non-system app. Non-system apps are isolated with a
6721 // different tag & policy and not batched.
6722 //
6723 // Batching is useful during internal testing with
6724 // StrictMode settings turned up high. Without batching,
6725 // thousands of separate files could be created on boot.
6726 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006727 new Thread("Error dump: " + dropboxTag) {
6728 @Override
6729 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006730 String report;
6731 synchronized (sb) {
6732 report = sb.toString();
6733 sb.delete(0, sb.length());
6734 sb.trimToSize();
6735 }
6736 if (report.length() != 0) {
6737 dbox.addText(dropboxTag, report);
6738 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006739 }
6740 }.start();
6741 return;
6742 }
6743
6744 // System app batching:
6745 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006746 // An existing dropbox-writing thread is outstanding, so
6747 // we don't need to start it up. The existing thread will
6748 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006749 return;
6750 }
6751
6752 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6753 // (After this point, we shouldn't access AMS internal data structures.)
6754 new Thread("Error dump: " + dropboxTag) {
6755 @Override
6756 public void run() {
6757 // 5 second sleep to let stacks arrive and be batched together
6758 try {
6759 Thread.sleep(5000); // 5 seconds
6760 } catch (InterruptedException e) {}
6761
6762 String errorReport;
6763 synchronized (mStrictModeBuffer) {
6764 errorReport = mStrictModeBuffer.toString();
6765 if (errorReport.length() == 0) {
6766 return;
6767 }
6768 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6769 mStrictModeBuffer.trimToSize();
6770 }
6771 dbox.addText(dropboxTag, errorReport);
6772 }
6773 }.start();
6774 }
6775
Dan Egnor60d87622009-12-16 16:32:58 -08006776 /**
6777 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6778 * @param app object of the crashing app, null for the system server
6779 * @param tag reported by the caller
6780 * @param crashInfo describing the context of the error
6781 * @return true if the process should exit immediately (WTF is fatal)
6782 */
6783 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006784 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006785 ProcessRecord r = findAppProcess(app);
6786
6787 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6788 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006789 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006790 tag, crashInfo.exceptionMessage);
6791
Dan Egnor42471dd2010-01-07 17:25:22 -08006792 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006793
Doug Zongker43866e02010-01-07 12:09:54 -08006794 if (Settings.Secure.getInt(mContext.getContentResolver(),
6795 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006796 crashApplication(r, crashInfo);
6797 return true;
6798 } else {
6799 return false;
6800 }
6801 }
6802
6803 /**
6804 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6805 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6806 */
6807 private ProcessRecord findAppProcess(IBinder app) {
6808 if (app == null) {
6809 return null;
6810 }
6811
6812 synchronized (this) {
6813 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6814 final int NA = apps.size();
6815 for (int ia=0; ia<NA; ia++) {
6816 ProcessRecord p = apps.valueAt(ia);
6817 if (p.thread != null && p.thread.asBinder() == app) {
6818 return p;
6819 }
6820 }
6821 }
6822
Joe Onorato8a9b2202010-02-26 18:56:32 -08006823 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006824 return null;
6825 }
6826 }
6827
6828 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006829 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6830 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006831 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006832 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6833 // Note: ProcessRecord 'process' is guarded by the service
6834 // instance. (notably process.pkgList, which could otherwise change
6835 // concurrently during execution of this method)
6836 synchronized (this) {
6837 if (process == null || process.pid == MY_PID) {
6838 sb.append("Process: system_server\n");
6839 } else {
6840 sb.append("Process: ").append(process.processName).append("\n");
6841 }
6842 if (process == null) {
6843 return;
6844 }
Dan Egnora455d192010-03-12 08:52:28 -08006845 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006846 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006847 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6848 for (String pkg : process.pkgList) {
6849 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006850 try {
Dan Egnora455d192010-03-12 08:52:28 -08006851 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6852 if (pi != null) {
6853 sb.append(" v").append(pi.versionCode);
6854 if (pi.versionName != null) {
6855 sb.append(" (").append(pi.versionName).append(")");
6856 }
6857 }
6858 } catch (RemoteException e) {
6859 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006860 }
Dan Egnora455d192010-03-12 08:52:28 -08006861 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006862 }
Dan Egnora455d192010-03-12 08:52:28 -08006863 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006864 }
6865
6866 private static String processClass(ProcessRecord process) {
6867 if (process == null || process.pid == MY_PID) {
6868 return "system_server";
6869 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6870 return "system_app";
6871 } else {
6872 return "data_app";
6873 }
6874 }
6875
6876 /**
6877 * Write a description of an error (crash, WTF, ANR) to the drop box.
6878 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6879 * @param process which caused the error, null means the system server
6880 * @param activity which triggered the error, null if unknown
6881 * @param parent activity related to the error, null if unknown
6882 * @param subject line related to the error, null if absent
6883 * @param report in long form describing the error, null if absent
6884 * @param logFile to include in the report, null if none
6885 * @param crashInfo giving an application stack trace, null if absent
6886 */
6887 public void addErrorToDropBox(String eventType,
6888 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6889 final String report, final File logFile,
6890 final ApplicationErrorReport.CrashInfo crashInfo) {
6891 // NOTE -- this must never acquire the ActivityManagerService lock,
6892 // otherwise the watchdog may be prevented from resetting the system.
6893
6894 final String dropboxTag = processClass(process) + "_" + eventType;
6895 final DropBoxManager dbox = (DropBoxManager)
6896 mContext.getSystemService(Context.DROPBOX_SERVICE);
6897
6898 // Exit early if the dropbox isn't configured to accept this report type.
6899 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6900
6901 final StringBuilder sb = new StringBuilder(1024);
6902 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006903 if (activity != null) {
6904 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6905 }
6906 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6907 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6908 }
6909 if (parent != null && parent != activity) {
6910 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6911 }
6912 if (subject != null) {
6913 sb.append("Subject: ").append(subject).append("\n");
6914 }
6915 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02006916 if (Debug.isDebuggerConnected()) {
6917 sb.append("Debugger: Connected\n");
6918 }
Dan Egnora455d192010-03-12 08:52:28 -08006919 sb.append("\n");
6920
6921 // Do the rest in a worker thread to avoid blocking the caller on I/O
6922 // (After this point, we shouldn't access AMS internal data structures.)
6923 Thread worker = new Thread("Error dump: " + dropboxTag) {
6924 @Override
6925 public void run() {
6926 if (report != null) {
6927 sb.append(report);
6928 }
6929 if (logFile != null) {
6930 try {
6931 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6932 } catch (IOException e) {
6933 Slog.e(TAG, "Error reading " + logFile, e);
6934 }
6935 }
6936 if (crashInfo != null && crashInfo.stackTrace != null) {
6937 sb.append(crashInfo.stackTrace);
6938 }
6939
6940 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6941 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6942 if (lines > 0) {
6943 sb.append("\n");
6944
6945 // Merge several logcat streams, and take the last N lines
6946 InputStreamReader input = null;
6947 try {
6948 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6949 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6950 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6951
6952 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6953 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6954 input = new InputStreamReader(logcat.getInputStream());
6955
6956 int num;
6957 char[] buf = new char[8192];
6958 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6959 } catch (IOException e) {
6960 Slog.e(TAG, "Error running logcat", e);
6961 } finally {
6962 if (input != null) try { input.close(); } catch (IOException e) {}
6963 }
6964 }
6965
6966 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006967 }
Dan Egnora455d192010-03-12 08:52:28 -08006968 };
6969
6970 if (process == null || process.pid == MY_PID) {
6971 worker.run(); // We may be about to die -- need to run this synchronously
6972 } else {
6973 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006974 }
6975 }
6976
6977 /**
6978 * Bring up the "unexpected error" dialog box for a crashing app.
6979 * Deal with edge cases (intercepts from instrumented applications,
6980 * ActivityController, error intent receivers, that sort of thing).
6981 * @param r the application crashing
6982 * @param crashInfo describing the failure
6983 */
6984 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006985 long timeMillis = System.currentTimeMillis();
6986 String shortMsg = crashInfo.exceptionClassName;
6987 String longMsg = crashInfo.exceptionMessage;
6988 String stackTrace = crashInfo.stackTrace;
6989 if (shortMsg != null && longMsg != null) {
6990 longMsg = shortMsg + ": " + longMsg;
6991 } else if (shortMsg != null) {
6992 longMsg = shortMsg;
6993 }
6994
Dan Egnor60d87622009-12-16 16:32:58 -08006995 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006996 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006997 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006998 try {
6999 String name = r != null ? r.processName : null;
7000 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007001 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007002 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007003 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007004 + " at watcher's request");
7005 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007006 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007007 }
7008 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007009 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007010 }
7011 }
7012
7013 final long origId = Binder.clearCallingIdentity();
7014
7015 // If this process is running instrumentation, finish it.
7016 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007017 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007018 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007019 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7020 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007021 Bundle info = new Bundle();
7022 info.putString("shortMsg", shortMsg);
7023 info.putString("longMsg", longMsg);
7024 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7025 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007026 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007027 }
7028
Dan Egnor60d87622009-12-16 16:32:58 -08007029 // If we can't identify the process or it's already exceeded its crash quota,
7030 // quit right away without showing a crash dialog.
7031 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007032 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007033 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007034 }
7035
7036 Message msg = Message.obtain();
7037 msg.what = SHOW_ERROR_MSG;
7038 HashMap data = new HashMap();
7039 data.put("result", result);
7040 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007041 msg.obj = data;
7042 mHandler.sendMessage(msg);
7043
7044 Binder.restoreCallingIdentity(origId);
7045 }
7046
7047 int res = result.get();
7048
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007049 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007050 synchronized (this) {
7051 if (r != null) {
7052 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7053 SystemClock.uptimeMillis());
7054 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007055 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007056 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007057 }
7058 }
7059
7060 if (appErrorIntent != null) {
7061 try {
7062 mContext.startActivity(appErrorIntent);
7063 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007064 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007067 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007068
7069 Intent createAppErrorIntentLocked(ProcessRecord r,
7070 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7071 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007072 if (report == null) {
7073 return null;
7074 }
7075 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7076 result.setComponent(r.errorReportReceiver);
7077 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7078 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7079 return result;
7080 }
7081
Dan Egnorb7f03672009-12-09 16:22:32 -08007082 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7083 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007084 if (r.errorReportReceiver == null) {
7085 return null;
7086 }
7087
7088 if (!r.crashing && !r.notResponding) {
7089 return null;
7090 }
7091
Dan Egnorb7f03672009-12-09 16:22:32 -08007092 ApplicationErrorReport report = new ApplicationErrorReport();
7093 report.packageName = r.info.packageName;
7094 report.installerPackageName = r.errorReportReceiver.getPackageName();
7095 report.processName = r.processName;
7096 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007097 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007098
Dan Egnorb7f03672009-12-09 16:22:32 -08007099 if (r.crashing) {
7100 report.type = ApplicationErrorReport.TYPE_CRASH;
7101 report.crashInfo = crashInfo;
7102 } else if (r.notResponding) {
7103 report.type = ApplicationErrorReport.TYPE_ANR;
7104 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007105
Dan Egnorb7f03672009-12-09 16:22:32 -08007106 report.anrInfo.activity = r.notRespondingReport.tag;
7107 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7108 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007109 }
7110
Dan Egnorb7f03672009-12-09 16:22:32 -08007111 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007112 }
7113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007114 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7115 // assume our apps are happy - lazy create the list
7116 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7117
7118 synchronized (this) {
7119
7120 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007121 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7122 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007123 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7124 // This one's in trouble, so we'll generate a report for it
7125 // crashes are higher priority (in case there's a crash *and* an anr)
7126 ActivityManager.ProcessErrorStateInfo report = null;
7127 if (app.crashing) {
7128 report = app.crashingReport;
7129 } else if (app.notResponding) {
7130 report = app.notRespondingReport;
7131 }
7132
7133 if (report != null) {
7134 if (errList == null) {
7135 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7136 }
7137 errList.add(report);
7138 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007139 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007140 " crashing = " + app.crashing +
7141 " notResponding = " + app.notResponding);
7142 }
7143 }
7144 }
7145 }
7146
7147 return errList;
7148 }
7149
7150 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7151 // Lazy instantiation of list
7152 List<ActivityManager.RunningAppProcessInfo> runList = null;
7153 synchronized (this) {
7154 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007155 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7156 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007157 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7158 // Generate process state info for running application
7159 ActivityManager.RunningAppProcessInfo currApp =
7160 new ActivityManager.RunningAppProcessInfo(app.processName,
7161 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007162 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007163 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007164 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007165 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007166 if (app.persistent) {
7167 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007169 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007170 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007171 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7172 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7173 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007174 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7175 } else if (adj >= HOME_APP_ADJ) {
7176 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7177 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007178 } else if (adj >= SECONDARY_SERVER_ADJ) {
7179 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007180 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007181 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007182 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7183 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007184 } else if (adj >= VISIBLE_APP_ADJ) {
7185 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7186 } else {
7187 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7188 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007189 currApp.importanceReasonCode = app.adjTypeCode;
7190 if (app.adjSource instanceof ProcessRecord) {
7191 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007192 } else if (app.adjSource instanceof ActivityRecord) {
7193 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007194 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7195 }
7196 if (app.adjTarget instanceof ComponentName) {
7197 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7198 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007199 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007200 // + " lru=" + currApp.lru);
7201 if (runList == null) {
7202 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7203 }
7204 runList.add(currApp);
7205 }
7206 }
7207 }
7208 return runList;
7209 }
7210
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007211 public List<ApplicationInfo> getRunningExternalApplications() {
7212 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7213 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7214 if (runningApps != null && runningApps.size() > 0) {
7215 Set<String> extList = new HashSet<String>();
7216 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7217 if (app.pkgList != null) {
7218 for (String pkg : app.pkgList) {
7219 extList.add(pkg);
7220 }
7221 }
7222 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007223 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007224 for (String pkg : extList) {
7225 try {
7226 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7227 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7228 retList.add(info);
7229 }
7230 } catch (RemoteException e) {
7231 }
7232 }
7233 }
7234 return retList;
7235 }
7236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007237 @Override
7238 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007239 if (checkCallingPermission(android.Manifest.permission.DUMP)
7240 != PackageManager.PERMISSION_GRANTED) {
7241 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7242 + Binder.getCallingPid()
7243 + ", uid=" + Binder.getCallingUid()
7244 + " without permission "
7245 + android.Manifest.permission.DUMP);
7246 return;
7247 }
7248
7249 boolean dumpAll = false;
7250
7251 int opti = 0;
7252 while (opti < args.length) {
7253 String opt = args[opti];
7254 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7255 break;
7256 }
7257 opti++;
7258 if ("-a".equals(opt)) {
7259 dumpAll = true;
7260 } else if ("-h".equals(opt)) {
7261 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007262 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007263 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007264 pw.println(" a[ctivities]: activity stack state");
7265 pw.println(" b[roadcasts]: broadcast state");
7266 pw.println(" i[ntents]: pending intent state");
7267 pw.println(" p[rocesses]: process state");
7268 pw.println(" o[om]: out of memory management");
7269 pw.println(" prov[iders]: content provider state");
7270 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007271 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007273 } else {
7274 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007275 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007276 }
7277
7278 // Is the caller requesting to dump a particular piece of data?
7279 if (opti < args.length) {
7280 String cmd = args[opti];
7281 opti++;
7282 if ("activities".equals(cmd) || "a".equals(cmd)) {
7283 synchronized (this) {
7284 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007285 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007286 return;
7287 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7288 synchronized (this) {
7289 dumpBroadcastsLocked(fd, pw, args, opti, true);
7290 }
7291 return;
7292 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7293 synchronized (this) {
7294 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7295 }
7296 return;
7297 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7298 synchronized (this) {
7299 dumpProcessesLocked(fd, pw, args, opti, true);
7300 }
7301 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007302 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7303 synchronized (this) {
7304 dumpOomLocked(fd, pw, args, opti, true);
7305 }
7306 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007307 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7308 synchronized (this) {
7309 dumpProvidersLocked(fd, pw, args, opti, true);
7310 }
7311 return;
7312 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007313 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007314 return;
7315 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7316 synchronized (this) {
7317 dumpServicesLocked(fd, pw, args, opti, true);
7318 }
7319 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007320 } else {
7321 // Dumping a single activity?
7322 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7323 return;
7324 }
7325 pw.println("Bad activity command: " + cmd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007326 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007327 }
7328
7329 // No piece of data specified, dump everything.
7330 synchronized (this) {
7331 boolean needSep;
7332 if (dumpAll) {
7333 pw.println("Providers in Current Activity Manager State:");
7334 }
7335 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7336 if (needSep) {
7337 pw.println(" ");
7338 }
7339 if (dumpAll) {
7340 pw.println("-------------------------------------------------------------------------------");
7341 pw.println("Broadcasts in Current Activity Manager State:");
7342 }
7343 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7344 if (needSep) {
7345 pw.println(" ");
7346 }
7347 if (dumpAll) {
7348 pw.println("-------------------------------------------------------------------------------");
7349 pw.println("Services in Current Activity Manager State:");
7350 }
7351 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7352 if (needSep) {
7353 pw.println(" ");
7354 }
7355 if (dumpAll) {
7356 pw.println("-------------------------------------------------------------------------------");
7357 pw.println("PendingIntents in Current Activity Manager State:");
7358 }
7359 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7360 if (needSep) {
7361 pw.println(" ");
7362 }
7363 if (dumpAll) {
7364 pw.println("-------------------------------------------------------------------------------");
7365 pw.println("Activities in Current Activity Manager State:");
7366 }
7367 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7368 if (needSep) {
7369 pw.println(" ");
7370 }
7371 if (dumpAll) {
7372 pw.println("-------------------------------------------------------------------------------");
7373 pw.println("Processes in Current Activity Manager State:");
7374 }
7375 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7376 }
7377 }
7378
7379 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7380 int opti, boolean dumpAll, boolean needHeader) {
7381 if (needHeader) {
7382 pw.println(" Activity stack:");
7383 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007384 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007385 pw.println(" ");
7386 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007387 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7388 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007389 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007390 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007391 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007392 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007393 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007394 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007395 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007396 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007397 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007398 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007399 pw.println(" ");
7400 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007401 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007403
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007404 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007405 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7406 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007407 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007408 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007409
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007410 if (dumpAll && mRecentTasks.size() > 0) {
7411 pw.println(" ");
7412 pw.println("Recent tasks in Current Activity Manager State:");
7413
7414 final int N = mRecentTasks.size();
7415 for (int i=0; i<N; i++) {
7416 TaskRecord tr = mRecentTasks.get(i);
7417 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7418 pw.println(tr);
7419 mRecentTasks.get(i).dump(pw, " ");
7420 }
7421 }
7422
7423 pw.println(" ");
7424 pw.println(" mCurTask: " + mCurTask);
7425
7426 return true;
7427 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007428
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007429 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7430 int opti, boolean dumpAll) {
7431 boolean needSep = false;
7432 int numPers = 0;
7433
7434 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007435 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7436 final int NA = procs.size();
7437 for (int ia=0; ia<NA; ia++) {
7438 if (!needSep) {
7439 pw.println(" All known processes:");
7440 needSep = true;
7441 }
7442 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007443 pw.print(r.persistent ? " *PERS*" : " *APP*");
7444 pw.print(" UID "); pw.print(procs.keyAt(ia));
7445 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 r.dump(pw, " ");
7447 if (r.persistent) {
7448 numPers++;
7449 }
7450 }
7451 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007452 }
7453
7454 if (mLruProcesses.size() > 0) {
7455 if (needSep) pw.println(" ");
7456 needSep = true;
7457 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007458 dumpProcessOomList(pw, this, mLruProcesses, " ",
7459 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007460 needSep = true;
7461 }
7462
7463 synchronized (mPidsSelfLocked) {
7464 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 if (needSep) pw.println(" ");
7466 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007467 pw.println(" PID mappings:");
7468 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7469 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7470 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471 }
7472 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007473 }
7474
7475 if (mForegroundProcesses.size() > 0) {
7476 if (needSep) pw.println(" ");
7477 needSep = true;
7478 pw.println(" Foreground Processes:");
7479 for (int i=0; i<mForegroundProcesses.size(); i++) {
7480 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7481 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007482 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007483 }
7484
7485 if (mPersistentStartingProcesses.size() > 0) {
7486 if (needSep) pw.println(" ");
7487 needSep = true;
7488 pw.println(" Persisent processes that are starting:");
7489 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007490 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007491 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007492
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007493 if (mStartingProcesses.size() > 0) {
7494 if (needSep) pw.println(" ");
7495 needSep = true;
7496 pw.println(" Processes that are starting:");
7497 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007498 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007499 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007500
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007501 if (mRemovedProcesses.size() > 0) {
7502 if (needSep) pw.println(" ");
7503 needSep = true;
7504 pw.println(" Processes that are being removed:");
7505 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007506 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007507 }
7508
7509 if (mProcessesOnHold.size() > 0) {
7510 if (needSep) pw.println(" ");
7511 needSep = true;
7512 pw.println(" Processes that are on old until the system is ready:");
7513 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007514 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007516
Dianne Hackborn287952c2010-09-22 22:34:31 -07007517 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007518
7519 if (mProcessCrashTimes.getMap().size() > 0) {
7520 if (needSep) pw.println(" ");
7521 needSep = true;
7522 pw.println(" Time since processes crashed:");
7523 long now = SystemClock.uptimeMillis();
7524 for (Map.Entry<String, SparseArray<Long>> procs
7525 : mProcessCrashTimes.getMap().entrySet()) {
7526 SparseArray<Long> uids = procs.getValue();
7527 final int N = uids.size();
7528 for (int i=0; i<N; i++) {
7529 pw.print(" Process "); pw.print(procs.getKey());
7530 pw.print(" uid "); pw.print(uids.keyAt(i));
7531 pw.print(": last crashed ");
7532 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007533 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007534 }
7535 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007537
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007538 if (mBadProcesses.getMap().size() > 0) {
7539 if (needSep) pw.println(" ");
7540 needSep = true;
7541 pw.println(" Bad processes:");
7542 for (Map.Entry<String, SparseArray<Long>> procs
7543 : mBadProcesses.getMap().entrySet()) {
7544 SparseArray<Long> uids = procs.getValue();
7545 final int N = uids.size();
7546 for (int i=0; i<N; i++) {
7547 pw.print(" Bad process "); pw.print(procs.getKey());
7548 pw.print(" uid "); pw.print(uids.keyAt(i));
7549 pw.print(": crashed at time ");
7550 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 }
7552 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007554
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007555 pw.println(" ");
7556 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007557 if (mHeavyWeightProcess != null) {
7558 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7559 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007560 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007561 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007562 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7563 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7564 || mOrigWaitForDebugger) {
7565 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7566 + " mDebugTransient=" + mDebugTransient
7567 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7568 }
7569 if (mAlwaysFinishActivities || mController != null) {
7570 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7571 + " mController=" + mController);
7572 }
7573 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007574 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007575 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007576 + " mProcessesReady=" + mProcessesReady
7577 + " mSystemReady=" + mSystemReady);
7578 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007579 + " mBooted=" + mBooted
7580 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007581 pw.print(" mLastPowerCheckRealtime=");
7582 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7583 pw.println("");
7584 pw.print(" mLastPowerCheckUptime=");
7585 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7586 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007587 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7588 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007589 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007591
7592 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007593 }
7594
Dianne Hackborn287952c2010-09-22 22:34:31 -07007595 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7596 int opti, boolean needSep, boolean dumpAll) {
7597 if (mProcessesToGc.size() > 0) {
7598 if (needSep) pw.println(" ");
7599 needSep = true;
7600 pw.println(" Processes that are waiting to GC:");
7601 long now = SystemClock.uptimeMillis();
7602 for (int i=0; i<mProcessesToGc.size(); i++) {
7603 ProcessRecord proc = mProcessesToGc.get(i);
7604 pw.print(" Process "); pw.println(proc);
7605 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7606 pw.print(", last gced=");
7607 pw.print(now-proc.lastRequestedGc);
7608 pw.print(" ms ago, last lowMem=");
7609 pw.print(now-proc.lastLowMemory);
7610 pw.println(" ms ago");
7611
7612 }
7613 }
7614 return needSep;
7615 }
7616
7617 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7618 int opti, boolean dumpAll) {
7619 boolean needSep = false;
7620
7621 if (mLruProcesses.size() > 0) {
7622 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7623
7624 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7625 @Override
7626 public int compare(ProcessRecord object1, ProcessRecord object2) {
7627 if (object1.setAdj != object2.setAdj) {
7628 return object1.setAdj > object2.setAdj ? -1 : 1;
7629 }
7630 if (object1.setSchedGroup != object2.setSchedGroup) {
7631 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7632 }
7633 if (object1.keeping != object2.keeping) {
7634 return object1.keeping ? -1 : 1;
7635 }
7636 if (object1.pid != object2.pid) {
7637 return object1.pid > object2.pid ? -1 : 1;
7638 }
7639 return 0;
7640 }
7641 };
7642
7643 Collections.sort(procs, comparator);
7644
7645 if (needSep) pw.println(" ");
7646 needSep = true;
7647 pw.println(" Process OOM control:");
7648 dumpProcessOomList(pw, this, procs, " ",
7649 "Proc", "PERS", true);
7650 needSep = true;
7651 }
7652
7653 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7654
7655 pw.println(" ");
7656 pw.println(" mHomeProcess: " + mHomeProcess);
7657 if (mHeavyWeightProcess != null) {
7658 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7659 }
7660
7661 return true;
7662 }
7663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007664 /**
7665 * There are three ways to call this:
7666 * - no service specified: dump all the services
7667 * - a flattened component name that matched an existing service was specified as the
7668 * first arg: dump that one service
7669 * - the first arg isn't the flattened component name of an existing service:
7670 * dump all services whose component contains the first arg as a substring
7671 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007672 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 String[] newArgs;
7674 String componentNameString;
7675 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007676 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007677 componentNameString = null;
7678 newArgs = EMPTY_STRING_ARRAY;
7679 r = null;
7680 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007681 componentNameString = args[opti];
7682 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007683 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007684 synchronized (this) {
7685 r = componentName != null ? mServices.get(componentName) : null;
7686 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007687 newArgs = new String[args.length - opti];
7688 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007689 }
7690
7691 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007692 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007693 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007694 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7695 synchronized (this) {
7696 for (ServiceRecord r1 : mServices.values()) {
7697 if (componentNameString == null
7698 || r1.name.flattenToString().contains(componentNameString)) {
7699 services.add(r1);
7700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701 }
7702 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007703 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007704 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007706 }
7707 }
7708
7709 /**
7710 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7711 * there is a thread associated with the service.
7712 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007713 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7714 pw.println("------------------------------------------------------------"
7715 + "-------------------");
7716 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007717 if (r.app != null && r.app.thread != null) {
7718 try {
7719 // flush anything that is already in the PrintWriter since the thread is going
7720 // to write to the file descriptor directly
7721 pw.flush();
7722 r.app.thread.dumpService(fd, r, args);
7723 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007724 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007725 } catch (RemoteException e) {
7726 pw.println("got a RemoteException while dumping the service");
7727 }
7728 }
7729 }
7730
Dianne Hackborn625ac272010-09-17 18:29:22 -07007731 /**
7732 * There are three things that cmd can be:
7733 * - a flattened component name that matched an existing activity
7734 * - the cmd arg isn't the flattened component name of an existing activity:
7735 * dump all activity whose component contains the cmd as a substring
7736 * - A hex number of the ActivityRecord object instance.
7737 */
7738 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7739 int opti, boolean dumpAll) {
7740 String[] newArgs;
7741 ComponentName componentName = ComponentName.unflattenFromString(name);
7742 int objectId = 0;
7743 try {
7744 objectId = Integer.parseInt(name, 16);
7745 name = null;
7746 componentName = null;
7747 } catch (RuntimeException e) {
7748 }
7749 newArgs = new String[args.length - opti];
7750 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7751
7752 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7753 synchronized (this) {
7754 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7755 if (componentName != null) {
7756 if (r1.intent.getComponent().equals(componentName)) {
7757 activities.add(r1);
7758 }
7759 } else if (name != null) {
7760 if (r1.intent.getComponent().flattenToString().contains(name)) {
7761 activities.add(r1);
7762 }
7763 } else if (System.identityHashCode(this) == objectId) {
7764 activities.add(r1);
7765 }
7766 }
7767 }
7768
7769 if (activities.size() <= 0) {
7770 return false;
7771 }
7772
7773 for (int i=0; i<activities.size(); i++) {
7774 dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
7775 }
7776 return true;
7777 }
7778
7779 /**
7780 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7781 * there is a thread associated with the activity.
7782 */
7783 private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
7784 boolean dumpAll) {
7785 pw.println(" Activity " + r.intent.getComponent().flattenToString());
7786 if (dumpAll) {
7787 synchronized (this) {
7788 pw.print(" * "); pw.println(r);
7789 r.dump(pw, " ");
7790 }
7791 pw.println("");
7792 }
7793 if (r.app != null && r.app.thread != null) {
7794 try {
7795 // flush anything that is already in the PrintWriter since the thread is going
7796 // to write to the file descriptor directly
7797 pw.flush();
7798 r.app.thread.dumpActivity(fd, r, args);
7799 pw.print("\n");
7800 pw.flush();
7801 } catch (RemoteException e) {
7802 pw.println("got a RemoteException while dumping the activity");
7803 }
7804 }
7805 }
7806
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007807 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7808 int opti, boolean dumpAll) {
7809 boolean needSep = false;
7810
7811 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007812 if (mRegisteredReceivers.size() > 0) {
7813 pw.println(" ");
7814 pw.println(" Registered Receivers:");
7815 Iterator it = mRegisteredReceivers.values().iterator();
7816 while (it.hasNext()) {
7817 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007818 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007819 r.dump(pw, " ");
7820 }
7821 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823 pw.println(" ");
7824 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007825 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007826 needSep = true;
7827 }
7828
7829 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7830 || mPendingBroadcast != null) {
7831 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007832 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007833 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007834 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007835 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7836 pw.println(" Broadcast #" + i + ":");
7837 mParallelBroadcasts.get(i).dump(pw, " ");
7838 }
7839 if (mOrderedBroadcasts.size() > 0) {
7840 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007841 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007842 }
7843 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7844 pw.println(" Serialized Broadcast #" + i + ":");
7845 mOrderedBroadcasts.get(i).dump(pw, " ");
7846 }
7847 pw.println(" ");
7848 pw.println(" Pending broadcast:");
7849 if (mPendingBroadcast != null) {
7850 mPendingBroadcast.dump(pw, " ");
7851 } else {
7852 pw.println(" (null)");
7853 }
7854 needSep = true;
7855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007856
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007857 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007858 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007859 pw.println(" Historical broadcasts:");
7860 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7861 BroadcastRecord r = mBroadcastHistory[i];
7862 if (r == null) {
7863 break;
7864 }
7865 pw.println(" Historical Broadcast #" + i + ":");
7866 r.dump(pw, " ");
7867 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007868 needSep = true;
7869 }
7870
7871 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007872 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007873 pw.println(" Sticky broadcasts:");
7874 StringBuilder sb = new StringBuilder(128);
7875 for (Map.Entry<String, ArrayList<Intent>> ent
7876 : mStickyBroadcasts.entrySet()) {
7877 pw.print(" * Sticky action "); pw.print(ent.getKey());
7878 pw.println(":");
7879 ArrayList<Intent> intents = ent.getValue();
7880 final int N = intents.size();
7881 for (int i=0; i<N; i++) {
7882 sb.setLength(0);
7883 sb.append(" Intent: ");
7884 intents.get(i).toShortString(sb, true, false);
7885 pw.println(sb.toString());
7886 Bundle bundle = intents.get(i).getExtras();
7887 if (bundle != null) {
7888 pw.print(" ");
7889 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 }
7891 }
7892 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007893 needSep = true;
7894 }
7895
7896 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007897 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007898 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007899 pw.println(" mHandler:");
7900 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007901 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007902 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007903
7904 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007905 }
7906
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007907 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7908 int opti, boolean dumpAll) {
7909 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007910
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007911 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007912 if (mServices.size() > 0) {
7913 pw.println(" Active services:");
7914 Iterator<ServiceRecord> it = mServices.values().iterator();
7915 while (it.hasNext()) {
7916 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007917 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007918 r.dump(pw, " ");
7919 }
7920 needSep = true;
7921 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007924 if (mPendingServices.size() > 0) {
7925 if (needSep) pw.println(" ");
7926 pw.println(" Pending services:");
7927 for (int i=0; i<mPendingServices.size(); i++) {
7928 ServiceRecord r = mPendingServices.get(i);
7929 pw.print(" * Pending "); pw.println(r);
7930 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007931 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007932 needSep = true;
7933 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007934
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007935 if (mRestartingServices.size() > 0) {
7936 if (needSep) pw.println(" ");
7937 pw.println(" Restarting services:");
7938 for (int i=0; i<mRestartingServices.size(); i++) {
7939 ServiceRecord r = mRestartingServices.get(i);
7940 pw.print(" * Restarting "); pw.println(r);
7941 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007942 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007943 needSep = true;
7944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007946 if (mStoppingServices.size() > 0) {
7947 if (needSep) pw.println(" ");
7948 pw.println(" Stopping services:");
7949 for (int i=0; i<mStoppingServices.size(); i++) {
7950 ServiceRecord r = mStoppingServices.get(i);
7951 pw.print(" * Stopping "); pw.println(r);
7952 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007953 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007954 needSep = true;
7955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007956
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007957 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007958 if (mServiceConnections.size() > 0) {
7959 if (needSep) pw.println(" ");
7960 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007961 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007962 = mServiceConnections.values().iterator();
7963 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007964 ArrayList<ConnectionRecord> r = it.next();
7965 for (int i=0; i<r.size(); i++) {
7966 pw.print(" * "); pw.println(r.get(i));
7967 r.get(i).dump(pw, " ");
7968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007969 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007970 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007971 }
7972 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007973
7974 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007975 }
7976
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007977 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7978 int opti, boolean dumpAll) {
7979 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007981 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007982 if (mProvidersByClass.size() > 0) {
7983 if (needSep) pw.println(" ");
7984 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007985 Iterator<Map.Entry<String, ContentProviderRecord>> it
7986 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007987 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007988 Map.Entry<String, ContentProviderRecord> e = it.next();
7989 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007990 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007991 r.dump(pw, " ");
7992 }
7993 needSep = true;
7994 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007995
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007996 if (mProvidersByName.size() > 0) {
7997 pw.println(" ");
7998 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007999 Iterator<Map.Entry<String, ContentProviderRecord>> it
8000 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008001 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008002 Map.Entry<String, ContentProviderRecord> e = it.next();
8003 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008004 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8005 pw.println(r);
8006 }
8007 needSep = true;
8008 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008009 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008010
8011 if (mLaunchingProviders.size() > 0) {
8012 if (needSep) pw.println(" ");
8013 pw.println(" Launching content providers:");
8014 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8015 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8016 pw.println(mLaunchingProviders.get(i));
8017 }
8018 needSep = true;
8019 }
8020
8021 if (mGrantedUriPermissions.size() > 0) {
8022 pw.println();
8023 pw.println("Granted Uri Permissions:");
8024 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8025 int uid = mGrantedUriPermissions.keyAt(i);
8026 HashMap<Uri, UriPermission> perms
8027 = mGrantedUriPermissions.valueAt(i);
8028 pw.print(" * UID "); pw.print(uid);
8029 pw.println(" holds:");
8030 for (UriPermission perm : perms.values()) {
8031 pw.print(" "); pw.println(perm);
8032 perm.dump(pw, " ");
8033 }
8034 }
8035 needSep = true;
8036 }
8037
8038 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008039 }
8040
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008041 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8042 int opti, boolean dumpAll) {
8043 boolean needSep = false;
8044
8045 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008046 if (this.mIntentSenderRecords.size() > 0) {
8047 Iterator<WeakReference<PendingIntentRecord>> it
8048 = mIntentSenderRecords.values().iterator();
8049 while (it.hasNext()) {
8050 WeakReference<PendingIntentRecord> ref = it.next();
8051 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008052 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008053 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008054 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008055 rec.dump(pw, " ");
8056 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008057 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008058 }
8059 }
8060 }
8061 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008062
8063 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008064 }
8065
8066 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008067 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008068 TaskRecord lastTask = null;
8069 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008070 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008071 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 if (lastTask != r.task) {
8073 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008074 pw.print(prefix);
8075 pw.print(full ? "* " : " ");
8076 pw.println(lastTask);
8077 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008078 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008079 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008080 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008081 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8082 pw.print(" #"); pw.print(i); pw.print(": ");
8083 pw.println(r);
8084 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008085 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008087 }
8088 }
8089
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008090 private static String buildOomTag(String prefix, String space, int val, int base) {
8091 if (val == base) {
8092 if (space == null) return prefix;
8093 return prefix + " ";
8094 }
8095 return prefix + "+" + Integer.toString(val-base);
8096 }
8097
8098 private static final int dumpProcessList(PrintWriter pw,
8099 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008100 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008101 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008102 final int N = list.size()-1;
8103 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008104 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008105 pw.println(String.format("%s%s #%2d: %s",
8106 prefix, (r.persistent ? persistentLabel : normalLabel),
8107 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008108 if (r.persistent) {
8109 numPers++;
8110 }
8111 }
8112 return numPers;
8113 }
8114
Dianne Hackborn287952c2010-09-22 22:34:31 -07008115 private static final void dumpProcessOomList(PrintWriter pw,
8116 ActivityManagerService service, List<ProcessRecord> list,
8117 String prefix, String normalLabel, String persistentLabel,
8118 boolean inclDetails) {
8119
8120 final long curRealtime = SystemClock.elapsedRealtime();
8121 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8122 final long curUptime = SystemClock.uptimeMillis();
8123 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8124
8125 final int N = list.size()-1;
8126 for (int i=N; i>=0; i--) {
8127 ProcessRecord r = list.get(i);
8128 String oomAdj;
8129 if (r.setAdj >= EMPTY_APP_ADJ) {
8130 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8131 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8132 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8133 } else if (r.setAdj >= HOME_APP_ADJ) {
8134 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8135 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8136 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8137 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8138 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8139 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8140 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8141 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8142 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8143 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8144 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8145 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8146 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8147 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8148 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8149 } else if (r.setAdj >= SYSTEM_ADJ) {
8150 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8151 } else {
8152 oomAdj = Integer.toString(r.setAdj);
8153 }
8154 String schedGroup;
8155 switch (r.setSchedGroup) {
8156 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8157 schedGroup = "B";
8158 break;
8159 case Process.THREAD_GROUP_DEFAULT:
8160 schedGroup = "F";
8161 break;
8162 default:
8163 schedGroup = Integer.toString(r.setSchedGroup);
8164 break;
8165 }
8166 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8167 prefix, (r.persistent ? persistentLabel : normalLabel),
8168 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8169 if (r.adjSource != null || r.adjTarget != null) {
8170 pw.print(prefix);
8171 pw.print(" ");
8172 if (r.adjTarget instanceof ComponentName) {
8173 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8174 } else if (r.adjTarget != null) {
8175 pw.print(r.adjTarget.toString());
8176 } else {
8177 pw.print("{null}");
8178 }
8179 pw.print("<=");
8180 if (r.adjSource instanceof ProcessRecord) {
8181 pw.print("Proc{");
8182 pw.print(((ProcessRecord)r.adjSource).toShortString());
8183 pw.println("}");
8184 } else if (r.adjSource != null) {
8185 pw.println(r.adjSource.toString());
8186 } else {
8187 pw.println("{null}");
8188 }
8189 }
8190 if (inclDetails) {
8191 pw.print(prefix);
8192 pw.print(" ");
8193 pw.print("oom: max="); pw.print(r.maxAdj);
8194 pw.print(" hidden="); pw.print(r.hiddenAdj);
8195 pw.print(" curRaw="); pw.print(r.curRawAdj);
8196 pw.print(" setRaw="); pw.print(r.setRawAdj);
8197 pw.print(" cur="); pw.print(r.curAdj);
8198 pw.print(" set="); pw.println(r.setAdj);
8199 pw.print(prefix);
8200 pw.print(" ");
8201 pw.print("keeping="); pw.print(r.keeping);
8202 pw.print(" hidden="); pw.print(r.hidden);
8203 pw.print(" empty="); pw.println(r.empty);
8204
8205 if (!r.keeping) {
8206 if (r.lastWakeTime != 0) {
8207 long wtime;
8208 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8209 synchronized (stats) {
8210 wtime = stats.getProcessWakeTime(r.info.uid,
8211 r.pid, curRealtime);
8212 }
8213 long timeUsed = wtime - r.lastWakeTime;
8214 pw.print(prefix);
8215 pw.print(" ");
8216 pw.print("keep awake over ");
8217 TimeUtils.formatDuration(realtimeSince, pw);
8218 pw.print(" used ");
8219 TimeUtils.formatDuration(timeUsed, pw);
8220 pw.print(" (");
8221 pw.print((timeUsed*100)/realtimeSince);
8222 pw.println("%)");
8223 }
8224 if (r.lastCpuTime != 0) {
8225 long timeUsed = r.curCpuTime - r.lastCpuTime;
8226 pw.print(prefix);
8227 pw.print(" ");
8228 pw.print("run cpu over ");
8229 TimeUtils.formatDuration(uptimeSince, pw);
8230 pw.print(" used ");
8231 TimeUtils.formatDuration(timeUsed, pw);
8232 pw.print(" (");
8233 pw.print((timeUsed*100)/uptimeSince);
8234 pw.println("%)");
8235 }
8236 }
8237 }
8238 }
8239 }
8240
Dianne Hackborn472ad872010-04-07 17:31:48 -07008241 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008242 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008243 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008244 long uptime = SystemClock.uptimeMillis();
8245 long realtime = SystemClock.elapsedRealtime();
8246
8247 if (isCheckinRequest) {
8248 // short checkin version
8249 pw.println(uptime + "," + realtime);
8250 pw.flush();
8251 } else {
8252 pw.println("Applications Memory Usage (kB):");
8253 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8254 }
8255 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8256 ProcessRecord r = (ProcessRecord)list.get(i);
8257 if (r.thread != null) {
8258 if (!isCheckinRequest) {
8259 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8260 pw.flush();
8261 }
8262 try {
8263 r.thread.asBinder().dump(fd, args);
8264 } catch (RemoteException e) {
8265 if (!isCheckinRequest) {
8266 pw.println("Got RemoteException!");
8267 pw.flush();
8268 }
8269 }
8270 }
8271 }
8272 }
8273
8274 /**
8275 * Searches array of arguments for the specified string
8276 * @param args array of argument strings
8277 * @param value value to search for
8278 * @return true if the value is contained in the array
8279 */
8280 private static boolean scanArgs(String[] args, String value) {
8281 if (args != null) {
8282 for (String arg : args) {
8283 if (value.equals(arg)) {
8284 return true;
8285 }
8286 }
8287 }
8288 return false;
8289 }
8290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008291 private final void killServicesLocked(ProcessRecord app,
8292 boolean allowRestart) {
8293 // Report disconnected services.
8294 if (false) {
8295 // XXX we are letting the client link to the service for
8296 // death notifications.
8297 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008298 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008299 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008300 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008301 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008302 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008303 = r.connections.values().iterator();
8304 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008305 ArrayList<ConnectionRecord> cl = jt.next();
8306 for (int i=0; i<cl.size(); i++) {
8307 ConnectionRecord c = cl.get(i);
8308 if (c.binding.client != app) {
8309 try {
8310 //c.conn.connected(r.className, null);
8311 } catch (Exception e) {
8312 // todo: this should be asynchronous!
8313 Slog.w(TAG, "Exception thrown disconnected servce "
8314 + r.shortName
8315 + " from app " + app.processName, e);
8316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008317 }
8318 }
8319 }
8320 }
8321 }
8322 }
8323 }
8324
8325 // Clean up any connections this application has to other services.
8326 if (app.connections.size() > 0) {
8327 Iterator<ConnectionRecord> it = app.connections.iterator();
8328 while (it.hasNext()) {
8329 ConnectionRecord r = it.next();
8330 removeConnectionLocked(r, app, null);
8331 }
8332 }
8333 app.connections.clear();
8334
8335 if (app.services.size() != 0) {
8336 // Any services running in the application need to be placed
8337 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008338 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008339 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008340 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008341 synchronized (sr.stats.getBatteryStats()) {
8342 sr.stats.stopLaunchedLocked();
8343 }
8344 sr.app = null;
8345 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008346 if (mStoppingServices.remove(sr)) {
8347 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8348 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008349
8350 boolean hasClients = sr.bindings.size() > 0;
8351 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008352 Iterator<IntentBindRecord> bindings
8353 = sr.bindings.values().iterator();
8354 while (bindings.hasNext()) {
8355 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008356 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008357 + ": shouldUnbind=" + b.hasBound);
8358 b.binder = null;
8359 b.requested = b.received = b.hasBound = false;
8360 }
8361 }
8362
8363 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008364 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008365 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008366 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008367 sr.crashCount, sr.shortName, app.pid);
8368 bringDownServiceLocked(sr, true);
8369 } else if (!allowRestart) {
8370 bringDownServiceLocked(sr, true);
8371 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008372 boolean canceled = scheduleServiceRestartLocked(sr, true);
8373
8374 // Should the service remain running? Note that in the
8375 // extreme case of so many attempts to deliver a command
8376 // that it failed, that we also will stop it here.
8377 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8378 if (sr.pendingStarts.size() == 0) {
8379 sr.startRequested = false;
8380 if (!hasClients) {
8381 // Whoops, no reason to restart!
8382 bringDownServiceLocked(sr, true);
8383 }
8384 }
8385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008386 }
8387 }
8388
8389 if (!allowRestart) {
8390 app.services.clear();
8391 }
8392 }
8393
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008394 // Make sure we have no more records on the stopping list.
8395 int i = mStoppingServices.size();
8396 while (i > 0) {
8397 i--;
8398 ServiceRecord sr = mStoppingServices.get(i);
8399 if (sr.app == app) {
8400 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008401 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008402 }
8403 }
8404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008405 app.executingServices.clear();
8406 }
8407
8408 private final void removeDyingProviderLocked(ProcessRecord proc,
8409 ContentProviderRecord cpr) {
8410 synchronized (cpr) {
8411 cpr.launchingApp = null;
8412 cpr.notifyAll();
8413 }
8414
8415 mProvidersByClass.remove(cpr.info.name);
8416 String names[] = cpr.info.authority.split(";");
8417 for (int j = 0; j < names.length; j++) {
8418 mProvidersByName.remove(names[j]);
8419 }
8420
8421 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8422 while (cit.hasNext()) {
8423 ProcessRecord capp = cit.next();
8424 if (!capp.persistent && capp.thread != null
8425 && capp.pid != 0
8426 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008427 Slog.i(TAG, "Kill " + capp.processName
8428 + " (pid " + capp.pid + "): provider " + cpr.info.name
8429 + " in dying process " + proc.processName);
8430 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8431 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008432 Process.killProcess(capp.pid);
8433 }
8434 }
8435
8436 mLaunchingProviders.remove(cpr);
8437 }
8438
8439 /**
8440 * Main code for cleaning up a process when it has gone away. This is
8441 * called both as a result of the process dying, or directly when stopping
8442 * a process when running in single process mode.
8443 */
8444 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8445 boolean restarting, int index) {
8446 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008447 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008448 }
8449
Dianne Hackborn36124872009-10-08 16:22:03 -07008450 mProcessesToGc.remove(app);
8451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008452 // Dismiss any open dialogs.
8453 if (app.crashDialog != null) {
8454 app.crashDialog.dismiss();
8455 app.crashDialog = null;
8456 }
8457 if (app.anrDialog != null) {
8458 app.anrDialog.dismiss();
8459 app.anrDialog = null;
8460 }
8461 if (app.waitDialog != null) {
8462 app.waitDialog.dismiss();
8463 app.waitDialog = null;
8464 }
8465
8466 app.crashing = false;
8467 app.notResponding = false;
8468
8469 app.resetPackageList();
8470 app.thread = null;
8471 app.forcingToForeground = null;
8472 app.foregroundServices = false;
8473
8474 killServicesLocked(app, true);
8475
8476 boolean restart = false;
8477
8478 int NL = mLaunchingProviders.size();
8479
8480 // Remove published content providers.
8481 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008482 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008483 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008484 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008485 cpr.provider = null;
8486 cpr.app = null;
8487
8488 // See if someone is waiting for this provider... in which
8489 // case we don't remove it, but just let it restart.
8490 int i = 0;
8491 if (!app.bad) {
8492 for (; i<NL; i++) {
8493 if (mLaunchingProviders.get(i) == cpr) {
8494 restart = true;
8495 break;
8496 }
8497 }
8498 } else {
8499 i = NL;
8500 }
8501
8502 if (i >= NL) {
8503 removeDyingProviderLocked(app, cpr);
8504 NL = mLaunchingProviders.size();
8505 }
8506 }
8507 app.pubProviders.clear();
8508 }
8509
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008510 // Take care of any launching providers waiting for this process.
8511 if (checkAppInLaunchingProvidersLocked(app, false)) {
8512 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008513 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 // Unregister from connected content providers.
8516 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008517 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518 while (it.hasNext()) {
8519 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8520 cpr.clients.remove(app);
8521 }
8522 app.conProviders.clear();
8523 }
8524
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008525 // At this point there may be remaining entries in mLaunchingProviders
8526 // where we were the only one waiting, so they are no longer of use.
8527 // Look for these and clean up if found.
8528 // XXX Commented out for now. Trying to figure out a way to reproduce
8529 // the actual situation to identify what is actually going on.
8530 if (false) {
8531 for (int i=0; i<NL; i++) {
8532 ContentProviderRecord cpr = (ContentProviderRecord)
8533 mLaunchingProviders.get(i);
8534 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8535 synchronized (cpr) {
8536 cpr.launchingApp = null;
8537 cpr.notifyAll();
8538 }
8539 }
8540 }
8541 }
8542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008543 skipCurrentReceiverLocked(app);
8544
8545 // Unregister any receivers.
8546 if (app.receivers.size() > 0) {
8547 Iterator<ReceiverList> it = app.receivers.iterator();
8548 while (it.hasNext()) {
8549 removeReceiverLocked(it.next());
8550 }
8551 app.receivers.clear();
8552 }
8553
Christopher Tate181fafa2009-05-14 11:12:14 -07008554 // If the app is undergoing backup, tell the backup manager about it
8555 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008556 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008557 try {
8558 IBackupManager bm = IBackupManager.Stub.asInterface(
8559 ServiceManager.getService(Context.BACKUP_SERVICE));
8560 bm.agentDisconnected(app.info.packageName);
8561 } catch (RemoteException e) {
8562 // can't happen; backup manager is local
8563 }
8564 }
8565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008566 // If the caller is restarting this app, then leave it in its
8567 // current lists and let the caller take care of it.
8568 if (restarting) {
8569 return;
8570 }
8571
8572 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008573 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008574 "Removing non-persistent process during cleanup: " + app);
8575 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008576 if (mHeavyWeightProcess == app) {
8577 mHeavyWeightProcess = null;
8578 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008580 } else if (!app.removed) {
8581 // This app is persistent, so we need to keep its record around.
8582 // If it is not already on the pending app list, add it there
8583 // and start a new process for it.
8584 app.thread = null;
8585 app.forcingToForeground = null;
8586 app.foregroundServices = false;
8587 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8588 mPersistentStartingProcesses.add(app);
8589 restart = true;
8590 }
8591 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008592 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8593 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008594 mProcessesOnHold.remove(app);
8595
The Android Open Source Project4df24232009-03-05 14:34:35 -08008596 if (app == mHomeProcess) {
8597 mHomeProcess = null;
8598 }
8599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008600 if (restart) {
8601 // We have components that still need to be running in the
8602 // process, so re-launch it.
8603 mProcessNames.put(app.processName, app.info.uid, app);
8604 startProcessLocked(app, "restart", app.processName);
8605 } else if (app.pid > 0 && app.pid != MY_PID) {
8606 // Goodbye!
8607 synchronized (mPidsSelfLocked) {
8608 mPidsSelfLocked.remove(app.pid);
8609 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8610 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008611 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008612 }
8613 }
8614
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008615 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8616 // Look through the content providers we are waiting to have launched,
8617 // and if any run in this process then either schedule a restart of
8618 // the process or kill the client waiting for it if this process has
8619 // gone bad.
8620 int NL = mLaunchingProviders.size();
8621 boolean restart = false;
8622 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008623 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008624 if (cpr.launchingApp == app) {
8625 if (!alwaysBad && !app.bad) {
8626 restart = true;
8627 } else {
8628 removeDyingProviderLocked(app, cpr);
8629 NL = mLaunchingProviders.size();
8630 }
8631 }
8632 }
8633 return restart;
8634 }
8635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008636 // =========================================================
8637 // SERVICES
8638 // =========================================================
8639
8640 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8641 ActivityManager.RunningServiceInfo info =
8642 new ActivityManager.RunningServiceInfo();
8643 info.service = r.name;
8644 if (r.app != null) {
8645 info.pid = r.app.pid;
8646 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008647 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008648 info.process = r.processName;
8649 info.foreground = r.isForeground;
8650 info.activeSince = r.createTime;
8651 info.started = r.startRequested;
8652 info.clientCount = r.connections.size();
8653 info.crashCount = r.crashCount;
8654 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008655 if (r.isForeground) {
8656 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8657 }
8658 if (r.startRequested) {
8659 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8660 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008661 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008662 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8663 }
8664 if (r.app != null && r.app.persistent) {
8665 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8666 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008667
8668 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8669 for (int i=0; i<connl.size(); i++) {
8670 ConnectionRecord conn = connl.get(i);
8671 if (conn.clientLabel != 0) {
8672 info.clientPackage = conn.binding.client.info.packageName;
8673 info.clientLabel = conn.clientLabel;
8674 return info;
8675 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008676 }
8677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008678 return info;
8679 }
8680
8681 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8682 int flags) {
8683 synchronized (this) {
8684 ArrayList<ActivityManager.RunningServiceInfo> res
8685 = new ArrayList<ActivityManager.RunningServiceInfo>();
8686
8687 if (mServices.size() > 0) {
8688 Iterator<ServiceRecord> it = mServices.values().iterator();
8689 while (it.hasNext() && res.size() < maxNum) {
8690 res.add(makeRunningServiceInfoLocked(it.next()));
8691 }
8692 }
8693
8694 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8695 ServiceRecord r = mRestartingServices.get(i);
8696 ActivityManager.RunningServiceInfo info =
8697 makeRunningServiceInfoLocked(r);
8698 info.restarting = r.nextRestartTime;
8699 res.add(info);
8700 }
8701
8702 return res;
8703 }
8704 }
8705
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008706 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8707 synchronized (this) {
8708 ServiceRecord r = mServices.get(name);
8709 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008710 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8711 for (int i=0; i<conn.size(); i++) {
8712 if (conn.get(i).clientIntent != null) {
8713 return conn.get(i).clientIntent;
8714 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008715 }
8716 }
8717 }
8718 }
8719 return null;
8720 }
8721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008722 private final ServiceRecord findServiceLocked(ComponentName name,
8723 IBinder token) {
8724 ServiceRecord r = mServices.get(name);
8725 return r == token ? r : null;
8726 }
8727
8728 private final class ServiceLookupResult {
8729 final ServiceRecord record;
8730 final String permission;
8731
8732 ServiceLookupResult(ServiceRecord _record, String _permission) {
8733 record = _record;
8734 permission = _permission;
8735 }
8736 };
8737
8738 private ServiceLookupResult findServiceLocked(Intent service,
8739 String resolvedType) {
8740 ServiceRecord r = null;
8741 if (service.getComponent() != null) {
8742 r = mServices.get(service.getComponent());
8743 }
8744 if (r == null) {
8745 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8746 r = mServicesByIntent.get(filter);
8747 }
8748
8749 if (r == null) {
8750 try {
8751 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008752 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008753 service, resolvedType, 0);
8754 ServiceInfo sInfo =
8755 rInfo != null ? rInfo.serviceInfo : null;
8756 if (sInfo == null) {
8757 return null;
8758 }
8759
8760 ComponentName name = new ComponentName(
8761 sInfo.applicationInfo.packageName, sInfo.name);
8762 r = mServices.get(name);
8763 } catch (RemoteException ex) {
8764 // pm is in same process, this will never happen.
8765 }
8766 }
8767 if (r != null) {
8768 int callingPid = Binder.getCallingPid();
8769 int callingUid = Binder.getCallingUid();
8770 if (checkComponentPermission(r.permission,
8771 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8772 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008773 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008774 + " from pid=" + callingPid
8775 + ", uid=" + callingUid
8776 + " requires " + r.permission);
8777 return new ServiceLookupResult(null, r.permission);
8778 }
8779 return new ServiceLookupResult(r, null);
8780 }
8781 return null;
8782 }
8783
8784 private class ServiceRestarter implements Runnable {
8785 private ServiceRecord mService;
8786
8787 void setService(ServiceRecord service) {
8788 mService = service;
8789 }
8790
8791 public void run() {
8792 synchronized(ActivityManagerService.this) {
8793 performServiceRestartLocked(mService);
8794 }
8795 }
8796 }
8797
8798 private ServiceLookupResult retrieveServiceLocked(Intent service,
8799 String resolvedType, int callingPid, int callingUid) {
8800 ServiceRecord r = null;
8801 if (service.getComponent() != null) {
8802 r = mServices.get(service.getComponent());
8803 }
8804 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8805 r = mServicesByIntent.get(filter);
8806 if (r == null) {
8807 try {
8808 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008809 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008810 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008811 ServiceInfo sInfo =
8812 rInfo != null ? rInfo.serviceInfo : null;
8813 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008814 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008815 ": not found");
8816 return null;
8817 }
8818
8819 ComponentName name = new ComponentName(
8820 sInfo.applicationInfo.packageName, sInfo.name);
8821 r = mServices.get(name);
8822 if (r == null) {
8823 filter = new Intent.FilterComparison(service.cloneFilter());
8824 ServiceRestarter res = new ServiceRestarter();
8825 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8826 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8827 synchronized (stats) {
8828 ss = stats.getServiceStatsLocked(
8829 sInfo.applicationInfo.uid, sInfo.packageName,
8830 sInfo.name);
8831 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008832 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008833 res.setService(r);
8834 mServices.put(name, r);
8835 mServicesByIntent.put(filter, r);
8836
8837 // Make sure this component isn't in the pending list.
8838 int N = mPendingServices.size();
8839 for (int i=0; i<N; i++) {
8840 ServiceRecord pr = mPendingServices.get(i);
8841 if (pr.name.equals(name)) {
8842 mPendingServices.remove(i);
8843 i--;
8844 N--;
8845 }
8846 }
8847 }
8848 } catch (RemoteException ex) {
8849 // pm is in same process, this will never happen.
8850 }
8851 }
8852 if (r != null) {
8853 if (checkComponentPermission(r.permission,
8854 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8855 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008856 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008857 + " from pid=" + Binder.getCallingPid()
8858 + ", uid=" + Binder.getCallingUid()
8859 + " requires " + r.permission);
8860 return new ServiceLookupResult(null, r.permission);
8861 }
8862 return new ServiceLookupResult(r, null);
8863 }
8864 return null;
8865 }
8866
Dianne Hackborn287952c2010-09-22 22:34:31 -07008867 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8868 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8869 + why + " of " + r + " in app " + r.app);
8870 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8871 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008872 long now = SystemClock.uptimeMillis();
8873 if (r.executeNesting == 0 && r.app != null) {
8874 if (r.app.executingServices.size() == 0) {
8875 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8876 msg.obj = r.app;
8877 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8878 }
8879 r.app.executingServices.add(r);
8880 }
8881 r.executeNesting++;
8882 r.executingStart = now;
8883 }
8884
8885 private final void sendServiceArgsLocked(ServiceRecord r,
8886 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008887 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008888 if (N == 0) {
8889 return;
8890 }
8891
Dianne Hackborn39792d22010-08-19 18:01:52 -07008892 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008893 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008894 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008895 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8896 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008897 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008898 // If somehow we got a dummy start at the front, then
8899 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008900 continue;
8901 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008902 si.deliveredTime = SystemClock.uptimeMillis();
8903 r.deliveredStarts.add(si);
8904 si.deliveryCount++;
8905 if (si.targetPermissionUid >= 0) {
8906 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008907 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008908 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008909 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008910 if (!oomAdjusted) {
8911 oomAdjusted = true;
8912 updateOomAdjLocked(r.app);
8913 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008914 int flags = 0;
8915 if (si.deliveryCount > 0) {
8916 flags |= Service.START_FLAG_RETRY;
8917 }
8918 if (si.doneExecutingCount > 0) {
8919 flags |= Service.START_FLAG_REDELIVERY;
8920 }
8921 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008922 } catch (RemoteException e) {
8923 // Remote process gone... we'll let the normal cleanup take
8924 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008925 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008926 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008927 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008928 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008929 break;
8930 }
8931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008932 }
8933
8934 private final boolean requestServiceBindingLocked(ServiceRecord r,
8935 IntentBindRecord i, boolean rebind) {
8936 if (r.app == null || r.app.thread == null) {
8937 // If service is not currently running, can't yet bind.
8938 return false;
8939 }
8940 if ((!i.requested || rebind) && i.apps.size() > 0) {
8941 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008942 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008943 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8944 if (!rebind) {
8945 i.requested = true;
8946 }
8947 i.hasBound = true;
8948 i.doRebind = false;
8949 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008950 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008951 return false;
8952 }
8953 }
8954 return true;
8955 }
8956
8957 private final void requestServiceBindingsLocked(ServiceRecord r) {
8958 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8959 while (bindings.hasNext()) {
8960 IntentBindRecord i = bindings.next();
8961 if (!requestServiceBindingLocked(r, i, false)) {
8962 break;
8963 }
8964 }
8965 }
8966
8967 private final void realStartServiceLocked(ServiceRecord r,
8968 ProcessRecord app) throws RemoteException {
8969 if (app.thread == null) {
8970 throw new RemoteException();
8971 }
8972
8973 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008974 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008975
8976 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008977 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008978 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008979
8980 boolean created = false;
8981 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008982 mStringBuilder.setLength(0);
8983 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008984 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008985 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008986 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008987 synchronized (r.stats.getBatteryStats()) {
8988 r.stats.startLaunchedLocked();
8989 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008990 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008991 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008992 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008993 created = true;
8994 } finally {
8995 if (!created) {
8996 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008997 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998 }
8999 }
9000
9001 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009002
9003 // If the service is in the started state, and there are no
9004 // pending arguments, then fake up one so its onStartCommand() will
9005 // be called.
9006 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9007 r.lastStartId++;
9008 if (r.lastStartId < 1) {
9009 r.lastStartId = 1;
9010 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009011 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009012 }
9013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009014 sendServiceArgsLocked(r, true);
9015 }
9016
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009017 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9018 boolean allowCancel) {
9019 boolean canceled = false;
9020
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009021 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009022 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009023 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009024
9025 // Any delivered but not yet finished starts should be put back
9026 // on the pending list.
9027 final int N = r.deliveredStarts.size();
9028 if (N > 0) {
9029 for (int i=N-1; i>=0; i--) {
9030 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009031 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009032 if (si.intent == null) {
9033 // We'll generate this again if needed.
9034 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9035 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9036 r.pendingStarts.add(0, si);
9037 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9038 dur *= 2;
9039 if (minDuration < dur) minDuration = dur;
9040 if (resetTime < dur) resetTime = dur;
9041 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009042 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009043 + r.name);
9044 canceled = true;
9045 }
9046 }
9047 r.deliveredStarts.clear();
9048 }
9049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009050 r.totalRestartCount++;
9051 if (r.restartDelay == 0) {
9052 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009053 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009054 } else {
9055 // If it has been a "reasonably long time" since the service
9056 // was started, then reset our restart duration back to
9057 // the beginning, so we don't infinitely increase the duration
9058 // on a service that just occasionally gets killed (which is
9059 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009060 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009061 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009062 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009063 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009064 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009065 if (r.restartDelay < minDuration) {
9066 r.restartDelay = minDuration;
9067 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009068 }
9069 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009070
9071 r.nextRestartTime = now + r.restartDelay;
9072
9073 // Make sure that we don't end up restarting a bunch of services
9074 // all at the same time.
9075 boolean repeat;
9076 do {
9077 repeat = false;
9078 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9079 ServiceRecord r2 = mRestartingServices.get(i);
9080 if (r2 != r && r.nextRestartTime
9081 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9082 && r.nextRestartTime
9083 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9084 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9085 r.restartDelay = r.nextRestartTime - now;
9086 repeat = true;
9087 break;
9088 }
9089 }
9090 } while (repeat);
9091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009092 if (!mRestartingServices.contains(r)) {
9093 mRestartingServices.add(r);
9094 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009095
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009096 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009098 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009099 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009100 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009101 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009102 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009103 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009104 r.shortName, r.restartDelay);
9105
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009106 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009107 }
9108
9109 final void performServiceRestartLocked(ServiceRecord r) {
9110 if (!mRestartingServices.contains(r)) {
9111 return;
9112 }
9113 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9114 }
9115
9116 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9117 if (r.restartDelay == 0) {
9118 return false;
9119 }
9120 r.resetRestartCounter();
9121 mRestartingServices.remove(r);
9122 mHandler.removeCallbacks(r.restarter);
9123 return true;
9124 }
9125
9126 private final boolean bringUpServiceLocked(ServiceRecord r,
9127 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009128 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009129 //r.dump(" ");
9130
Dianne Hackborn36124872009-10-08 16:22:03 -07009131 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009132 sendServiceArgsLocked(r, false);
9133 return true;
9134 }
9135
9136 if (!whileRestarting && r.restartDelay > 0) {
9137 // If waiting for a restart, then do nothing.
9138 return true;
9139 }
9140
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009141 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009142
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009143 // We are now bringing the service up, so no longer in the
9144 // restarting state.
9145 mRestartingServices.remove(r);
9146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009147 final String appName = r.processName;
9148 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9149 if (app != null && app.thread != null) {
9150 try {
9151 realStartServiceLocked(r, app);
9152 return true;
9153 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009154 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009155 }
9156
9157 // If a dead object exception was thrown -- fall through to
9158 // restart the application.
9159 }
9160
Dianne Hackborn36124872009-10-08 16:22:03 -07009161 // Not running -- get it started, and enqueue this service record
9162 // to be executed when the app comes up.
9163 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9164 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009165 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009166 + r.appInfo.packageName + "/"
9167 + r.appInfo.uid + " for service "
9168 + r.intent.getIntent() + ": process is bad");
9169 bringDownServiceLocked(r, true);
9170 return false;
9171 }
9172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009174 mPendingServices.add(r);
9175 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 return true;
9178 }
9179
9180 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009181 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182 //r.dump(" ");
9183
9184 // Does it still need to run?
9185 if (!force && r.startRequested) {
9186 return;
9187 }
9188 if (r.connections.size() > 0) {
9189 if (!force) {
9190 // XXX should probably keep a count of the number of auto-create
9191 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009192 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009193 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009194 ArrayList<ConnectionRecord> cr = it.next();
9195 for (int i=0; i<cr.size(); i++) {
9196 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9197 return;
9198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009199 }
9200 }
9201 }
9202
9203 // Report to all of the connections that the service is no longer
9204 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009205 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009206 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009207 ArrayList<ConnectionRecord> c = it.next();
9208 for (int i=0; i<c.size(); i++) {
9209 try {
9210 c.get(i).conn.connected(r.name, null);
9211 } catch (Exception e) {
9212 Slog.w(TAG, "Failure disconnecting service " + r.name +
9213 " to connection " + c.get(i).conn.asBinder() +
9214 " (in " + c.get(i).binding.client.processName + ")", e);
9215 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009216 }
9217 }
9218 }
9219
9220 // Tell the service that it has been unbound.
9221 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9222 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9223 while (it.hasNext()) {
9224 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009225 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 + ": hasBound=" + ibr.hasBound);
9227 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9228 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009229 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009230 updateOomAdjLocked(r.app);
9231 ibr.hasBound = false;
9232 r.app.thread.scheduleUnbindService(r,
9233 ibr.intent.getIntent());
9234 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009235 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009236 + r.shortName, e);
9237 serviceDoneExecutingLocked(r, true);
9238 }
9239 }
9240 }
9241 }
9242
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009243 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009244 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009245 System.identityHashCode(r), r.shortName,
9246 (r.app != null) ? r.app.pid : -1);
9247
9248 mServices.remove(r.name);
9249 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 r.totalRestartCount = 0;
9251 unscheduleServiceRestartLocked(r);
9252
9253 // Also make sure it is not on the pending list.
9254 int N = mPendingServices.size();
9255 for (int i=0; i<N; i++) {
9256 if (mPendingServices.get(i) == r) {
9257 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009258 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009259 i--;
9260 N--;
9261 }
9262 }
9263
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009264 r.cancelNotification();
9265 r.isForeground = false;
9266 r.foregroundId = 0;
9267 r.foregroundNoti = null;
9268
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009269 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009270 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009271 r.pendingStarts.clear();
9272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009273 if (r.app != null) {
9274 synchronized (r.stats.getBatteryStats()) {
9275 r.stats.stopLaunchedLocked();
9276 }
9277 r.app.services.remove(r);
9278 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009279 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009280 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009281 mStoppingServices.add(r);
9282 updateOomAdjLocked(r.app);
9283 r.app.thread.scheduleStopService(r);
9284 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009285 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009286 + r.shortName, e);
9287 serviceDoneExecutingLocked(r, true);
9288 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009289 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009290 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009291 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009292 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009293 }
9294 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009295 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009296 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009297 }
9298 }
9299
9300 ComponentName startServiceLocked(IApplicationThread caller,
9301 Intent service, String resolvedType,
9302 int callingPid, int callingUid) {
9303 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009304 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009305 + " type=" + resolvedType + " args=" + service.getExtras());
9306
9307 if (caller != null) {
9308 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9309 if (callerApp == null) {
9310 throw new SecurityException(
9311 "Unable to find app for caller " + caller
9312 + " (pid=" + Binder.getCallingPid()
9313 + ") when starting service " + service);
9314 }
9315 }
9316
9317 ServiceLookupResult res =
9318 retrieveServiceLocked(service, resolvedType,
9319 callingPid, callingUid);
9320 if (res == null) {
9321 return null;
9322 }
9323 if (res.record == null) {
9324 return new ComponentName("!", res.permission != null
9325 ? res.permission : "private to package");
9326 }
9327 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009328 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9329 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009330 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009331 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009332 }
9333 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009334 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009335 r.lastStartId++;
9336 if (r.lastStartId < 1) {
9337 r.lastStartId = 1;
9338 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009339 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9340 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009341 r.lastActivity = SystemClock.uptimeMillis();
9342 synchronized (r.stats.getBatteryStats()) {
9343 r.stats.startRunningLocked();
9344 }
9345 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9346 return new ComponentName("!", "Service process is bad");
9347 }
9348 return r.name;
9349 }
9350 }
9351
9352 public ComponentName startService(IApplicationThread caller, Intent service,
9353 String resolvedType) {
9354 // Refuse possible leaked file descriptors
9355 if (service != null && service.hasFileDescriptors() == true) {
9356 throw new IllegalArgumentException("File descriptors passed in Intent");
9357 }
9358
9359 synchronized(this) {
9360 final int callingPid = Binder.getCallingPid();
9361 final int callingUid = Binder.getCallingUid();
9362 final long origId = Binder.clearCallingIdentity();
9363 ComponentName res = startServiceLocked(caller, service,
9364 resolvedType, callingPid, callingUid);
9365 Binder.restoreCallingIdentity(origId);
9366 return res;
9367 }
9368 }
9369
9370 ComponentName startServiceInPackage(int uid,
9371 Intent service, String resolvedType) {
9372 synchronized(this) {
9373 final long origId = Binder.clearCallingIdentity();
9374 ComponentName res = startServiceLocked(null, service,
9375 resolvedType, -1, uid);
9376 Binder.restoreCallingIdentity(origId);
9377 return res;
9378 }
9379 }
9380
9381 public int stopService(IApplicationThread caller, Intent service,
9382 String resolvedType) {
9383 // Refuse possible leaked file descriptors
9384 if (service != null && service.hasFileDescriptors() == true) {
9385 throw new IllegalArgumentException("File descriptors passed in Intent");
9386 }
9387
9388 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009389 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009390 + " type=" + resolvedType);
9391
9392 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9393 if (caller != null && callerApp == null) {
9394 throw new SecurityException(
9395 "Unable to find app for caller " + caller
9396 + " (pid=" + Binder.getCallingPid()
9397 + ") when stopping service " + service);
9398 }
9399
9400 // If this service is active, make sure it is stopped.
9401 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9402 if (r != null) {
9403 if (r.record != null) {
9404 synchronized (r.record.stats.getBatteryStats()) {
9405 r.record.stats.stopRunningLocked();
9406 }
9407 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009408 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009409 final long origId = Binder.clearCallingIdentity();
9410 bringDownServiceLocked(r.record, false);
9411 Binder.restoreCallingIdentity(origId);
9412 return 1;
9413 }
9414 return -1;
9415 }
9416 }
9417
9418 return 0;
9419 }
9420
9421 public IBinder peekService(Intent service, String resolvedType) {
9422 // Refuse possible leaked file descriptors
9423 if (service != null && service.hasFileDescriptors() == true) {
9424 throw new IllegalArgumentException("File descriptors passed in Intent");
9425 }
9426
9427 IBinder ret = null;
9428
9429 synchronized(this) {
9430 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9431
9432 if (r != null) {
9433 // r.record is null if findServiceLocked() failed the caller permission check
9434 if (r.record == null) {
9435 throw new SecurityException(
9436 "Permission Denial: Accessing service " + r.record.name
9437 + " from pid=" + Binder.getCallingPid()
9438 + ", uid=" + Binder.getCallingUid()
9439 + " requires " + r.permission);
9440 }
9441 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9442 if (ib != null) {
9443 ret = ib.binder;
9444 }
9445 }
9446 }
9447
9448 return ret;
9449 }
9450
9451 public boolean stopServiceToken(ComponentName className, IBinder token,
9452 int startId) {
9453 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009454 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009455 + " " + token + " startId=" + startId);
9456 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009457 if (r != null) {
9458 if (startId >= 0) {
9459 // Asked to only stop if done with all work. Note that
9460 // to avoid leaks, we will take this as dropping all
9461 // start items up to and including this one.
9462 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9463 if (si != null) {
9464 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009465 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9466 cur.removeUriPermissionsLocked();
9467 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009468 break;
9469 }
9470 }
9471 }
9472
9473 if (r.lastStartId != startId) {
9474 return false;
9475 }
9476
9477 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009478 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009479 + " is last, but have " + r.deliveredStarts.size()
9480 + " remaining args");
9481 }
9482 }
9483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009484 synchronized (r.stats.getBatteryStats()) {
9485 r.stats.stopRunningLocked();
9486 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009487 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009488 }
9489 final long origId = Binder.clearCallingIdentity();
9490 bringDownServiceLocked(r, false);
9491 Binder.restoreCallingIdentity(origId);
9492 return true;
9493 }
9494 }
9495 return false;
9496 }
9497
9498 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009499 int id, Notification notification, boolean removeNotification) {
9500 final long origId = Binder.clearCallingIdentity();
9501 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009502 synchronized(this) {
9503 ServiceRecord r = findServiceLocked(className, token);
9504 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009505 if (id != 0) {
9506 if (notification == null) {
9507 throw new IllegalArgumentException("null notification");
9508 }
9509 if (r.foregroundId != id) {
9510 r.cancelNotification();
9511 r.foregroundId = id;
9512 }
9513 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9514 r.foregroundNoti = notification;
9515 r.isForeground = true;
9516 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009517 if (r.app != null) {
9518 updateServiceForegroundLocked(r.app, true);
9519 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009520 } else {
9521 if (r.isForeground) {
9522 r.isForeground = false;
9523 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009524 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009525 updateServiceForegroundLocked(r.app, true);
9526 }
9527 }
9528 if (removeNotification) {
9529 r.cancelNotification();
9530 r.foregroundId = 0;
9531 r.foregroundNoti = null;
9532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009533 }
9534 }
9535 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009536 } finally {
9537 Binder.restoreCallingIdentity(origId);
9538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009539 }
9540
9541 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9542 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009543 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009544 if (sr.isForeground) {
9545 anyForeground = true;
9546 break;
9547 }
9548 }
9549 if (anyForeground != proc.foregroundServices) {
9550 proc.foregroundServices = anyForeground;
9551 if (oomAdj) {
9552 updateOomAdjLocked();
9553 }
9554 }
9555 }
9556
9557 public int bindService(IApplicationThread caller, IBinder token,
9558 Intent service, String resolvedType,
9559 IServiceConnection connection, int flags) {
9560 // Refuse possible leaked file descriptors
9561 if (service != null && service.hasFileDescriptors() == true) {
9562 throw new IllegalArgumentException("File descriptors passed in Intent");
9563 }
9564
9565 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009566 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009567 + " type=" + resolvedType + " conn=" + connection.asBinder()
9568 + " flags=0x" + Integer.toHexString(flags));
9569 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9570 if (callerApp == null) {
9571 throw new SecurityException(
9572 "Unable to find app for caller " + caller
9573 + " (pid=" + Binder.getCallingPid()
9574 + ") when binding service " + service);
9575 }
9576
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009577 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009579 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009580 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009581 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009582 return 0;
9583 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009584 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009585 }
9586
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009587 int clientLabel = 0;
9588 PendingIntent clientIntent = null;
9589
9590 if (callerApp.info.uid == Process.SYSTEM_UID) {
9591 // Hacky kind of thing -- allow system stuff to tell us
9592 // what they are, so we can report this elsewhere for
9593 // others to know why certain services are running.
9594 try {
9595 clientIntent = (PendingIntent)service.getParcelableExtra(
9596 Intent.EXTRA_CLIENT_INTENT);
9597 } catch (RuntimeException e) {
9598 }
9599 if (clientIntent != null) {
9600 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9601 if (clientLabel != 0) {
9602 // There are no useful extras in the intent, trash them.
9603 // System code calling with this stuff just needs to know
9604 // this will happen.
9605 service = service.cloneFilter();
9606 }
9607 }
9608 }
9609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009610 ServiceLookupResult res =
9611 retrieveServiceLocked(service, resolvedType,
9612 Binder.getCallingPid(), Binder.getCallingUid());
9613 if (res == null) {
9614 return 0;
9615 }
9616 if (res.record == null) {
9617 return -1;
9618 }
9619 ServiceRecord s = res.record;
9620
9621 final long origId = Binder.clearCallingIdentity();
9622
9623 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009624 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009625 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626 }
9627
9628 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9629 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009630 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009631
9632 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009633 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9634 if (clist == null) {
9635 clist = new ArrayList<ConnectionRecord>();
9636 s.connections.put(binder, clist);
9637 }
9638 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009639 b.connections.add(c);
9640 if (activity != null) {
9641 if (activity.connections == null) {
9642 activity.connections = new HashSet<ConnectionRecord>();
9643 }
9644 activity.connections.add(c);
9645 }
9646 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009647 clist = mServiceConnections.get(binder);
9648 if (clist == null) {
9649 clist = new ArrayList<ConnectionRecord>();
9650 mServiceConnections.put(binder, clist);
9651 }
9652 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009653
9654 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9655 s.lastActivity = SystemClock.uptimeMillis();
9656 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9657 return 0;
9658 }
9659 }
9660
9661 if (s.app != null) {
9662 // This could have made the service more important.
9663 updateOomAdjLocked(s.app);
9664 }
9665
Joe Onorato8a9b2202010-02-26 18:56:32 -08009666 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667 + ": received=" + b.intent.received
9668 + " apps=" + b.intent.apps.size()
9669 + " doRebind=" + b.intent.doRebind);
9670
9671 if (s.app != null && b.intent.received) {
9672 // Service is already running, so we can immediately
9673 // publish the connection.
9674 try {
9675 c.conn.connected(s.name, b.intent.binder);
9676 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009677 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009678 + " to connection " + c.conn.asBinder()
9679 + " (in " + c.binding.client.processName + ")", e);
9680 }
9681
9682 // If this is the first app connected back to this binding,
9683 // and the service had previously asked to be told when
9684 // rebound, then do so.
9685 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9686 requestServiceBindingLocked(s, b.intent, true);
9687 }
9688 } else if (!b.intent.requested) {
9689 requestServiceBindingLocked(s, b.intent, false);
9690 }
9691
9692 Binder.restoreCallingIdentity(origId);
9693 }
9694
9695 return 1;
9696 }
9697
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009698 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009699 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700 IBinder binder = c.conn.asBinder();
9701 AppBindRecord b = c.binding;
9702 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009703 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9704 if (clist != null) {
9705 clist.remove(c);
9706 if (clist.size() == 0) {
9707 s.connections.remove(binder);
9708 }
9709 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009710 b.connections.remove(c);
9711 if (c.activity != null && c.activity != skipAct) {
9712 if (c.activity.connections != null) {
9713 c.activity.connections.remove(c);
9714 }
9715 }
9716 if (b.client != skipApp) {
9717 b.client.connections.remove(c);
9718 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009719 clist = mServiceConnections.get(binder);
9720 if (clist != null) {
9721 clist.remove(c);
9722 if (clist.size() == 0) {
9723 mServiceConnections.remove(binder);
9724 }
9725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009726
9727 if (b.connections.size() == 0) {
9728 b.intent.apps.remove(b.client);
9729 }
9730
Joe Onorato8a9b2202010-02-26 18:56:32 -08009731 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009732 + ": shouldUnbind=" + b.intent.hasBound);
9733 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9734 && b.intent.hasBound) {
9735 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009736 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009737 updateOomAdjLocked(s.app);
9738 b.intent.hasBound = false;
9739 // Assume the client doesn't want to know about a rebind;
9740 // we will deal with that later if it asks for one.
9741 b.intent.doRebind = false;
9742 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9743 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009744 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009745 serviceDoneExecutingLocked(s, true);
9746 }
9747 }
9748
9749 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9750 bringDownServiceLocked(s, false);
9751 }
9752 }
9753
9754 public boolean unbindService(IServiceConnection connection) {
9755 synchronized (this) {
9756 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009757 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009758 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9759 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009760 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009761 + connection.asBinder());
9762 return false;
9763 }
9764
9765 final long origId = Binder.clearCallingIdentity();
9766
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009767 while (clist.size() > 0) {
9768 ConnectionRecord r = clist.get(0);
9769 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009770
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009771 if (r.binding.service.app != null) {
9772 // This could have made the service less important.
9773 updateOomAdjLocked(r.binding.service.app);
9774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009775 }
9776
9777 Binder.restoreCallingIdentity(origId);
9778 }
9779
9780 return true;
9781 }
9782
9783 public void publishService(IBinder token, Intent intent, IBinder service) {
9784 // Refuse possible leaked file descriptors
9785 if (intent != null && intent.hasFileDescriptors() == true) {
9786 throw new IllegalArgumentException("File descriptors passed in Intent");
9787 }
9788
9789 synchronized(this) {
9790 if (!(token instanceof ServiceRecord)) {
9791 throw new IllegalArgumentException("Invalid service token");
9792 }
9793 ServiceRecord r = (ServiceRecord)token;
9794
9795 final long origId = Binder.clearCallingIdentity();
9796
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009797 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009798 + " " + intent + ": " + service);
9799 if (r != null) {
9800 Intent.FilterComparison filter
9801 = new Intent.FilterComparison(intent);
9802 IntentBindRecord b = r.bindings.get(filter);
9803 if (b != null && !b.received) {
9804 b.binder = service;
9805 b.requested = true;
9806 b.received = true;
9807 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009808 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009809 = r.connections.values().iterator();
9810 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009811 ArrayList<ConnectionRecord> clist = it.next();
9812 for (int i=0; i<clist.size(); i++) {
9813 ConnectionRecord c = clist.get(i);
9814 if (!filter.equals(c.binding.intent.intent)) {
9815 if (DEBUG_SERVICE) Slog.v(
9816 TAG, "Not publishing to: " + c);
9817 if (DEBUG_SERVICE) Slog.v(
9818 TAG, "Bound intent: " + c.binding.intent.intent);
9819 if (DEBUG_SERVICE) Slog.v(
9820 TAG, "Published intent: " + intent);
9821 continue;
9822 }
9823 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9824 try {
9825 c.conn.connected(r.name, service);
9826 } catch (Exception e) {
9827 Slog.w(TAG, "Failure sending service " + r.name +
9828 " to connection " + c.conn.asBinder() +
9829 " (in " + c.binding.client.processName + ")", e);
9830 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009831 }
9832 }
9833 }
9834 }
9835
9836 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9837
9838 Binder.restoreCallingIdentity(origId);
9839 }
9840 }
9841 }
9842
9843 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9844 // Refuse possible leaked file descriptors
9845 if (intent != null && intent.hasFileDescriptors() == true) {
9846 throw new IllegalArgumentException("File descriptors passed in Intent");
9847 }
9848
9849 synchronized(this) {
9850 if (!(token instanceof ServiceRecord)) {
9851 throw new IllegalArgumentException("Invalid service token");
9852 }
9853 ServiceRecord r = (ServiceRecord)token;
9854
9855 final long origId = Binder.clearCallingIdentity();
9856
9857 if (r != null) {
9858 Intent.FilterComparison filter
9859 = new Intent.FilterComparison(intent);
9860 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009861 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009862 + " at " + b + ": apps="
9863 + (b != null ? b.apps.size() : 0));
9864 if (b != null) {
9865 if (b.apps.size() > 0) {
9866 // Applications have already bound since the last
9867 // unbind, so just rebind right here.
9868 requestServiceBindingLocked(r, b, true);
9869 } else {
9870 // Note to tell the service the next time there is
9871 // a new client.
9872 b.doRebind = true;
9873 }
9874 }
9875
9876 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9877
9878 Binder.restoreCallingIdentity(origId);
9879 }
9880 }
9881 }
9882
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009883 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009884 synchronized(this) {
9885 if (!(token instanceof ServiceRecord)) {
9886 throw new IllegalArgumentException("Invalid service token");
9887 }
9888 ServiceRecord r = (ServiceRecord)token;
9889 boolean inStopping = mStoppingServices.contains(token);
9890 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009891 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009892 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009893 + " with incorrect token: given " + token
9894 + ", expected " + r);
9895 return;
9896 }
9897
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009898 if (type == 1) {
9899 // This is a call from a service start... take care of
9900 // book-keeping.
9901 r.callStart = true;
9902 switch (res) {
9903 case Service.START_STICKY_COMPATIBILITY:
9904 case Service.START_STICKY: {
9905 // We are done with the associated start arguments.
9906 r.findDeliveredStart(startId, true);
9907 // Don't stop if killed.
9908 r.stopIfKilled = false;
9909 break;
9910 }
9911 case Service.START_NOT_STICKY: {
9912 // We are done with the associated start arguments.
9913 r.findDeliveredStart(startId, true);
9914 if (r.lastStartId == startId) {
9915 // There is no more work, and this service
9916 // doesn't want to hang around if killed.
9917 r.stopIfKilled = true;
9918 }
9919 break;
9920 }
9921 case Service.START_REDELIVER_INTENT: {
9922 // We'll keep this item until they explicitly
9923 // call stop for it, but keep track of the fact
9924 // that it was delivered.
9925 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9926 if (si != null) {
9927 si.deliveryCount = 0;
9928 si.doneExecutingCount++;
9929 // Don't stop if killed.
9930 r.stopIfKilled = true;
9931 }
9932 break;
9933 }
9934 default:
9935 throw new IllegalArgumentException(
9936 "Unknown service start result: " + res);
9937 }
9938 if (res == Service.START_STICKY_COMPATIBILITY) {
9939 r.callStart = false;
9940 }
9941 }
9942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 final long origId = Binder.clearCallingIdentity();
9944 serviceDoneExecutingLocked(r, inStopping);
9945 Binder.restoreCallingIdentity(origId);
9946 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009947 Slog.w(TAG, "Done executing unknown service from pid "
9948 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009949 }
9950 }
9951 }
9952
9953 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009954 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9955 + ": nesting=" + r.executeNesting
9956 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009957 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009958 r.executeNesting--;
9959 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009960 if (DEBUG_SERVICE) Slog.v(TAG,
9961 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 r.app.executingServices.remove(r);
9963 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009964 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9965 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009966 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9967 }
9968 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009969 if (DEBUG_SERVICE) Slog.v(TAG,
9970 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971 mStoppingServices.remove(r);
9972 }
9973 updateOomAdjLocked(r.app);
9974 }
9975 }
9976
9977 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009978 String anrMessage = null;
9979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009980 synchronized(this) {
9981 if (proc.executingServices.size() == 0 || proc.thread == null) {
9982 return;
9983 }
9984 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9985 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9986 ServiceRecord timeout = null;
9987 long nextTime = 0;
9988 while (it.hasNext()) {
9989 ServiceRecord sr = it.next();
9990 if (sr.executingStart < maxTime) {
9991 timeout = sr;
9992 break;
9993 }
9994 if (sr.executingStart > nextTime) {
9995 nextTime = sr.executingStart;
9996 }
9997 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009998 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009999 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010000 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001 } else {
10002 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10003 msg.obj = proc;
10004 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10005 }
10006 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010007
10008 if (anrMessage != null) {
10009 appNotResponding(proc, null, null, anrMessage);
10010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010011 }
10012
10013 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010014 // BACKUP AND RESTORE
10015 // =========================================================
10016
10017 // Cause the target app to be launched if necessary and its backup agent
10018 // instantiated. The backup agent will invoke backupAgentCreated() on the
10019 // activity manager to announce its creation.
10020 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010021 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010022 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10023
10024 synchronized(this) {
10025 // !!! TODO: currently no check here that we're already bound
10026 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10027 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10028 synchronized (stats) {
10029 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10030 }
10031
10032 BackupRecord r = new BackupRecord(ss, app, backupMode);
10033 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10034 // startProcessLocked() returns existing proc's record if it's already running
10035 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010036 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010037 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010038 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010039 return false;
10040 }
10041
10042 r.app = proc;
10043 mBackupTarget = r;
10044 mBackupAppName = app.packageName;
10045
Christopher Tate6fa95972009-06-05 18:43:55 -070010046 // Try not to kill the process during backup
10047 updateOomAdjLocked(proc);
10048
Christopher Tate181fafa2009-05-14 11:12:14 -070010049 // If the process is already attached, schedule the creation of the backup agent now.
10050 // If it is not yet live, this will be done when it attaches to the framework.
10051 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010052 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010053 try {
10054 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10055 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010056 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010057 }
10058 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010059 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010060 }
10061 // Invariants: at this point, the target app process exists and the application
10062 // is either already running or in the process of coming up. mBackupTarget and
10063 // mBackupAppName describe the app, so that when it binds back to the AM we
10064 // know that it's scheduled for a backup-agent operation.
10065 }
10066
10067 return true;
10068 }
10069
10070 // A backup agent has just come up
10071 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010072 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010073 + " = " + agent);
10074
10075 synchronized(this) {
10076 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010077 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010078 return;
10079 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010080 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010081
Dianne Hackborn06740692010-09-22 22:46:21 -070010082 long oldIdent = Binder.clearCallingIdentity();
10083 try {
10084 IBackupManager bm = IBackupManager.Stub.asInterface(
10085 ServiceManager.getService(Context.BACKUP_SERVICE));
10086 bm.agentConnected(agentPackageName, agent);
10087 } catch (RemoteException e) {
10088 // can't happen; the backup manager service is local
10089 } catch (Exception e) {
10090 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10091 e.printStackTrace();
10092 } finally {
10093 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010094 }
10095 }
10096
10097 // done with this agent
10098 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010099 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010100 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010101 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010102 return;
10103 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010104
10105 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010106 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010107 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010108 return;
10109 }
10110
Christopher Tate181fafa2009-05-14 11:12:14 -070010111 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010112 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010113 return;
10114 }
10115
Christopher Tate6fa95972009-06-05 18:43:55 -070010116 ProcessRecord proc = mBackupTarget.app;
10117 mBackupTarget = null;
10118 mBackupAppName = null;
10119
10120 // Not backing this app up any more; reset its OOM adjustment
10121 updateOomAdjLocked(proc);
10122
Christopher Tatec7b31e32009-06-10 15:49:30 -070010123 // If the app crashed during backup, 'thread' will be null here
10124 if (proc.thread != null) {
10125 try {
10126 proc.thread.scheduleDestroyBackupAgent(appInfo);
10127 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010128 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010129 e.printStackTrace();
10130 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010131 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010132 }
10133 }
10134 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010135 // BROADCASTS
10136 // =========================================================
10137
Josh Bartel7f208742010-02-25 11:01:44 -060010138 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010139 List cur) {
10140 final ContentResolver resolver = mContext.getContentResolver();
10141 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10142 if (list == null) {
10143 return cur;
10144 }
10145 int N = list.size();
10146 for (int i=0; i<N; i++) {
10147 Intent intent = list.get(i);
10148 if (filter.match(resolver, intent, true, TAG) >= 0) {
10149 if (cur == null) {
10150 cur = new ArrayList<Intent>();
10151 }
10152 cur.add(intent);
10153 }
10154 }
10155 return cur;
10156 }
10157
10158 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010159 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010160 + mBroadcastsScheduled);
10161
10162 if (mBroadcastsScheduled) {
10163 return;
10164 }
10165 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10166 mBroadcastsScheduled = true;
10167 }
10168
10169 public Intent registerReceiver(IApplicationThread caller,
10170 IIntentReceiver receiver, IntentFilter filter, String permission) {
10171 synchronized(this) {
10172 ProcessRecord callerApp = null;
10173 if (caller != null) {
10174 callerApp = getRecordForAppLocked(caller);
10175 if (callerApp == null) {
10176 throw new SecurityException(
10177 "Unable to find app for caller " + caller
10178 + " (pid=" + Binder.getCallingPid()
10179 + ") when registering receiver " + receiver);
10180 }
10181 }
10182
10183 List allSticky = null;
10184
10185 // Look for any matching sticky broadcasts...
10186 Iterator actions = filter.actionsIterator();
10187 if (actions != null) {
10188 while (actions.hasNext()) {
10189 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010190 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010191 }
10192 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010193 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010194 }
10195
10196 // The first sticky in the list is returned directly back to
10197 // the client.
10198 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10199
Joe Onorato8a9b2202010-02-26 18:56:32 -080010200 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010201 + ": " + sticky);
10202
10203 if (receiver == null) {
10204 return sticky;
10205 }
10206
10207 ReceiverList rl
10208 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10209 if (rl == null) {
10210 rl = new ReceiverList(this, callerApp,
10211 Binder.getCallingPid(),
10212 Binder.getCallingUid(), receiver);
10213 if (rl.app != null) {
10214 rl.app.receivers.add(rl);
10215 } else {
10216 try {
10217 receiver.asBinder().linkToDeath(rl, 0);
10218 } catch (RemoteException e) {
10219 return sticky;
10220 }
10221 rl.linkedToDeath = true;
10222 }
10223 mRegisteredReceivers.put(receiver.asBinder(), rl);
10224 }
10225 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10226 rl.add(bf);
10227 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010228 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010229 }
10230 mReceiverResolver.addFilter(bf);
10231
10232 // Enqueue broadcasts for all existing stickies that match
10233 // this filter.
10234 if (allSticky != null) {
10235 ArrayList receivers = new ArrayList();
10236 receivers.add(bf);
10237
10238 int N = allSticky.size();
10239 for (int i=0; i<N; i++) {
10240 Intent intent = (Intent)allSticky.get(i);
10241 BroadcastRecord r = new BroadcastRecord(intent, null,
10242 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010243 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010244 if (mParallelBroadcasts.size() == 0) {
10245 scheduleBroadcastsLocked();
10246 }
10247 mParallelBroadcasts.add(r);
10248 }
10249 }
10250
10251 return sticky;
10252 }
10253 }
10254
10255 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010256 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010257
10258 boolean doNext = false;
10259
10260 synchronized(this) {
10261 ReceiverList rl
10262 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10263 if (rl != null) {
10264 if (rl.curBroadcast != null) {
10265 BroadcastRecord r = rl.curBroadcast;
10266 doNext = finishReceiverLocked(
10267 receiver.asBinder(), r.resultCode, r.resultData,
10268 r.resultExtras, r.resultAbort, true);
10269 }
10270
10271 if (rl.app != null) {
10272 rl.app.receivers.remove(rl);
10273 }
10274 removeReceiverLocked(rl);
10275 if (rl.linkedToDeath) {
10276 rl.linkedToDeath = false;
10277 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10278 }
10279 }
10280 }
10281
10282 if (!doNext) {
10283 return;
10284 }
10285
10286 final long origId = Binder.clearCallingIdentity();
10287 processNextBroadcast(false);
10288 trimApplications();
10289 Binder.restoreCallingIdentity(origId);
10290 }
10291
10292 void removeReceiverLocked(ReceiverList rl) {
10293 mRegisteredReceivers.remove(rl.receiver.asBinder());
10294 int N = rl.size();
10295 for (int i=0; i<N; i++) {
10296 mReceiverResolver.removeFilter(rl.get(i));
10297 }
10298 }
10299
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010300 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10301 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10302 ProcessRecord r = mLruProcesses.get(i);
10303 if (r.thread != null) {
10304 try {
10305 r.thread.dispatchPackageBroadcast(cmd, packages);
10306 } catch (RemoteException ex) {
10307 }
10308 }
10309 }
10310 }
10311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010312 private final int broadcastIntentLocked(ProcessRecord callerApp,
10313 String callerPackage, Intent intent, String resolvedType,
10314 IIntentReceiver resultTo, int resultCode, String resultData,
10315 Bundle map, String requiredPermission,
10316 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10317 intent = new Intent(intent);
10318
Joe Onorato8a9b2202010-02-26 18:56:32 -080010319 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010320 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10321 + " ordered=" + ordered);
10322 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010323 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010324 }
10325
10326 // Handle special intents: if this broadcast is from the package
10327 // manager about a package being removed, we need to remove all of
10328 // its activities from the history stack.
10329 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10330 intent.getAction());
10331 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10332 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010333 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010334 || uidRemoved) {
10335 if (checkComponentPermission(
10336 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10337 callingPid, callingUid, -1)
10338 == PackageManager.PERMISSION_GRANTED) {
10339 if (uidRemoved) {
10340 final Bundle intentExtras = intent.getExtras();
10341 final int uid = intentExtras != null
10342 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10343 if (uid >= 0) {
10344 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10345 synchronized (bs) {
10346 bs.removeUidStatsLocked(uid);
10347 }
10348 }
10349 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010350 // If resources are unvailble just force stop all
10351 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010352 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010353 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10354 if (list != null && (list.length > 0)) {
10355 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010356 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010357 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010358 sendPackageBroadcastLocked(
10359 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010360 }
10361 } else {
10362 Uri data = intent.getData();
10363 String ssp;
10364 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10365 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10366 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010367 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010368 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010369 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10370 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10371 new String[] {ssp});
10372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 }
10374 }
10375 }
10376 } else {
10377 String msg = "Permission Denial: " + intent.getAction()
10378 + " broadcast from " + callerPackage + " (pid=" + callingPid
10379 + ", uid=" + callingUid + ")"
10380 + " requires "
10381 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010382 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010383 throw new SecurityException(msg);
10384 }
10385 }
10386
10387 /*
10388 * If this is the time zone changed action, queue up a message that will reset the timezone
10389 * of all currently running processes. This message will get queued up before the broadcast
10390 * happens.
10391 */
10392 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10393 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10394 }
10395
Robert Greenwalt03595d02010-11-02 14:08:23 -070010396 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10397 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10398 }
10399
Dianne Hackborn854060af2009-07-09 18:14:31 -070010400 /*
10401 * Prevent non-system code (defined here to be non-persistent
10402 * processes) from sending protected broadcasts.
10403 */
10404 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10405 || callingUid == Process.SHELL_UID || callingUid == 0) {
10406 // Always okay.
10407 } else if (callerApp == null || !callerApp.persistent) {
10408 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010409 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010410 intent.getAction())) {
10411 String msg = "Permission Denial: not allowed to send broadcast "
10412 + intent.getAction() + " from pid="
10413 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010414 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010415 throw new SecurityException(msg);
10416 }
10417 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010418 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010419 return BROADCAST_SUCCESS;
10420 }
10421 }
10422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 // Add to the sticky list if requested.
10424 if (sticky) {
10425 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10426 callingPid, callingUid)
10427 != PackageManager.PERMISSION_GRANTED) {
10428 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10429 + callingPid + ", uid=" + callingUid
10430 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010431 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010432 throw new SecurityException(msg);
10433 }
10434 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010435 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010436 + " and enforce permission " + requiredPermission);
10437 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10438 }
10439 if (intent.getComponent() != null) {
10440 throw new SecurityException(
10441 "Sticky broadcasts can't target a specific component");
10442 }
10443 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10444 if (list == null) {
10445 list = new ArrayList<Intent>();
10446 mStickyBroadcasts.put(intent.getAction(), list);
10447 }
10448 int N = list.size();
10449 int i;
10450 for (i=0; i<N; i++) {
10451 if (intent.filterEquals(list.get(i))) {
10452 // This sticky already exists, replace it.
10453 list.set(i, new Intent(intent));
10454 break;
10455 }
10456 }
10457 if (i >= N) {
10458 list.add(new Intent(intent));
10459 }
10460 }
10461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010462 // Figure out who all will receive this broadcast.
10463 List receivers = null;
10464 List<BroadcastFilter> registeredReceivers = null;
10465 try {
10466 if (intent.getComponent() != null) {
10467 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010468 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010469 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010470 if (ai != null) {
10471 receivers = new ArrayList();
10472 ResolveInfo ri = new ResolveInfo();
10473 ri.activityInfo = ai;
10474 receivers.add(ri);
10475 }
10476 } else {
10477 // Need to resolve the intent to interested receivers...
10478 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10479 == 0) {
10480 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010481 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010482 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010483 }
Mihai Preda074edef2009-05-18 17:13:31 +020010484 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010485 }
10486 } catch (RemoteException ex) {
10487 // pm is in same process, this will never happen.
10488 }
10489
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010490 final boolean replacePending =
10491 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10492
Joe Onorato8a9b2202010-02-26 18:56:32 -080010493 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010494 + " replacePending=" + replacePending);
10495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010496 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10497 if (!ordered && NR > 0) {
10498 // If we are not serializing this broadcast, then send the
10499 // registered receivers separately so they don't wait for the
10500 // components to be launched.
10501 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10502 callerPackage, callingPid, callingUid, requiredPermission,
10503 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010504 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010505 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010506 TAG, "Enqueueing parallel broadcast " + r
10507 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010508 boolean replaced = false;
10509 if (replacePending) {
10510 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10511 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010512 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010513 "***** DROPPING PARALLEL: " + intent);
10514 mParallelBroadcasts.set(i, r);
10515 replaced = true;
10516 break;
10517 }
10518 }
10519 }
10520 if (!replaced) {
10521 mParallelBroadcasts.add(r);
10522 scheduleBroadcastsLocked();
10523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010524 registeredReceivers = null;
10525 NR = 0;
10526 }
10527
10528 // Merge into one list.
10529 int ir = 0;
10530 if (receivers != null) {
10531 // A special case for PACKAGE_ADDED: do not allow the package
10532 // being added to see this broadcast. This prevents them from
10533 // using this as a back door to get run as soon as they are
10534 // installed. Maybe in the future we want to have a special install
10535 // broadcast or such for apps, but we'd like to deliberately make
10536 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010537 String skipPackages[] = null;
10538 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10539 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10540 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10541 Uri data = intent.getData();
10542 if (data != null) {
10543 String pkgName = data.getSchemeSpecificPart();
10544 if (pkgName != null) {
10545 skipPackages = new String[] { pkgName };
10546 }
10547 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010548 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010549 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010550 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010551 if (skipPackages != null && (skipPackages.length > 0)) {
10552 for (String skipPackage : skipPackages) {
10553 if (skipPackage != null) {
10554 int NT = receivers.size();
10555 for (int it=0; it<NT; it++) {
10556 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10557 if (curt.activityInfo.packageName.equals(skipPackage)) {
10558 receivers.remove(it);
10559 it--;
10560 NT--;
10561 }
10562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010563 }
10564 }
10565 }
10566
10567 int NT = receivers != null ? receivers.size() : 0;
10568 int it = 0;
10569 ResolveInfo curt = null;
10570 BroadcastFilter curr = null;
10571 while (it < NT && ir < NR) {
10572 if (curt == null) {
10573 curt = (ResolveInfo)receivers.get(it);
10574 }
10575 if (curr == null) {
10576 curr = registeredReceivers.get(ir);
10577 }
10578 if (curr.getPriority() >= curt.priority) {
10579 // Insert this broadcast record into the final list.
10580 receivers.add(it, curr);
10581 ir++;
10582 curr = null;
10583 it++;
10584 NT++;
10585 } else {
10586 // Skip to the next ResolveInfo in the final list.
10587 it++;
10588 curt = null;
10589 }
10590 }
10591 }
10592 while (ir < NR) {
10593 if (receivers == null) {
10594 receivers = new ArrayList();
10595 }
10596 receivers.add(registeredReceivers.get(ir));
10597 ir++;
10598 }
10599
10600 if ((receivers != null && receivers.size() > 0)
10601 || resultTo != null) {
10602 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10603 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010604 receivers, resultTo, resultCode, resultData, map, ordered,
10605 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010606 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010607 TAG, "Enqueueing ordered broadcast " + r
10608 + ": prev had " + mOrderedBroadcasts.size());
10609 if (DEBUG_BROADCAST) {
10610 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010611 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010612 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010613 boolean replaced = false;
10614 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010615 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010616 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010617 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010618 "***** DROPPING ORDERED: " + intent);
10619 mOrderedBroadcasts.set(i, r);
10620 replaced = true;
10621 break;
10622 }
10623 }
10624 }
10625 if (!replaced) {
10626 mOrderedBroadcasts.add(r);
10627 scheduleBroadcastsLocked();
10628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010629 }
10630
10631 return BROADCAST_SUCCESS;
10632 }
10633
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010634 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010635 // Refuse possible leaked file descriptors
10636 if (intent != null && intent.hasFileDescriptors() == true) {
10637 throw new IllegalArgumentException("File descriptors passed in Intent");
10638 }
10639
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010640 int flags = intent.getFlags();
10641
10642 if (!mProcessesReady) {
10643 // if the caller really truly claims to know what they're doing, go
10644 // ahead and allow the broadcast without launching any receivers
10645 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10646 intent = new Intent(intent);
10647 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10648 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10649 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10650 + " before boot completion");
10651 throw new IllegalStateException("Cannot broadcast before boot completed");
10652 }
10653 }
10654
10655 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10656 throw new IllegalArgumentException(
10657 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10658 }
10659
10660 return intent;
10661 }
10662
10663 public final int broadcastIntent(IApplicationThread caller,
10664 Intent intent, String resolvedType, IIntentReceiver resultTo,
10665 int resultCode, String resultData, Bundle map,
10666 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010668 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010670 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10671 final int callingPid = Binder.getCallingPid();
10672 final int callingUid = Binder.getCallingUid();
10673 final long origId = Binder.clearCallingIdentity();
10674 int res = broadcastIntentLocked(callerApp,
10675 callerApp != null ? callerApp.info.packageName : null,
10676 intent, resolvedType, resultTo,
10677 resultCode, resultData, map, requiredPermission, serialized,
10678 sticky, callingPid, callingUid);
10679 Binder.restoreCallingIdentity(origId);
10680 return res;
10681 }
10682 }
10683
10684 int broadcastIntentInPackage(String packageName, int uid,
10685 Intent intent, String resolvedType, IIntentReceiver resultTo,
10686 int resultCode, String resultData, Bundle map,
10687 String requiredPermission, boolean serialized, boolean sticky) {
10688 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010689 intent = verifyBroadcastLocked(intent);
10690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010691 final long origId = Binder.clearCallingIdentity();
10692 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10693 resultTo, resultCode, resultData, map, requiredPermission,
10694 serialized, sticky, -1, uid);
10695 Binder.restoreCallingIdentity(origId);
10696 return res;
10697 }
10698 }
10699
10700 public final void unbroadcastIntent(IApplicationThread caller,
10701 Intent intent) {
10702 // Refuse possible leaked file descriptors
10703 if (intent != null && intent.hasFileDescriptors() == true) {
10704 throw new IllegalArgumentException("File descriptors passed in Intent");
10705 }
10706
10707 synchronized(this) {
10708 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10709 != PackageManager.PERMISSION_GRANTED) {
10710 String msg = "Permission Denial: unbroadcastIntent() from pid="
10711 + Binder.getCallingPid()
10712 + ", uid=" + Binder.getCallingUid()
10713 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010714 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010715 throw new SecurityException(msg);
10716 }
10717 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10718 if (list != null) {
10719 int N = list.size();
10720 int i;
10721 for (i=0; i<N; i++) {
10722 if (intent.filterEquals(list.get(i))) {
10723 list.remove(i);
10724 break;
10725 }
10726 }
10727 }
10728 }
10729 }
10730
10731 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10732 String resultData, Bundle resultExtras, boolean resultAbort,
10733 boolean explicit) {
10734 if (mOrderedBroadcasts.size() == 0) {
10735 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010736 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010737 }
10738 return false;
10739 }
10740 BroadcastRecord r = mOrderedBroadcasts.get(0);
10741 if (r.receiver == null) {
10742 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010743 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010744 }
10745 return false;
10746 }
10747 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010748 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010749 return false;
10750 }
10751 int state = r.state;
10752 r.state = r.IDLE;
10753 if (state == r.IDLE) {
10754 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010755 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010756 }
10757 }
10758 r.receiver = null;
10759 r.intent.setComponent(null);
10760 if (r.curApp != null) {
10761 r.curApp.curReceiver = null;
10762 }
10763 if (r.curFilter != null) {
10764 r.curFilter.receiverList.curBroadcast = null;
10765 }
10766 r.curFilter = null;
10767 r.curApp = null;
10768 r.curComponent = null;
10769 r.curReceiver = null;
10770 mPendingBroadcast = null;
10771
10772 r.resultCode = resultCode;
10773 r.resultData = resultData;
10774 r.resultExtras = resultExtras;
10775 r.resultAbort = resultAbort;
10776
10777 // We will process the next receiver right now if this is finishing
10778 // an app receiver (which is always asynchronous) or after we have
10779 // come back from calling a receiver.
10780 return state == BroadcastRecord.APP_RECEIVE
10781 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10782 }
10783
10784 public void finishReceiver(IBinder who, int resultCode, String resultData,
10785 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010786 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010787
10788 // Refuse possible leaked file descriptors
10789 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10790 throw new IllegalArgumentException("File descriptors passed in Bundle");
10791 }
10792
10793 boolean doNext;
10794
10795 final long origId = Binder.clearCallingIdentity();
10796
10797 synchronized(this) {
10798 doNext = finishReceiverLocked(
10799 who, resultCode, resultData, resultExtras, resultAbort, true);
10800 }
10801
10802 if (doNext) {
10803 processNextBroadcast(false);
10804 }
10805 trimApplications();
10806
10807 Binder.restoreCallingIdentity(origId);
10808 }
10809
Jeff Brown4d94a762010-09-23 11:33:28 -070010810 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010811 if (r.nextReceiver > 0) {
10812 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10813 if (curReceiver instanceof BroadcastFilter) {
10814 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010815 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010816 System.identityHashCode(r),
10817 r.intent.getAction(),
10818 r.nextReceiver - 1,
10819 System.identityHashCode(bf));
10820 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010821 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010822 System.identityHashCode(r),
10823 r.intent.getAction(),
10824 r.nextReceiver - 1,
10825 ((ResolveInfo)curReceiver).toString());
10826 }
10827 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010828 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010830 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010831 System.identityHashCode(r),
10832 r.intent.getAction(),
10833 r.nextReceiver,
10834 "NONE");
10835 }
10836 }
10837
Jeff Brown4d94a762010-09-23 11:33:28 -070010838 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10839 if (! mPendingBroadcastTimeoutMessage) {
10840 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10841 mHandler.sendMessageAtTime(msg, timeoutTime);
10842 mPendingBroadcastTimeoutMessage = true;
10843 }
10844 }
10845
10846 private final void cancelBroadcastTimeoutLocked() {
10847 if (mPendingBroadcastTimeoutMessage) {
10848 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10849 mPendingBroadcastTimeoutMessage = false;
10850 }
10851 }
10852
10853 private final void broadcastTimeoutLocked(boolean fromMsg) {
10854 if (fromMsg) {
10855 mPendingBroadcastTimeoutMessage = false;
10856 }
10857
10858 if (mOrderedBroadcasts.size() == 0) {
10859 return;
10860 }
10861
10862 long now = SystemClock.uptimeMillis();
10863 BroadcastRecord r = mOrderedBroadcasts.get(0);
10864 if (fromMsg) {
10865 if (mDidDexOpt) {
10866 // Delay timeouts until dexopt finishes.
10867 mDidDexOpt = false;
10868 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10869 setBroadcastTimeoutLocked(timeoutTime);
10870 return;
10871 }
10872 if (! mProcessesReady) {
10873 // Only process broadcast timeouts if the system is ready. That way
10874 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10875 // to do heavy lifting for system up.
10876 return;
10877 }
10878
10879 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10880 if (timeoutTime > now) {
10881 // We can observe premature timeouts because we do not cancel and reset the
10882 // broadcast timeout message after each receiver finishes. Instead, we set up
10883 // an initial timeout then kick it down the road a little further as needed
10884 // when it expires.
10885 if (DEBUG_BROADCAST) Slog.v(TAG,
10886 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10887 + timeoutTime);
10888 setBroadcastTimeoutLocked(timeoutTime);
10889 return;
10890 }
10891 }
10892
10893 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10894 + ", started " + (now - r.receiverTime) + "ms ago");
10895 r.receiverTime = now;
10896 r.anrCount++;
10897
10898 // Current receiver has passed its expiration date.
10899 if (r.nextReceiver <= 0) {
10900 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10901 return;
10902 }
10903
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010904 ProcessRecord app = null;
10905 String anrMessage = null;
10906
Jeff Brown4d94a762010-09-23 11:33:28 -070010907 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10908 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10909 logBroadcastReceiverDiscardLocked(r);
10910 if (curReceiver instanceof BroadcastFilter) {
10911 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10912 if (bf.receiverList.pid != 0
10913 && bf.receiverList.pid != MY_PID) {
10914 synchronized (this.mPidsSelfLocked) {
10915 app = this.mPidsSelfLocked.get(
10916 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010918 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010919 } else {
10920 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010921 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010922
Jeff Brown4d94a762010-09-23 11:33:28 -070010923 if (app != null) {
10924 anrMessage = "Broadcast of " + r.intent.toString();
10925 }
10926
10927 if (mPendingBroadcast == r) {
10928 mPendingBroadcast = null;
10929 }
10930
10931 // Move on to the next receiver.
10932 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10933 r.resultExtras, r.resultAbort, true);
10934 scheduleBroadcastsLocked();
10935
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010936 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010937 // Post the ANR to the handler since we do not want to process ANRs while
10938 // potentially holding our lock.
10939 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010941 }
10942
10943 private final void processCurBroadcastLocked(BroadcastRecord r,
10944 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010945 if (DEBUG_BROADCAST) Slog.v(TAG,
10946 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010947 if (app.thread == null) {
10948 throw new RemoteException();
10949 }
10950 r.receiver = app.thread.asBinder();
10951 r.curApp = app;
10952 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010953 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954
10955 // Tell the application to launch this receiver.
10956 r.intent.setComponent(r.curComponent);
10957
10958 boolean started = false;
10959 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010960 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010961 "Delivering to component " + r.curComponent
10962 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010963 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010964 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10965 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010966 if (DEBUG_BROADCAST) Slog.v(TAG,
10967 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010968 started = true;
10969 } finally {
10970 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010971 if (DEBUG_BROADCAST) Slog.v(TAG,
10972 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 r.receiver = null;
10974 r.curApp = null;
10975 app.curReceiver = null;
10976 }
10977 }
10978
10979 }
10980
Jeff Brown4d94a762010-09-23 11:33:28 -070010981 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010982 Intent intent, int resultCode, String data, Bundle extras,
10983 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010984 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 if (app != null && app.thread != null) {
10986 // If we have an app thread, do the call through that so it is
10987 // correctly ordered with other one-way calls.
10988 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010989 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010990 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010991 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992 }
10993 }
10994
Jeff Brown4d94a762010-09-23 11:33:28 -070010995 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 BroadcastFilter filter, boolean ordered) {
10997 boolean skip = false;
10998 if (filter.requiredPermission != null) {
10999 int perm = checkComponentPermission(filter.requiredPermission,
11000 r.callingPid, r.callingUid, -1);
11001 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011002 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011003 + r.intent.toString()
11004 + " from " + r.callerPackage + " (pid="
11005 + r.callingPid + ", uid=" + r.callingUid + ")"
11006 + " requires " + filter.requiredPermission
11007 + " due to registered receiver " + filter);
11008 skip = true;
11009 }
11010 }
11011 if (r.requiredPermission != null) {
11012 int perm = checkComponentPermission(r.requiredPermission,
11013 filter.receiverList.pid, filter.receiverList.uid, -1);
11014 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011015 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016 + r.intent.toString()
11017 + " to " + filter.receiverList.app
11018 + " (pid=" + filter.receiverList.pid
11019 + ", uid=" + filter.receiverList.uid + ")"
11020 + " requires " + r.requiredPermission
11021 + " due to sender " + r.callerPackage
11022 + " (uid " + r.callingUid + ")");
11023 skip = true;
11024 }
11025 }
11026
11027 if (!skip) {
11028 // If this is not being sent as an ordered broadcast, then we
11029 // don't want to touch the fields that keep track of the current
11030 // state of ordered broadcasts.
11031 if (ordered) {
11032 r.receiver = filter.receiverList.receiver.asBinder();
11033 r.curFilter = filter;
11034 filter.receiverList.curBroadcast = r;
11035 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011036 if (filter.receiverList.app != null) {
11037 // Bump hosting application to no longer be in background
11038 // scheduling class. Note that we can't do that if there
11039 // isn't an app... but we can only be in that case for
11040 // things that directly call the IActivityManager API, which
11041 // are already core system stuff so don't matter for this.
11042 r.curApp = filter.receiverList.app;
11043 filter.receiverList.app.curReceiver = r;
11044 updateOomAdjLocked();
11045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011046 }
11047 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011048 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011050 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011051 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011053 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011054 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011055 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056 if (ordered) {
11057 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11058 }
11059 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011060 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011061 if (ordered) {
11062 r.receiver = null;
11063 r.curFilter = null;
11064 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011065 if (filter.receiverList.app != null) {
11066 filter.receiverList.app.curReceiver = null;
11067 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011068 }
11069 }
11070 }
11071 }
11072
Dianne Hackborn12527f92009-11-11 17:39:50 -080011073 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11074 if (r.callingUid < 0) {
11075 // This was from a registerReceiver() call; ignore it.
11076 return;
11077 }
11078 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11079 MAX_BROADCAST_HISTORY-1);
11080 r.finishTime = SystemClock.uptimeMillis();
11081 mBroadcastHistory[0] = r;
11082 }
11083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011084 private final void processNextBroadcast(boolean fromMsg) {
11085 synchronized(this) {
11086 BroadcastRecord r;
11087
Joe Onorato8a9b2202010-02-26 18:56:32 -080011088 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011089 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011090 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091
11092 updateCpuStats();
11093
11094 if (fromMsg) {
11095 mBroadcastsScheduled = false;
11096 }
11097
11098 // First, deliver any non-serialized broadcasts right away.
11099 while (mParallelBroadcasts.size() > 0) {
11100 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011101 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011102 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011103 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011104 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011105 for (int i=0; i<N; i++) {
11106 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011107 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011108 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011110 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011111 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011112 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011113 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011114 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011115 }
11116
11117 // Now take care of the next serialized one...
11118
11119 // If we are waiting for a process to come up to handle the next
11120 // broadcast, then do nothing at this point. Just in case, we
11121 // check that the process we're waiting for still exists.
11122 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011123 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011124 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011125 + mPendingBroadcast.curApp);
11126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011127
11128 boolean isDead;
11129 synchronized (mPidsSelfLocked) {
11130 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11131 }
11132 if (!isDead) {
11133 // It's still alive, so keep waiting
11134 return;
11135 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011136 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011137 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011138 mPendingBroadcast.state = BroadcastRecord.IDLE;
11139 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011140 mPendingBroadcast = null;
11141 }
11142 }
11143
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011144 boolean looped = false;
11145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011146 do {
11147 if (mOrderedBroadcasts.size() == 0) {
11148 // No more broadcasts pending, so all done!
11149 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011150 if (looped) {
11151 // If we had finished the last ordered broadcast, then
11152 // make sure all processes have correct oom and sched
11153 // adjustments.
11154 updateOomAdjLocked();
11155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 return;
11157 }
11158 r = mOrderedBroadcasts.get(0);
11159 boolean forceReceive = false;
11160
11161 // Ensure that even if something goes awry with the timeout
11162 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011163 // and continue to make progress.
11164 //
11165 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011166 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011167 // one time heavy lifting after system upgrades and can take
11168 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011169 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011170 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011171 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011172 if ((numReceivers > 0) &&
11173 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011174 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011175 + " now=" + now
11176 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011177 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011178 + " intent=" + r.intent
11179 + " numReceivers=" + numReceivers
11180 + " nextReceiver=" + r.nextReceiver
11181 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011182 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011183 forceReceive = true;
11184 r.state = BroadcastRecord.IDLE;
11185 }
11186 }
11187
11188 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011189 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011190 "processNextBroadcast() called when not idle (state="
11191 + r.state + ")");
11192 return;
11193 }
11194
11195 if (r.receivers == null || r.nextReceiver >= numReceivers
11196 || r.resultAbort || forceReceive) {
11197 // No more receivers for this broadcast! Send the final
11198 // result if requested...
11199 if (r.resultTo != null) {
11200 try {
11201 if (DEBUG_BROADCAST) {
11202 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011203 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 + " seq=" + seq + " app=" + r.callerApp);
11205 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011206 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011207 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011208 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011209 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011210 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011211 }
11212 }
11213
Joe Onorato8a9b2202010-02-26 18:56:32 -080011214 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011215 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011216
Joe Onorato8a9b2202010-02-26 18:56:32 -080011217 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011218 + r);
11219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011221 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011222 mOrderedBroadcasts.remove(0);
11223 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011224 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011225 continue;
11226 }
11227 } while (r == null);
11228
11229 // Get the next receiver...
11230 int recIdx = r.nextReceiver++;
11231
11232 // Keep track of when this receiver started, and make sure there
11233 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011234 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011236 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237
Joe Onorato8a9b2202010-02-26 18:56:32 -080011238 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011239 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011240 }
11241 if (! mPendingBroadcastTimeoutMessage) {
11242 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011243 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011244 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11245 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011246 }
11247
11248 Object nextReceiver = r.receivers.get(recIdx);
11249 if (nextReceiver instanceof BroadcastFilter) {
11250 // Simple case: this is a registered receiver who gets
11251 // a direct call.
11252 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011253 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011254 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011255 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011256 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011257 if (r.receiver == null || !r.ordered) {
11258 // The receiver has already finished, so schedule to
11259 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011260 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11261 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011262 r.state = BroadcastRecord.IDLE;
11263 scheduleBroadcastsLocked();
11264 }
11265 return;
11266 }
11267
11268 // Hard case: need to instantiate the receiver, possibly
11269 // starting its application process to host it.
11270
11271 ResolveInfo info =
11272 (ResolveInfo)nextReceiver;
11273
11274 boolean skip = false;
11275 int perm = checkComponentPermission(info.activityInfo.permission,
11276 r.callingPid, r.callingUid,
11277 info.activityInfo.exported
11278 ? -1 : info.activityInfo.applicationInfo.uid);
11279 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011280 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011281 + r.intent.toString()
11282 + " from " + r.callerPackage + " (pid=" + r.callingPid
11283 + ", uid=" + r.callingUid + ")"
11284 + " requires " + info.activityInfo.permission
11285 + " due to receiver " + info.activityInfo.packageName
11286 + "/" + info.activityInfo.name);
11287 skip = true;
11288 }
11289 if (r.callingUid != Process.SYSTEM_UID &&
11290 r.requiredPermission != null) {
11291 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011292 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011293 checkPermission(r.requiredPermission,
11294 info.activityInfo.applicationInfo.packageName);
11295 } catch (RemoteException e) {
11296 perm = PackageManager.PERMISSION_DENIED;
11297 }
11298 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011299 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011300 + r.intent + " to "
11301 + info.activityInfo.applicationInfo.packageName
11302 + " requires " + r.requiredPermission
11303 + " due to sender " + r.callerPackage
11304 + " (uid " + r.callingUid + ")");
11305 skip = true;
11306 }
11307 }
11308 if (r.curApp != null && r.curApp.crashing) {
11309 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011310 if (DEBUG_BROADCAST) Slog.v(TAG,
11311 "Skipping deliver ordered " + r + " to " + r.curApp
11312 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011313 skip = true;
11314 }
11315
11316 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011317 if (DEBUG_BROADCAST) Slog.v(TAG,
11318 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011319 r.receiver = null;
11320 r.curFilter = null;
11321 r.state = BroadcastRecord.IDLE;
11322 scheduleBroadcastsLocked();
11323 return;
11324 }
11325
11326 r.state = BroadcastRecord.APP_RECEIVE;
11327 String targetProcess = info.activityInfo.processName;
11328 r.curComponent = new ComponentName(
11329 info.activityInfo.applicationInfo.packageName,
11330 info.activityInfo.name);
11331 r.curReceiver = info.activityInfo;
11332
11333 // Is this receiver's application already running?
11334 ProcessRecord app = getProcessRecordLocked(targetProcess,
11335 info.activityInfo.applicationInfo.uid);
11336 if (app != null && app.thread != null) {
11337 try {
11338 processCurBroadcastLocked(r, app);
11339 return;
11340 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011341 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011342 + r.curComponent, e);
11343 }
11344
11345 // If a dead object exception was thrown -- fall through to
11346 // restart the application.
11347 }
11348
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011349 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011350 if (DEBUG_BROADCAST) Slog.v(TAG,
11351 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011352 if ((r.curApp=startProcessLocked(targetProcess,
11353 info.activityInfo.applicationInfo, true,
11354 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011355 "broadcast", r.curComponent,
11356 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11357 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011358 // Ah, this recipient is unavailable. Finish it if necessary,
11359 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011360 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011361 + info.activityInfo.applicationInfo.packageName + "/"
11362 + info.activityInfo.applicationInfo.uid + " for broadcast "
11363 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011364 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011365 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11366 r.resultExtras, r.resultAbort, true);
11367 scheduleBroadcastsLocked();
11368 r.state = BroadcastRecord.IDLE;
11369 return;
11370 }
11371
11372 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011373 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011374 }
11375 }
11376
11377 // =========================================================
11378 // INSTRUMENTATION
11379 // =========================================================
11380
11381 public boolean startInstrumentation(ComponentName className,
11382 String profileFile, int flags, Bundle arguments,
11383 IInstrumentationWatcher watcher) {
11384 // Refuse possible leaked file descriptors
11385 if (arguments != null && arguments.hasFileDescriptors()) {
11386 throw new IllegalArgumentException("File descriptors passed in Bundle");
11387 }
11388
11389 synchronized(this) {
11390 InstrumentationInfo ii = null;
11391 ApplicationInfo ai = null;
11392 try {
11393 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011394 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011395 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011396 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011397 } catch (PackageManager.NameNotFoundException e) {
11398 }
11399 if (ii == null) {
11400 reportStartInstrumentationFailure(watcher, className,
11401 "Unable to find instrumentation info for: " + className);
11402 return false;
11403 }
11404 if (ai == null) {
11405 reportStartInstrumentationFailure(watcher, className,
11406 "Unable to find instrumentation target package: " + ii.targetPackage);
11407 return false;
11408 }
11409
11410 int match = mContext.getPackageManager().checkSignatures(
11411 ii.targetPackage, ii.packageName);
11412 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11413 String msg = "Permission Denial: starting instrumentation "
11414 + className + " from pid="
11415 + Binder.getCallingPid()
11416 + ", uid=" + Binder.getCallingPid()
11417 + " not allowed because package " + ii.packageName
11418 + " does not have a signature matching the target "
11419 + ii.targetPackage;
11420 reportStartInstrumentationFailure(watcher, className, msg);
11421 throw new SecurityException(msg);
11422 }
11423
11424 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011425 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426 ProcessRecord app = addAppLocked(ai);
11427 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011428 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011429 app.instrumentationProfileFile = profileFile;
11430 app.instrumentationArguments = arguments;
11431 app.instrumentationWatcher = watcher;
11432 app.instrumentationResultClass = className;
11433 Binder.restoreCallingIdentity(origId);
11434 }
11435
11436 return true;
11437 }
11438
11439 /**
11440 * Report errors that occur while attempting to start Instrumentation. Always writes the
11441 * error to the logs, but if somebody is watching, send the report there too. This enables
11442 * the "am" command to report errors with more information.
11443 *
11444 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11445 * @param cn The component name of the instrumentation.
11446 * @param report The error report.
11447 */
11448 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11449 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011450 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011451 try {
11452 if (watcher != null) {
11453 Bundle results = new Bundle();
11454 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11455 results.putString("Error", report);
11456 watcher.instrumentationStatus(cn, -1, results);
11457 }
11458 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011459 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011460 }
11461 }
11462
11463 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11464 if (app.instrumentationWatcher != null) {
11465 try {
11466 // NOTE: IInstrumentationWatcher *must* be oneway here
11467 app.instrumentationWatcher.instrumentationFinished(
11468 app.instrumentationClass,
11469 resultCode,
11470 results);
11471 } catch (RemoteException e) {
11472 }
11473 }
11474 app.instrumentationWatcher = null;
11475 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011476 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011477 app.instrumentationProfileFile = null;
11478 app.instrumentationArguments = null;
11479
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011480 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011481 }
11482
11483 public void finishInstrumentation(IApplicationThread target,
11484 int resultCode, Bundle results) {
11485 // Refuse possible leaked file descriptors
11486 if (results != null && results.hasFileDescriptors()) {
11487 throw new IllegalArgumentException("File descriptors passed in Intent");
11488 }
11489
11490 synchronized(this) {
11491 ProcessRecord app = getRecordForAppLocked(target);
11492 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011493 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011494 return;
11495 }
11496 final long origId = Binder.clearCallingIdentity();
11497 finishInstrumentationLocked(app, resultCode, results);
11498 Binder.restoreCallingIdentity(origId);
11499 }
11500 }
11501
11502 // =========================================================
11503 // CONFIGURATION
11504 // =========================================================
11505
11506 public ConfigurationInfo getDeviceConfigurationInfo() {
11507 ConfigurationInfo config = new ConfigurationInfo();
11508 synchronized (this) {
11509 config.reqTouchScreen = mConfiguration.touchscreen;
11510 config.reqKeyboardType = mConfiguration.keyboard;
11511 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011512 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11513 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011514 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11515 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011516 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11517 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11519 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011520 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011521 }
11522 return config;
11523 }
11524
11525 public Configuration getConfiguration() {
11526 Configuration ci;
11527 synchronized(this) {
11528 ci = new Configuration(mConfiguration);
11529 }
11530 return ci;
11531 }
11532
11533 public void updateConfiguration(Configuration values) {
11534 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11535 "updateConfiguration()");
11536
11537 synchronized(this) {
11538 if (values == null && mWindowManager != null) {
11539 // sentinel: fetch the current configuration from the window manager
11540 values = mWindowManager.computeNewConfiguration();
11541 }
11542
11543 final long origId = Binder.clearCallingIdentity();
11544 updateConfigurationLocked(values, null);
11545 Binder.restoreCallingIdentity(origId);
11546 }
11547 }
11548
11549 /**
11550 * Do either or both things: (1) change the current configuration, and (2)
11551 * make sure the given activity is running with the (now) current
11552 * configuration. Returns true if the activity has been left running, or
11553 * false if <var>starting</var> is being destroyed to match the new
11554 * configuration.
11555 */
11556 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011557 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011558 int changes = 0;
11559
11560 boolean kept = true;
11561
11562 if (values != null) {
11563 Configuration newConfig = new Configuration(mConfiguration);
11564 changes = newConfig.updateFrom(values);
11565 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011566 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011567 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011568 }
11569
Doug Zongker2bec3d42009-12-04 12:52:44 -080011570 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011571
11572 if (values.locale != null) {
11573 saveLocaleLocked(values.locale,
11574 !values.locale.equals(mConfiguration.locale),
11575 values.userSetLocale);
11576 }
11577
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011578 mConfigurationSeq++;
11579 if (mConfigurationSeq <= 0) {
11580 mConfigurationSeq = 1;
11581 }
11582 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011583 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011584 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011585
11586 AttributeCache ac = AttributeCache.instance();
11587 if (ac != null) {
11588 ac.updateConfiguration(mConfiguration);
11589 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011590
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011591 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11592 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11593 msg.obj = new Configuration(mConfiguration);
11594 mHandler.sendMessage(msg);
11595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011596
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011597 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11598 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011599 try {
11600 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011601 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011602 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011603 app.thread.scheduleConfigurationChanged(mConfiguration);
11604 }
11605 } catch (Exception e) {
11606 }
11607 }
11608 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011609 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11610 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011611 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11612 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011613 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11614 broadcastIntentLocked(null, null,
11615 new Intent(Intent.ACTION_LOCALE_CHANGED),
11616 null, null, 0, null, null,
11617 null, false, false, MY_PID, Process.SYSTEM_UID);
11618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011619 }
11620 }
11621
11622 if (changes != 0 && starting == null) {
11623 // If the configuration changed, and the caller is not already
11624 // in the process of starting an activity, then find the top
11625 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011626 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011627 }
11628
11629 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011630 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011631 if (kept) {
11632 // If this didn't result in the starting activity being
11633 // destroyed, then we need to make sure at this point that all
11634 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011635 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011637 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011638 }
11639 }
11640
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011641 if (values != null && mWindowManager != null) {
11642 mWindowManager.setNewConfiguration(mConfiguration);
11643 }
11644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011645 return kept;
11646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011647
11648 /**
11649 * Save the locale. You must be inside a synchronized (this) block.
11650 */
11651 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11652 if(isDiff) {
11653 SystemProperties.set("user.language", l.getLanguage());
11654 SystemProperties.set("user.region", l.getCountry());
11655 }
11656
11657 if(isPersist) {
11658 SystemProperties.set("persist.sys.language", l.getLanguage());
11659 SystemProperties.set("persist.sys.country", l.getCountry());
11660 SystemProperties.set("persist.sys.localevar", l.getVariant());
11661 }
11662 }
11663
11664 // =========================================================
11665 // LIFETIME MANAGEMENT
11666 // =========================================================
11667
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011668 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11669 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011670 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011671 // This adjustment has already been computed. If we are calling
11672 // from the top, we may have already computed our adjustment with
11673 // an earlier hidden adjustment that isn't really for us... if
11674 // so, use the new hidden adjustment.
11675 if (!recursed && app.hidden) {
11676 app.curAdj = hiddenAdj;
11677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011678 return app.curAdj;
11679 }
11680
11681 if (app.thread == null) {
11682 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011683 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011684 return (app.curAdj=EMPTY_APP_ADJ);
11685 }
11686
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011687 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11688 // The max adjustment doesn't allow this app to be anything
11689 // below foreground, so it is not worth doing work for it.
11690 app.adjType = "fixed";
11691 app.adjSeq = mAdjSeq;
11692 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011693 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011694 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11695 return (app.curAdj=app.maxAdj);
11696 }
11697
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011698 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011699 app.adjSource = null;
11700 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011701 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011702 app.empty = false;
11703 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011704
The Android Open Source Project4df24232009-03-05 14:34:35 -080011705 // Determine the importance of the process, starting with most
11706 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011707 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011708 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011709 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011710 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011711 // The last app on the list is the foreground app.
11712 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011713 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011714 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011715 } else if (app.instrumentationClass != null) {
11716 // Don't want to kill running instrumentation.
11717 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011718 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011719 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011720 } else if (app.curReceiver != null ||
11721 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11722 // An app that is currently receiving a broadcast also
11723 // counts as being in the foreground.
11724 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011725 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011726 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011727 } else if (app.executingServices.size() > 0) {
11728 // An app that is currently executing a service callback also
11729 // counts as being in the foreground.
11730 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011731 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011732 app.adjType = "exec-service";
11733 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011734 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011735 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011736 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011737 app.adjType = "foreground-service";
11738 } else if (app.forcingToForeground != null) {
11739 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011740 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011741 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011742 app.adjType = "force-foreground";
11743 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011744 } else if (app == mHeavyWeightProcess) {
11745 // We don't want to kill the current heavy-weight process.
11746 adj = HEAVY_WEIGHT_APP_ADJ;
11747 schedGroup = Process.THREAD_GROUP_DEFAULT;
11748 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011749 } else if (app == mHomeProcess) {
11750 // This process is hosting what we currently consider to be the
11751 // home app, so we don't want to let it go into the background.
11752 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011753 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011754 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011755 } else if ((N=app.activities.size()) != 0) {
11756 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011757 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011758 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011759 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011760 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011761 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011762 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011763 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011764 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011765 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011766 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011767 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011768 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011769 break;
11770 }
11771 }
11772 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011773 // A very not-needed process. If this is lower in the lru list,
11774 // we will push it in to the empty bucket.
11775 app.hidden = true;
11776 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011777 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011778 adj = hiddenAdj;
11779 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011780 }
11781
Joe Onorato8a9b2202010-02-26 18:56:32 -080011782 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011783
The Android Open Source Project4df24232009-03-05 14:34:35 -080011784 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785 // there are applications dependent on our services or providers, but
11786 // this gives us a baseline and makes sure we don't get into an
11787 // infinite recursion.
11788 app.adjSeq = mAdjSeq;
11789 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011790
Christopher Tate6fa95972009-06-05 18:43:55 -070011791 if (mBackupTarget != null && app == mBackupTarget.app) {
11792 // If possible we want to avoid killing apps while they're being backed up
11793 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011794 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011795 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011796 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011797 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011798 }
11799 }
11800
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011801 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11802 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011803 final long now = SystemClock.uptimeMillis();
11804 // This process is more important if the top activity is
11805 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011806 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011807 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011808 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011809 if (s.startRequested) {
11810 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11811 // This service has seen some activity within
11812 // recent memory, so we will keep its process ahead
11813 // of the background processes.
11814 if (adj > SECONDARY_SERVER_ADJ) {
11815 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011816 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011817 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011818 }
11819 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011820 // If we have let the service slide into the background
11821 // state, still have some text describing what it is doing
11822 // even though the service no longer has an impact.
11823 if (adj > SECONDARY_SERVER_ADJ) {
11824 app.adjType = "started-bg-services";
11825 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011826 // Don't kill this process because it is doing work; it
11827 // has said it is doing work.
11828 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011829 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011830 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11831 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011832 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011833 = s.connections.values().iterator();
11834 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011835 ArrayList<ConnectionRecord> clist = kt.next();
11836 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11837 // XXX should compute this based on the max of
11838 // all connected clients.
11839 ConnectionRecord cr = clist.get(i);
11840 if (cr.binding.client == app) {
11841 // Binding to ourself is not interesting.
11842 continue;
11843 }
11844 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11845 ProcessRecord client = cr.binding.client;
11846 int myHiddenAdj = hiddenAdj;
11847 if (myHiddenAdj > client.hiddenAdj) {
11848 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11849 myHiddenAdj = client.hiddenAdj;
11850 } else {
11851 myHiddenAdj = VISIBLE_APP_ADJ;
11852 }
11853 }
11854 int clientAdj = computeOomAdjLocked(
11855 client, myHiddenAdj, TOP_APP, true);
11856 if (adj > clientAdj) {
11857 adj = clientAdj >= VISIBLE_APP_ADJ
11858 ? clientAdj : VISIBLE_APP_ADJ;
11859 if (!client.hidden) {
11860 app.hidden = false;
11861 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011862 if (client.keeping) {
11863 app.keeping = true;
11864 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011865 app.adjType = "service";
11866 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11867 .REASON_SERVICE_IN_USE;
11868 app.adjSource = cr.binding.client;
11869 app.adjTarget = s.name;
11870 }
11871 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11872 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11873 schedGroup = Process.THREAD_GROUP_DEFAULT;
11874 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011875 }
11876 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011877 ActivityRecord a = cr.activity;
11878 //if (a != null) {
11879 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11880 //}
11881 if (a != null && adj > FOREGROUND_APP_ADJ &&
11882 (a.state == ActivityState.RESUMED
11883 || a.state == ActivityState.PAUSING)) {
11884 adj = FOREGROUND_APP_ADJ;
11885 schedGroup = Process.THREAD_GROUP_DEFAULT;
11886 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011887 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011888 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11889 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011890 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011891 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011893 }
11894 }
11895 }
11896 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011897
Dianne Hackborn287952c2010-09-22 22:34:31 -070011898 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011899 // would like to avoid killing it unless it would prevent the current
11900 // application from running. By default we put the process in
11901 // with the rest of the background processes; as we scan through
11902 // its services we may bump it up from there.
11903 if (adj > hiddenAdj) {
11904 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011905 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011906 app.adjType = "bg-services";
11907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011908 }
11909
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011910 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11911 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011912 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011913 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11914 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011915 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011916 if (cpr.clients.size() != 0) {
11917 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11918 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11919 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011920 if (client == app) {
11921 // Being our own client is not interesting.
11922 continue;
11923 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011924 int myHiddenAdj = hiddenAdj;
11925 if (myHiddenAdj > client.hiddenAdj) {
11926 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11927 myHiddenAdj = client.hiddenAdj;
11928 } else {
11929 myHiddenAdj = FOREGROUND_APP_ADJ;
11930 }
11931 }
11932 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011933 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011934 if (adj > clientAdj) {
11935 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011936 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011937 if (!client.hidden) {
11938 app.hidden = false;
11939 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011940 if (client.keeping) {
11941 app.keeping = true;
11942 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011943 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011944 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11945 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011946 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011947 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011948 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011949 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11950 schedGroup = Process.THREAD_GROUP_DEFAULT;
11951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 }
11953 }
11954 // If the provider has external (non-framework) process
11955 // dependencies, ensure that its adjustment is at least
11956 // FOREGROUND_APP_ADJ.
11957 if (cpr.externals != 0) {
11958 if (adj > FOREGROUND_APP_ADJ) {
11959 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011960 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011961 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011962 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011963 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011964 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011965 }
11966 }
11967 }
11968 }
11969
11970 app.curRawAdj = adj;
11971
Joe Onorato8a9b2202010-02-26 18:56:32 -080011972 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011973 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11974 if (adj > app.maxAdj) {
11975 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011976 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011977 schedGroup = Process.THREAD_GROUP_DEFAULT;
11978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011979 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011980 if (adj < HIDDEN_APP_MIN_ADJ) {
11981 app.keeping = true;
11982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011983
11984 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011985 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011987 return adj;
11988 }
11989
11990 /**
11991 * Ask a given process to GC right now.
11992 */
11993 final void performAppGcLocked(ProcessRecord app) {
11994 try {
11995 app.lastRequestedGc = SystemClock.uptimeMillis();
11996 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011997 if (app.reportLowMemory) {
11998 app.reportLowMemory = false;
11999 app.thread.scheduleLowMemory();
12000 } else {
12001 app.thread.processInBackground();
12002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012003 }
12004 } catch (Exception e) {
12005 // whatever.
12006 }
12007 }
12008
12009 /**
12010 * Returns true if things are idle enough to perform GCs.
12011 */
Josh Bartel7f208742010-02-25 11:01:44 -060012012 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012013 return mParallelBroadcasts.size() == 0
12014 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012015 && (mSleeping || (mMainStack.mResumedActivity != null &&
12016 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 }
12018
12019 /**
12020 * Perform GCs on all processes that are waiting for it, but only
12021 * if things are idle.
12022 */
12023 final void performAppGcsLocked() {
12024 final int N = mProcessesToGc.size();
12025 if (N <= 0) {
12026 return;
12027 }
Josh Bartel7f208742010-02-25 11:01:44 -060012028 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012029 while (mProcessesToGc.size() > 0) {
12030 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012031 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012032 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12033 <= SystemClock.uptimeMillis()) {
12034 // To avoid spamming the system, we will GC processes one
12035 // at a time, waiting a few seconds between each.
12036 performAppGcLocked(proc);
12037 scheduleAppGcsLocked();
12038 return;
12039 } else {
12040 // It hasn't been long enough since we last GCed this
12041 // process... put it in the list to wait for its time.
12042 addProcessToGcListLocked(proc);
12043 break;
12044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012045 }
12046 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012047
12048 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012049 }
12050 }
12051
12052 /**
12053 * If all looks good, perform GCs on all processes waiting for them.
12054 */
12055 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012056 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012057 performAppGcsLocked();
12058 return;
12059 }
12060 // Still not idle, wait some more.
12061 scheduleAppGcsLocked();
12062 }
12063
12064 /**
12065 * Schedule the execution of all pending app GCs.
12066 */
12067 final void scheduleAppGcsLocked() {
12068 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012069
12070 if (mProcessesToGc.size() > 0) {
12071 // Schedule a GC for the time to the next process.
12072 ProcessRecord proc = mProcessesToGc.get(0);
12073 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12074
12075 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12076 long now = SystemClock.uptimeMillis();
12077 if (when < (now+GC_TIMEOUT)) {
12078 when = now + GC_TIMEOUT;
12079 }
12080 mHandler.sendMessageAtTime(msg, when);
12081 }
12082 }
12083
12084 /**
12085 * Add a process to the array of processes waiting to be GCed. Keeps the
12086 * list in sorted order by the last GC time. The process can't already be
12087 * on the list.
12088 */
12089 final void addProcessToGcListLocked(ProcessRecord proc) {
12090 boolean added = false;
12091 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12092 if (mProcessesToGc.get(i).lastRequestedGc <
12093 proc.lastRequestedGc) {
12094 added = true;
12095 mProcessesToGc.add(i+1, proc);
12096 break;
12097 }
12098 }
12099 if (!added) {
12100 mProcessesToGc.add(0, proc);
12101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012102 }
12103
12104 /**
12105 * Set up to ask a process to GC itself. This will either do it
12106 * immediately, or put it on the list of processes to gc the next
12107 * time things are idle.
12108 */
12109 final void scheduleAppGcLocked(ProcessRecord app) {
12110 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012111 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012112 return;
12113 }
12114 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012115 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012116 scheduleAppGcsLocked();
12117 }
12118 }
12119
Dianne Hackborn287952c2010-09-22 22:34:31 -070012120 final void checkExcessivePowerUsageLocked(boolean doKills) {
12121 updateCpuStatsNow();
12122
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012123 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012124 boolean doWakeKills = doKills;
12125 boolean doCpuKills = doKills;
12126 if (mLastPowerCheckRealtime == 0) {
12127 doWakeKills = false;
12128 }
12129 if (mLastPowerCheckUptime == 0) {
12130 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012131 }
12132 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012133 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012134 }
12135 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012136 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12137 final long curUptime = SystemClock.uptimeMillis();
12138 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12139 mLastPowerCheckRealtime = curRealtime;
12140 mLastPowerCheckUptime = curUptime;
12141 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12142 doWakeKills = false;
12143 }
12144 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12145 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012146 }
12147 int i = mLruProcesses.size();
12148 while (i > 0) {
12149 i--;
12150 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012151 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012152 long wtime;
12153 synchronized (stats) {
12154 wtime = stats.getProcessWakeTime(app.info.uid,
12155 app.pid, curRealtime);
12156 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012157 long wtimeUsed = wtime - app.lastWakeTime;
12158 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12159 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012160 StringBuilder sb = new StringBuilder(128);
12161 sb.append("Wake for ");
12162 app.toShortString(sb);
12163 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012164 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012165 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012166 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012167 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012168 sb.append((wtimeUsed*100)/realtimeSince);
12169 sb.append("%)");
12170 Slog.i(TAG, sb.toString());
12171 sb.setLength(0);
12172 sb.append("CPU for ");
12173 app.toShortString(sb);
12174 sb.append(": over ");
12175 TimeUtils.formatDuration(uptimeSince, sb);
12176 sb.append(" used ");
12177 TimeUtils.formatDuration(cputimeUsed, sb);
12178 sb.append(" (");
12179 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012180 sb.append("%)");
12181 Slog.i(TAG, sb.toString());
12182 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012183 // If a process has held a wake lock for more
12184 // than 50% of the time during this period,
12185 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012186 if (doWakeKills && realtimeSince > 0
12187 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12188 synchronized (stats) {
12189 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12190 realtimeSince, wtimeUsed);
12191 }
12192 Slog.w(TAG, "Excessive wake lock in " + app.processName
12193 + " (pid " + app.pid + "): held " + wtimeUsed
12194 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012195 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12196 app.processName, app.setAdj, "excessive wake lock");
12197 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012198 } else if (doCpuKills && uptimeSince > 0
12199 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12200 synchronized (stats) {
12201 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12202 uptimeSince, cputimeUsed);
12203 }
12204 Slog.w(TAG, "Excessive CPU in " + app.processName
12205 + " (pid " + app.pid + "): used " + cputimeUsed
12206 + " during " + uptimeSince);
12207 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12208 app.processName, app.setAdj, "excessive cpu");
12209 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012210 } else {
12211 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012212 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012213 }
12214 }
12215 }
12216 }
12217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012218 private final boolean updateOomAdjLocked(
12219 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12220 app.hiddenAdj = hiddenAdj;
12221
12222 if (app.thread == null) {
12223 return true;
12224 }
12225
Dianne Hackborn287952c2010-09-22 22:34:31 -070012226 final boolean wasKeeping = app.keeping;
12227
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012228 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012229
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012230 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012231 if (app.curRawAdj != app.setRawAdj) {
12232 if (app.curRawAdj > FOREGROUND_APP_ADJ
12233 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12234 // If this app is transitioning from foreground to
12235 // non-foreground, have it do a gc.
12236 scheduleAppGcLocked(app);
12237 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12238 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12239 // Likewise do a gc when an app is moving in to the
12240 // background (such as a service stopping).
12241 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012242 }
12243
12244 if (wasKeeping && !app.keeping) {
12245 // This app is no longer something we want to keep. Note
12246 // its current wake lock time to later know to kill it if
12247 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012248 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12249 synchronized (stats) {
12250 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12251 app.pid, SystemClock.elapsedRealtime());
12252 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012253 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012254 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012256 app.setRawAdj = app.curRawAdj;
12257 }
12258 if (adj != app.setAdj) {
12259 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012260 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012261 TAG, "Set app " + app.processName +
12262 " oom adj to " + adj);
12263 app.setAdj = adj;
12264 } else {
12265 return false;
12266 }
12267 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012268 if (app.setSchedGroup != app.curSchedGroup) {
12269 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012270 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012271 "Setting process group of " + app.processName
12272 + " to " + app.curSchedGroup);
12273 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012274 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012275 try {
12276 Process.setProcessGroup(app.pid, app.curSchedGroup);
12277 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012278 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012279 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012280 e.printStackTrace();
12281 } finally {
12282 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012283 }
12284 }
12285 if (false) {
12286 if (app.thread != null) {
12287 try {
12288 app.thread.setSchedulingGroup(app.curSchedGroup);
12289 } catch (RemoteException e) {
12290 }
12291 }
12292 }
12293 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012294 }
12295
12296 return true;
12297 }
12298
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012299 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012300 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012301 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012302 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012303 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012304 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012305 }
12306 }
12307 return resumedActivity;
12308 }
12309
12310 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012311 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012312 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12313 int curAdj = app.curAdj;
12314 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12315 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12316
12317 mAdjSeq++;
12318
12319 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12320 if (res) {
12321 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12322 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12323 if (nowHidden != wasHidden) {
12324 // Changed to/from hidden state, so apps after it in the LRU
12325 // list may also be changed.
12326 updateOomAdjLocked();
12327 }
12328 }
12329 return res;
12330 }
12331
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012332 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012333 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012334 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012335 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12336
12337 if (false) {
12338 RuntimeException e = new RuntimeException();
12339 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012340 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012341 }
12342
12343 mAdjSeq++;
12344
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012345 // Let's determine how many processes we have running vs.
12346 // how many slots we have for background processes; we may want
12347 // to put multiple processes in a slot of there are enough of
12348 // them.
12349 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12350 int factor = (mLruProcesses.size()-4)/numSlots;
12351 if (factor < 1) factor = 1;
12352 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012353 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012355 // First try updating the OOM adjustment for each of the
12356 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012357 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012358 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12359 while (i > 0) {
12360 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012361 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012362 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012363 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012364 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012365 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012366 step++;
12367 if (step >= factor) {
12368 step = 0;
12369 curHiddenAdj++;
12370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012371 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012372 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012373 if (!app.killedBackground) {
12374 numHidden++;
12375 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012376 Slog.i(TAG, "No longer want " + app.processName
12377 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012378 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12379 app.processName, app.setAdj, "too many background");
12380 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012381 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012382 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012383 }
12384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012385 } else {
12386 didOomAdj = false;
12387 }
12388 }
12389
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012390 // If we return false, we will fall back on killing processes to
12391 // have a fixed limit. Do this if a limit has been requested; else
12392 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012393 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12394 }
12395
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012396 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012397 synchronized (this) {
12398 int i;
12399
12400 // First remove any unused application processes whose package
12401 // has been removed.
12402 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12403 final ProcessRecord app = mRemovedProcesses.get(i);
12404 if (app.activities.size() == 0
12405 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012406 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012407 TAG, "Exiting empty application process "
12408 + app.processName + " ("
12409 + (app.thread != null ? app.thread.asBinder() : null)
12410 + ")\n");
12411 if (app.pid > 0 && app.pid != MY_PID) {
12412 Process.killProcess(app.pid);
12413 } else {
12414 try {
12415 app.thread.scheduleExit();
12416 } catch (Exception e) {
12417 // Ignore exceptions.
12418 }
12419 }
12420 cleanUpApplicationRecordLocked(app, false, -1);
12421 mRemovedProcesses.remove(i);
12422
12423 if (app.persistent) {
12424 if (app.persistent) {
12425 addAppLocked(app.info);
12426 }
12427 }
12428 }
12429 }
12430
12431 // Now try updating the OOM adjustment for each of the
12432 // application processes based on their current state.
12433 // If the setOomAdj() API is not supported, then go with our
12434 // back-up plan...
12435 if (!updateOomAdjLocked()) {
12436
12437 // Count how many processes are running services.
12438 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012439 for (i=mLruProcesses.size()-1; i>=0; i--) {
12440 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012441
12442 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012443 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012444 // Don't count processes holding services against our
12445 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012446 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012447 TAG, "Not trimming app " + app + " with services: "
12448 + app.services);
12449 numServiceProcs++;
12450 }
12451 }
12452
12453 int curMaxProcs = mProcessLimit;
12454 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12455 if (mAlwaysFinishActivities) {
12456 curMaxProcs = 1;
12457 }
12458 curMaxProcs += numServiceProcs;
12459
12460 // Quit as many processes as we can to get down to the desired
12461 // process count. First remove any processes that no longer
12462 // have activites running in them.
12463 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012464 i<mLruProcesses.size()
12465 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012466 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012467 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012468 // Quit an application only if it is not currently
12469 // running any activities.
12470 if (!app.persistent && app.activities.size() == 0
12471 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012472 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012473 TAG, "Exiting empty application process "
12474 + app.processName + " ("
12475 + (app.thread != null ? app.thread.asBinder() : null)
12476 + ")\n");
12477 if (app.pid > 0 && app.pid != MY_PID) {
12478 Process.killProcess(app.pid);
12479 } else {
12480 try {
12481 app.thread.scheduleExit();
12482 } catch (Exception e) {
12483 // Ignore exceptions.
12484 }
12485 }
12486 // todo: For now we assume the application is not buggy
12487 // or evil, and will quit as a result of our request.
12488 // Eventually we need to drive this off of the death
12489 // notification, and kill the process if it takes too long.
12490 cleanUpApplicationRecordLocked(app, false, i);
12491 i--;
12492 }
12493 }
12494
12495 // If we still have too many processes, now from the least
12496 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012497 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012498 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012499 " of " + curMaxProcs + " processes");
12500 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012501 i<mLruProcesses.size()
12502 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012503 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012504 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012505 // Quit the application only if we have a state saved for
12506 // all of its activities.
12507 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012508 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012509 int NUMA = app.activities.size();
12510 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012511 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012512 TAG, "Looking to quit " + app.processName);
12513 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012514 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012515 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012516 TAG, " " + r.intent.getComponent().flattenToShortString()
12517 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12518 canQuit = (r.haveState || !r.stateNotNeeded)
12519 && !r.visible && r.stopped;
12520 }
12521 if (canQuit) {
12522 // Finish all of the activities, and then the app itself.
12523 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012524 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012525 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012526 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012527 }
12528 r.resultTo = null;
12529 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012530 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012531 + app.processName + " ("
12532 + (app.thread != null ? app.thread.asBinder() : null)
12533 + ")\n");
12534 if (app.pid > 0 && app.pid != MY_PID) {
12535 Process.killProcess(app.pid);
12536 } else {
12537 try {
12538 app.thread.scheduleExit();
12539 } catch (Exception e) {
12540 // Ignore exceptions.
12541 }
12542 }
12543 // todo: For now we assume the application is not buggy
12544 // or evil, and will quit as a result of our request.
12545 // Eventually we need to drive this off of the death
12546 // notification, and kill the process if it takes too long.
12547 cleanUpApplicationRecordLocked(app, false, i);
12548 i--;
12549 //dump();
12550 }
12551 }
12552
12553 }
12554
12555 int curMaxActivities = MAX_ACTIVITIES;
12556 if (mAlwaysFinishActivities) {
12557 curMaxActivities = 1;
12558 }
12559
12560 // Finally, if there are too many activities now running, try to
12561 // finish as many as we can to get back down to the limit.
12562 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012563 i<mMainStack.mLRUActivities.size()
12564 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012565 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012566 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012567 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012568
12569 // We can finish this one if we have its icicle saved and
12570 // it is not persistent.
12571 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012572 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012573 final int origSize = mMainStack.mLRUActivities.size();
12574 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012575
12576 // This will remove it from the LRU list, so keep
12577 // our index at the same value. Note that this check to
12578 // see if the size changes is just paranoia -- if
12579 // something unexpected happens, we don't want to end up
12580 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012581 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012582 i--;
12583 }
12584 }
12585 }
12586 }
12587 }
12588
12589 /** This method sends the specified signal to each of the persistent apps */
12590 public void signalPersistentProcesses(int sig) throws RemoteException {
12591 if (sig != Process.SIGNAL_USR1) {
12592 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12593 }
12594
12595 synchronized (this) {
12596 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12597 != PackageManager.PERMISSION_GRANTED) {
12598 throw new SecurityException("Requires permission "
12599 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12600 }
12601
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012602 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12603 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012604 if (r.thread != null && r.persistent) {
12605 Process.sendSignal(r.pid, sig);
12606 }
12607 }
12608 }
12609 }
12610
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012611 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012612 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012613
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012614 try {
12615 synchronized (this) {
12616 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12617 // its own permission.
12618 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12619 != PackageManager.PERMISSION_GRANTED) {
12620 throw new SecurityException("Requires permission "
12621 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012622 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012623
12624 if (start && fd == null) {
12625 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012626 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012627
12628 ProcessRecord proc = null;
12629 try {
12630 int pid = Integer.parseInt(process);
12631 synchronized (mPidsSelfLocked) {
12632 proc = mPidsSelfLocked.get(pid);
12633 }
12634 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012635 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012636
12637 if (proc == null) {
12638 HashMap<String, SparseArray<ProcessRecord>> all
12639 = mProcessNames.getMap();
12640 SparseArray<ProcessRecord> procs = all.get(process);
12641 if (procs != null && procs.size() > 0) {
12642 proc = procs.valueAt(0);
12643 }
12644 }
12645
12646 if (proc == null || proc.thread == null) {
12647 throw new IllegalArgumentException("Unknown process: " + process);
12648 }
12649
12650 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12651 if (isSecure) {
12652 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12653 throw new SecurityException("Process not debuggable: " + proc);
12654 }
12655 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012656
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012657 proc.thread.profilerControl(start, path, fd);
12658 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012659 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012660 }
12661 } catch (RemoteException e) {
12662 throw new IllegalStateException("Process disappeared");
12663 } finally {
12664 if (fd != null) {
12665 try {
12666 fd.close();
12667 } catch (IOException e) {
12668 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012669 }
12670 }
12671 }
Andy McFadden824c5102010-07-09 16:26:57 -070012672
12673 public boolean dumpHeap(String process, boolean managed,
12674 String path, ParcelFileDescriptor fd) throws RemoteException {
12675
12676 try {
12677 synchronized (this) {
12678 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12679 // its own permission (same as profileControl).
12680 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12681 != PackageManager.PERMISSION_GRANTED) {
12682 throw new SecurityException("Requires permission "
12683 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12684 }
12685
12686 if (fd == null) {
12687 throw new IllegalArgumentException("null fd");
12688 }
12689
12690 ProcessRecord proc = null;
12691 try {
12692 int pid = Integer.parseInt(process);
12693 synchronized (mPidsSelfLocked) {
12694 proc = mPidsSelfLocked.get(pid);
12695 }
12696 } catch (NumberFormatException e) {
12697 }
12698
12699 if (proc == null) {
12700 HashMap<String, SparseArray<ProcessRecord>> all
12701 = mProcessNames.getMap();
12702 SparseArray<ProcessRecord> procs = all.get(process);
12703 if (procs != null && procs.size() > 0) {
12704 proc = procs.valueAt(0);
12705 }
12706 }
12707
12708 if (proc == null || proc.thread == null) {
12709 throw new IllegalArgumentException("Unknown process: " + process);
12710 }
12711
12712 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12713 if (isSecure) {
12714 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12715 throw new SecurityException("Process not debuggable: " + proc);
12716 }
12717 }
12718
12719 proc.thread.dumpHeap(managed, path, fd);
12720 fd = null;
12721 return true;
12722 }
12723 } catch (RemoteException e) {
12724 throw new IllegalStateException("Process disappeared");
12725 } finally {
12726 if (fd != null) {
12727 try {
12728 fd.close();
12729 } catch (IOException e) {
12730 }
12731 }
12732 }
12733 }
12734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012735 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12736 public void monitor() {
12737 synchronized (this) { }
12738 }
12739}