blob: 8d36e4f61ccd87f2d0ce40e18b0d395b568715a3 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962
963 AlertDialog mUidAlert;
964
965 final Handler mHandler = new Handler() {
966 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800967 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 //}
969
970 public void handleMessage(Message msg) {
971 switch (msg.what) {
972 case SHOW_ERROR_MSG: {
973 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 synchronized (ActivityManagerService.this) {
975 ProcessRecord proc = (ProcessRecord)data.get("app");
976 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800977 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 return;
979 }
980 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700981 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800982 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 d.show();
984 proc.crashDialog = d;
985 } else {
986 // The device is asleep, so just pretend that the user
987 // saw a crash dialog and hit "force quit".
988 res.set(0);
989 }
990 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700991
992 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 } break;
994 case SHOW_NOT_RESPONDING_MSG: {
995 synchronized (ActivityManagerService.this) {
996 HashMap data = (HashMap) msg.obj;
997 ProcessRecord proc = (ProcessRecord)data.get("app");
998 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800999 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 return;
1001 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001002
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001003 Intent intent = new Intent("android.intent.action.ANR");
1004 if (!mProcessesReady) {
1005 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1006 }
1007 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001008 null, null, 0, null, null, null,
1009 false, false, MY_PID, Process.SYSTEM_UID);
1010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001012 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 d.show();
1014 proc.anrDialog = d;
1015 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001016
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001017 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001019 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1020 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1021 synchronized (ActivityManagerService.this) {
1022 ProcessRecord proc = (ProcessRecord) data.get("app");
1023 if (proc == null) {
1024 Slog.e(TAG, "App not found when showing strict mode dialog.");
1025 break;
1026 }
1027 if (proc.crashDialog != null) {
1028 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1029 return;
1030 }
1031 AppErrorResult res = (AppErrorResult) data.get("result");
1032 if (!mSleeping && !mShuttingDown) {
1033 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1034 d.show();
1035 proc.crashDialog = d;
1036 } else {
1037 // The device is asleep, so just pretend that the user
1038 // saw a crash dialog and hit "force quit".
1039 res.set(0);
1040 }
1041 }
1042 ensureBootCompleted();
1043 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 case SHOW_FACTORY_ERROR_MSG: {
1045 Dialog d = new FactoryErrorDialog(
1046 mContext, msg.getData().getCharSequence("msg"));
1047 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001048 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 } break;
1050 case UPDATE_CONFIGURATION_MSG: {
1051 final ContentResolver resolver = mContext.getContentResolver();
1052 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1053 } break;
1054 case GC_BACKGROUND_PROCESSES_MSG: {
1055 synchronized (ActivityManagerService.this) {
1056 performAppGcsIfAppropriateLocked();
1057 }
1058 } break;
1059 case WAIT_FOR_DEBUGGER_MSG: {
1060 synchronized (ActivityManagerService.this) {
1061 ProcessRecord app = (ProcessRecord)msg.obj;
1062 if (msg.arg1 != 0) {
1063 if (!app.waitedForDebugger) {
1064 Dialog d = new AppWaitingForDebuggerDialog(
1065 ActivityManagerService.this,
1066 mContext, app);
1067 app.waitDialog = d;
1068 app.waitedForDebugger = true;
1069 d.show();
1070 }
1071 } else {
1072 if (app.waitDialog != null) {
1073 app.waitDialog.dismiss();
1074 app.waitDialog = null;
1075 }
1076 }
1077 }
1078 } break;
1079 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001080 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 TAG, "Received BROADCAST_INTENT_MSG");
1082 processNextBroadcast(true);
1083 } break;
1084 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001085 synchronized (ActivityManagerService.this) {
1086 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001090 if (mDidDexOpt) {
1091 mDidDexOpt = false;
1092 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1093 nmsg.obj = msg.obj;
1094 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1095 return;
1096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 serviceTimeout((ProcessRecord)msg.obj);
1098 } break;
1099 case UPDATE_TIME_ZONE: {
1100 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001101 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1102 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 if (r.thread != null) {
1104 try {
1105 r.thread.updateTimeZone();
1106 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001107 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 }
1109 }
1110 }
1111 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001112 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 case SHOW_UID_ERROR_MSG: {
1114 // XXX This is a temporary dialog, no need to localize.
1115 AlertDialog d = new BaseErrorDialog(mContext);
1116 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1117 d.setCancelable(false);
1118 d.setTitle("System UIDs Inconsistent");
1119 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 +02001120 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1122 mUidAlert = d;
1123 d.show();
1124 } break;
1125 case IM_FEELING_LUCKY_MSG: {
1126 if (mUidAlert != null) {
1127 mUidAlert.dismiss();
1128 mUidAlert = null;
1129 }
1130 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001132 if (mDidDexOpt) {
1133 mDidDexOpt = false;
1134 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1135 nmsg.obj = msg.obj;
1136 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1137 return;
1138 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139 ProcessRecord app = (ProcessRecord)msg.obj;
1140 synchronized (ActivityManagerService.this) {
1141 processStartTimedOutLocked(app);
1142 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001143 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001144 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1145 synchronized (ActivityManagerService.this) {
1146 doPendingActivityLaunchesLocked(true);
1147 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001148 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001149 case KILL_APPLICATION_MSG: {
1150 synchronized (ActivityManagerService.this) {
1151 int uid = msg.arg1;
1152 boolean restart = (msg.arg2 == 1);
1153 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001154 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001155 }
1156 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001157 case FINALIZE_PENDING_INTENT_MSG: {
1158 ((PendingIntentRecord)msg.obj).completeFinalize();
1159 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001160 case POST_HEAVY_NOTIFICATION_MSG: {
1161 INotificationManager inm = NotificationManager.getService();
1162 if (inm == null) {
1163 return;
1164 }
1165
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001166 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001167 ProcessRecord process = root.app;
1168 if (process == null) {
1169 return;
1170 }
1171
1172 try {
1173 Context context = mContext.createPackageContext(process.info.packageName, 0);
1174 String text = mContext.getString(R.string.heavy_weight_notification,
1175 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1176 Notification notification = new Notification();
1177 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1178 notification.when = 0;
1179 notification.flags = Notification.FLAG_ONGOING_EVENT;
1180 notification.tickerText = text;
1181 notification.defaults = 0; // please be quiet
1182 notification.sound = null;
1183 notification.vibrate = null;
1184 notification.setLatestEventInfo(context, text,
1185 mContext.getText(R.string.heavy_weight_notification_detail),
1186 PendingIntent.getActivity(mContext, 0, root.intent,
1187 PendingIntent.FLAG_CANCEL_CURRENT));
1188
1189 try {
1190 int[] outId = new int[1];
1191 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1192 notification, outId);
1193 } catch (RuntimeException e) {
1194 Slog.w(ActivityManagerService.TAG,
1195 "Error showing notification for heavy-weight app", e);
1196 } catch (RemoteException e) {
1197 }
1198 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001199 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001200 }
1201 } break;
1202 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1203 INotificationManager inm = NotificationManager.getService();
1204 if (inm == null) {
1205 return;
1206 }
1207 try {
1208 inm.cancelNotification("android",
1209 R.string.heavy_weight_notification);
1210 } catch (RuntimeException e) {
1211 Slog.w(ActivityManagerService.TAG,
1212 "Error canceling notification for service", e);
1213 } catch (RemoteException e) {
1214 }
1215 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001216 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1217 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001218 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001219 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001220 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1221 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001222 }
1223 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 }
1225 }
1226 };
1227
1228 public static void setSystemProcess() {
1229 try {
1230 ActivityManagerService m = mSelf;
1231
1232 ServiceManager.addService("activity", m);
1233 ServiceManager.addService("meminfo", new MemBinder(m));
1234 if (MONITOR_CPU_USAGE) {
1235 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 ServiceManager.addService("permission", new PermissionController(m));
1238
1239 ApplicationInfo info =
1240 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001241 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001242 mSystemThread.installSystemApplicationInfo(info);
1243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 synchronized (mSelf) {
1245 ProcessRecord app = mSelf.newProcessRecordLocked(
1246 mSystemThread.getApplicationThread(), info,
1247 info.processName);
1248 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001249 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001250 app.maxAdj = SYSTEM_ADJ;
1251 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1252 synchronized (mSelf.mPidsSelfLocked) {
1253 mSelf.mPidsSelfLocked.put(app.pid, app);
1254 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001255 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 }
1257 } catch (PackageManager.NameNotFoundException e) {
1258 throw new RuntimeException(
1259 "Unable to find android system package", e);
1260 }
1261 }
1262
1263 public void setWindowManager(WindowManagerService wm) {
1264 mWindowManager = wm;
1265 }
1266
1267 public static final Context main(int factoryTest) {
1268 AThread thr = new AThread();
1269 thr.start();
1270
1271 synchronized (thr) {
1272 while (thr.mService == null) {
1273 try {
1274 thr.wait();
1275 } catch (InterruptedException e) {
1276 }
1277 }
1278 }
1279
1280 ActivityManagerService m = thr.mService;
1281 mSelf = m;
1282 ActivityThread at = ActivityThread.systemMain();
1283 mSystemThread = at;
1284 Context context = at.getSystemContext();
1285 m.mContext = context;
1286 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001287 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288
1289 m.mBatteryStatsService.publish(context);
1290 m.mUsageStatsService.publish(context);
1291
1292 synchronized (thr) {
1293 thr.mReady = true;
1294 thr.notifyAll();
1295 }
1296
1297 m.startRunning(null, null, null, null);
1298
1299 return context;
1300 }
1301
1302 public static ActivityManagerService self() {
1303 return mSelf;
1304 }
1305
1306 static class AThread extends Thread {
1307 ActivityManagerService mService;
1308 boolean mReady = false;
1309
1310 public AThread() {
1311 super("ActivityManager");
1312 }
1313
1314 public void run() {
1315 Looper.prepare();
1316
1317 android.os.Process.setThreadPriority(
1318 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001319 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320
1321 ActivityManagerService m = new ActivityManagerService();
1322
1323 synchronized (this) {
1324 mService = m;
1325 notifyAll();
1326 }
1327
1328 synchronized (this) {
1329 while (!mReady) {
1330 try {
1331 wait();
1332 } catch (InterruptedException e) {
1333 }
1334 }
1335 }
1336
1337 Looper.loop();
1338 }
1339 }
1340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341 static class MemBinder extends Binder {
1342 ActivityManagerService mActivityManagerService;
1343 MemBinder(ActivityManagerService activityManagerService) {
1344 mActivityManagerService = activityManagerService;
1345 }
1346
1347 @Override
1348 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1349 ActivityManagerService service = mActivityManagerService;
1350 ArrayList<ProcessRecord> procs;
1351 synchronized (mActivityManagerService) {
1352 if (args != null && args.length > 0
1353 && args[0].charAt(0) != '-') {
1354 procs = new ArrayList<ProcessRecord>();
1355 int pid = -1;
1356 try {
1357 pid = Integer.parseInt(args[0]);
1358 } catch (NumberFormatException e) {
1359
1360 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001361 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1362 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 if (proc.pid == pid) {
1364 procs.add(proc);
1365 } else if (proc.processName.equals(args[0])) {
1366 procs.add(proc);
1367 }
1368 }
1369 if (procs.size() <= 0) {
1370 pw.println("No process found for: " + args[0]);
1371 return;
1372 }
1373 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001374 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 }
1376 }
1377 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1378 }
1379 }
1380
1381 static class CpuBinder extends Binder {
1382 ActivityManagerService mActivityManagerService;
1383 CpuBinder(ActivityManagerService activityManagerService) {
1384 mActivityManagerService = activityManagerService;
1385 }
1386
1387 @Override
1388 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1389 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001390 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1391 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1392 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 }
1394 }
1395 }
1396
1397 private ActivityManagerService() {
1398 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1399 if (v != null && Integer.getInteger(v) != 0) {
1400 mSimpleProcessManagement = true;
1401 }
1402 v = System.getenv("ANDROID_DEBUG_APP");
1403 if (v != null) {
1404 mSimpleProcessManagement = true;
1405 }
1406
Joe Onorato8a9b2202010-02-26 18:56:32 -08001407 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 File dataDir = Environment.getDataDirectory();
1410 File systemDir = new File(dataDir, "system");
1411 systemDir.mkdirs();
1412 mBatteryStatsService = new BatteryStatsService(new File(
1413 systemDir, "batterystats.bin").toString());
1414 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001415 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001416 mOnBattery = DEBUG_POWER ? true
1417 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001418 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001420 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001421 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422
Jack Palevichb90d28c2009-07-22 15:35:24 -07001423 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1424 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1425
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001426 mConfiguration.setToDefaults();
1427 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428 mProcessStats.init();
1429
1430 // Add ourself to the Watchdog monitors.
1431 Watchdog.getInstance().addMonitor(this);
1432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 mProcessStatsThread = new Thread("ProcessStats") {
1434 public void run() {
1435 while (true) {
1436 try {
1437 try {
1438 synchronized(this) {
1439 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001440 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001442 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 // + ", write delay=" + nextWriteDelay);
1444 if (nextWriteDelay < nextCpuDelay) {
1445 nextCpuDelay = nextWriteDelay;
1446 }
1447 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001448 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 this.wait(nextCpuDelay);
1450 }
1451 }
1452 } catch (InterruptedException e) {
1453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 updateCpuStatsNow();
1455 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001456 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 }
1458 }
1459 }
1460 };
1461 mProcessStatsThread.start();
1462 }
1463
1464 @Override
1465 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1466 throws RemoteException {
1467 try {
1468 return super.onTransact(code, data, reply, flags);
1469 } catch (RuntimeException e) {
1470 // The activity manager only throws security exceptions, so let's
1471 // log all others.
1472 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001473 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 }
1475 throw e;
1476 }
1477 }
1478
1479 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001480 final long now = SystemClock.uptimeMillis();
1481 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1482 return;
1483 }
1484 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1485 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 mProcessStatsThread.notify();
1487 }
1488 }
1489 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 void updateCpuStatsNow() {
1492 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001493 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 final long now = SystemClock.uptimeMillis();
1495 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001498 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1499 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 haveNewCpuStats = true;
1501 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001502 //Slog.i(TAG, mProcessStats.printCurrentState());
1503 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 // + mProcessStats.getTotalCpuPercent() + "%");
1505
Joe Onorato8a9b2202010-02-26 18:56:32 -08001506 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 if ("true".equals(SystemProperties.get("events.cpu"))) {
1508 int user = mProcessStats.getLastUserTime();
1509 int system = mProcessStats.getLastSystemTime();
1510 int iowait = mProcessStats.getLastIoWaitTime();
1511 int irq = mProcessStats.getLastIrqTime();
1512 int softIrq = mProcessStats.getLastSoftIrqTime();
1513 int idle = mProcessStats.getLastIdleTime();
1514
1515 int total = user + system + iowait + irq + softIrq + idle;
1516 if (total == 0) total = 1;
1517
Doug Zongker2bec3d42009-12-04 12:52:44 -08001518 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 ((user+system+iowait+irq+softIrq) * 100) / total,
1520 (user * 100) / total,
1521 (system * 100) / total,
1522 (iowait * 100) / total,
1523 (irq * 100) / total,
1524 (softIrq * 100) / total);
1525 }
1526 }
1527
Amith Yamasanie43530a2009-08-21 13:11:37 -07001528 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001529 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001530 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 synchronized(mPidsSelfLocked) {
1532 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001533 if (mOnBattery) {
1534 int perc = bstats.startAddingCpuLocked();
1535 int totalUTime = 0;
1536 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001537 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001539 ProcessStats.Stats st = mProcessStats.getStats(i);
1540 if (!st.working) {
1541 continue;
1542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001544 int otherUTime = (st.rel_utime*perc)/100;
1545 int otherSTime = (st.rel_stime*perc)/100;
1546 totalUTime += otherUTime;
1547 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 if (pr != null) {
1549 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001550 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1551 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001552 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001553 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001554 } else {
1555 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001556 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001557 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001558 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1559 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001560 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 }
1563 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001564 bstats.finishAddingCpuLocked(perc, totalUTime,
1565 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 }
1567 }
1568 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1571 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001572 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 }
1574 }
1575 }
1576 }
1577
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001578 @Override
1579 public void batteryNeedsCpuUpdate() {
1580 updateCpuStatsNow();
1581 }
1582
1583 @Override
1584 public void batteryPowerChanged(boolean onBattery) {
1585 // When plugging in, update the CPU stats first before changing
1586 // the plug state.
1587 updateCpuStatsNow();
1588 synchronized (this) {
1589 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001590 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001591 }
1592 }
1593 }
1594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 /**
1596 * Initialize the application bind args. These are passed to each
1597 * process when the bindApplication() IPC is sent to the process. They're
1598 * lazily setup to make sure the services are running when they're asked for.
1599 */
1600 private HashMap<String, IBinder> getCommonServicesLocked() {
1601 if (mAppBindArgs == null) {
1602 mAppBindArgs = new HashMap<String, IBinder>();
1603
1604 // Setup the application init args
1605 mAppBindArgs.put("package", ServiceManager.getService("package"));
1606 mAppBindArgs.put("window", ServiceManager.getService("window"));
1607 mAppBindArgs.put(Context.ALARM_SERVICE,
1608 ServiceManager.getService(Context.ALARM_SERVICE));
1609 }
1610 return mAppBindArgs;
1611 }
1612
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001613 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 if (mFocusedActivity != r) {
1615 mFocusedActivity = r;
1616 mWindowManager.setFocusedApp(r, true);
1617 }
1618 }
1619
Dianne Hackborn906497c2010-05-10 15:57:38 -07001620 private final void updateLruProcessInternalLocked(ProcessRecord app,
1621 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001623 int lrui = mLruProcesses.indexOf(app);
1624 if (lrui >= 0) mLruProcesses.remove(lrui);
1625
1626 int i = mLruProcesses.size()-1;
1627 int skipTop = 0;
1628
Dianne Hackborn906497c2010-05-10 15:57:38 -07001629 app.lruSeq = mLruSeq;
1630
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001631 // compute the new weight for this process.
1632 if (updateActivityTime) {
1633 app.lastActivityTime = SystemClock.uptimeMillis();
1634 }
1635 if (app.activities.size() > 0) {
1636 // If this process has activities, we more strongly want to keep
1637 // it around.
1638 app.lruWeight = app.lastActivityTime;
1639 } else if (app.pubProviders.size() > 0) {
1640 // If this process contains content providers, we want to keep
1641 // it a little more strongly.
1642 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1643 // Also don't let it kick out the first few "real" hidden processes.
1644 skipTop = MIN_HIDDEN_APPS;
1645 } else {
1646 // If this process doesn't have activities, we less strongly
1647 // want to keep it around, and generally want to avoid getting
1648 // in front of any very recently used activities.
1649 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1650 // Also don't let it kick out the first few "real" hidden processes.
1651 skipTop = MIN_HIDDEN_APPS;
1652 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001653
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001654 while (i >= 0) {
1655 ProcessRecord p = mLruProcesses.get(i);
1656 // If this app shouldn't be in front of the first N background
1657 // apps, then skip over that many that are currently hidden.
1658 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1659 skipTop--;
1660 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001661 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001662 mLruProcesses.add(i+1, app);
1663 break;
1664 }
1665 i--;
1666 }
1667 if (i < 0) {
1668 mLruProcesses.add(0, app);
1669 }
1670
Dianne Hackborn906497c2010-05-10 15:57:38 -07001671 // If the app is currently using a content provider or service,
1672 // bump those processes as well.
1673 if (app.connections.size() > 0) {
1674 for (ConnectionRecord cr : app.connections) {
1675 if (cr.binding != null && cr.binding.service != null
1676 && cr.binding.service.app != null
1677 && cr.binding.service.app.lruSeq != mLruSeq) {
1678 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1679 updateActivityTime, i+1);
1680 }
1681 }
1682 }
1683 if (app.conProviders.size() > 0) {
1684 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1685 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1686 updateLruProcessInternalLocked(cpr.app, oomAdj,
1687 updateActivityTime, i+1);
1688 }
1689 }
1690 }
1691
Joe Onorato8a9b2202010-02-26 18:56:32 -08001692 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 if (oomAdj) {
1694 updateOomAdjLocked();
1695 }
1696 }
1697
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001698 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001699 boolean oomAdj, boolean updateActivityTime) {
1700 mLruSeq++;
1701 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1702 }
1703
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001704 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 String processName, int uid) {
1706 if (uid == Process.SYSTEM_UID) {
1707 // The system gets to run in any process. If there are multiple
1708 // processes with the same uid, just pick the first (this
1709 // should never happen).
1710 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1711 processName);
1712 return procs != null ? procs.valueAt(0) : null;
1713 }
1714 ProcessRecord proc = mProcessNames.get(processName, uid);
1715 return proc;
1716 }
1717
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001718 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001719 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001720 try {
1721 if (pm.performDexOpt(packageName)) {
1722 mDidDexOpt = true;
1723 }
1724 } catch (RemoteException e) {
1725 }
1726 }
1727
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001728 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 int transit = mWindowManager.getPendingAppTransition();
1730 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1731 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1732 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1733 }
1734
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001735 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001737 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1739 // We don't have to do anything more if:
1740 // (1) There is an existing application record; and
1741 // (2) The caller doesn't think it is dead, OR there is no thread
1742 // object attached to it so we know it couldn't have crashed; and
1743 // (3) There is a pid assigned to it, so it is either starting or
1744 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001745 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 + " app=" + app + " knownToBeDead=" + knownToBeDead
1747 + " thread=" + (app != null ? app.thread : null)
1748 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001749 if (app != null && app.pid > 0) {
1750 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001751 // We already have the app running, or are waiting for it to
1752 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001753 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001754 return app;
1755 } else {
1756 // An application record is attached to a previous process,
1757 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001758 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001759 handleAppDiedLocked(app, true);
1760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 String hostingNameStr = hostingName != null
1764 ? hostingName.flattenToShortString() : null;
1765
1766 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1767 // If we are in the background, then check to see if this process
1768 // is bad. If so, we will just silently fail.
1769 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001770 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1771 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 return null;
1773 }
1774 } else {
1775 // When the user is explicitly starting a process, then clear its
1776 // crash count so that we won't make it bad until they see at
1777 // least one crash dialog again, and make the process good again
1778 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001779 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1780 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 mProcessCrashTimes.remove(info.processName, info.uid);
1782 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001783 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 info.processName);
1785 mBadProcesses.remove(info.processName, info.uid);
1786 if (app != null) {
1787 app.bad = false;
1788 }
1789 }
1790 }
1791
1792 if (app == null) {
1793 app = newProcessRecordLocked(null, info, processName);
1794 mProcessNames.put(processName, info.uid, app);
1795 } else {
1796 // If this is a new package in the process, add the package to the list
1797 app.addPackage(info.packageName);
1798 }
1799
1800 // If the system is not ready yet, then hold off on starting this
1801 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001802 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001803 && !isAllowedWhileBooting(info)
1804 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 if (!mProcessesOnHold.contains(app)) {
1806 mProcessesOnHold.add(app);
1807 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001808 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 return app;
1810 }
1811
1812 startProcessLocked(app, hostingType, hostingNameStr);
1813 return (app.pid != 0) ? app : null;
1814 }
1815
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001816 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1817 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1818 }
1819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 private final void startProcessLocked(ProcessRecord app,
1821 String hostingType, String hostingNameStr) {
1822 if (app.pid > 0 && app.pid != MY_PID) {
1823 synchronized (mPidsSelfLocked) {
1824 mPidsSelfLocked.remove(app.pid);
1825 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1826 }
1827 app.pid = 0;
1828 }
1829
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001830 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1831 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 mProcessesOnHold.remove(app);
1833
1834 updateCpuStats();
1835
1836 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1837 mProcDeaths[0] = 0;
1838
1839 try {
1840 int uid = app.info.uid;
1841 int[] gids = null;
1842 try {
1843 gids = mContext.getPackageManager().getPackageGids(
1844 app.info.packageName);
1845 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001846 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 }
1848 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1849 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1850 && mTopComponent != null
1851 && app.processName.equals(mTopComponent.getPackageName())) {
1852 uid = 0;
1853 }
1854 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1855 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1856 uid = 0;
1857 }
1858 }
1859 int debugFlags = 0;
1860 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1861 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1862 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001863 // Run the app in safe mode if its manifest requests so or the
1864 // system is booted in safe mode.
1865 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1866 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001867 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1870 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1871 }
1872 if ("1".equals(SystemProperties.get("debug.assert"))) {
1873 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1874 }
1875 int pid = Process.start("android.app.ActivityThread",
1876 mSimpleProcessManagement ? app.processName : null, uid, uid,
1877 gids, debugFlags, null);
1878 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1879 synchronized (bs) {
1880 if (bs.isOnBattery()) {
1881 app.batteryStats.incStartsLocked();
1882 }
1883 }
1884
Doug Zongker2bec3d42009-12-04 12:52:44 -08001885 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 app.processName, hostingType,
1887 hostingNameStr != null ? hostingNameStr : "");
1888
1889 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001890 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 }
1892
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001893 StringBuilder buf = mStringBuilder;
1894 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 buf.append("Start proc ");
1896 buf.append(app.processName);
1897 buf.append(" for ");
1898 buf.append(hostingType);
1899 if (hostingNameStr != null) {
1900 buf.append(" ");
1901 buf.append(hostingNameStr);
1902 }
1903 buf.append(": pid=");
1904 buf.append(pid);
1905 buf.append(" uid=");
1906 buf.append(uid);
1907 buf.append(" gids={");
1908 if (gids != null) {
1909 for (int gi=0; gi<gids.length; gi++) {
1910 if (gi != 0) buf.append(", ");
1911 buf.append(gids[gi]);
1912
1913 }
1914 }
1915 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001916 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 if (pid == 0 || pid == MY_PID) {
1918 // Processes are being emulated with threads.
1919 app.pid = MY_PID;
1920 app.removed = false;
1921 mStartingProcesses.add(app);
1922 } else if (pid > 0) {
1923 app.pid = pid;
1924 app.removed = false;
1925 synchronized (mPidsSelfLocked) {
1926 this.mPidsSelfLocked.put(pid, app);
1927 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1928 msg.obj = app;
1929 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1930 }
1931 } else {
1932 app.pid = 0;
1933 RuntimeException e = new RuntimeException(
1934 "Failure starting process " + app.processName
1935 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001936 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 }
1938 } catch (RuntimeException e) {
1939 // XXX do better error recovery.
1940 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001941 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 }
1943 }
1944
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001945 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 if (resumed) {
1947 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1948 } else {
1949 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1950 }
1951 }
1952
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001953 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001954 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1955 && mTopAction == null) {
1956 // We are running in factory test mode, but unable to find
1957 // the factory test app, so just sit around displaying the
1958 // error message and don't try to start anything.
1959 return false;
1960 }
1961 Intent intent = new Intent(
1962 mTopAction,
1963 mTopData != null ? Uri.parse(mTopData) : null);
1964 intent.setComponent(mTopComponent);
1965 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1966 intent.addCategory(Intent.CATEGORY_HOME);
1967 }
1968 ActivityInfo aInfo =
1969 intent.resolveActivityInfo(mContext.getPackageManager(),
1970 STOCK_PM_FLAGS);
1971 if (aInfo != null) {
1972 intent.setComponent(new ComponentName(
1973 aInfo.applicationInfo.packageName, aInfo.name));
1974 // Don't do this if the home app is currently being
1975 // instrumented.
1976 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1977 aInfo.applicationInfo.uid);
1978 if (app == null || app.instrumentationClass == null) {
1979 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001980 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001981 null, null, 0, 0, 0, false, false);
1982 }
1983 }
1984
1985
1986 return true;
1987 }
1988
1989 /**
1990 * Starts the "new version setup screen" if appropriate.
1991 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001992 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001993 // Only do this once per boot.
1994 if (mCheckedForSetup) {
1995 return;
1996 }
1997
1998 // We will show this screen if the current one is a different
1999 // version than the last one shown, and we are not running in
2000 // low-level factory test mode.
2001 final ContentResolver resolver = mContext.getContentResolver();
2002 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2003 Settings.Secure.getInt(resolver,
2004 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2005 mCheckedForSetup = true;
2006
2007 // See if we should be showing the platform update setup UI.
2008 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2009 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2010 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2011
2012 // We don't allow third party apps to replace this.
2013 ResolveInfo ri = null;
2014 for (int i=0; ris != null && i<ris.size(); i++) {
2015 if ((ris.get(i).activityInfo.applicationInfo.flags
2016 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2017 ri = ris.get(i);
2018 break;
2019 }
2020 }
2021
2022 if (ri != null) {
2023 String vers = ri.activityInfo.metaData != null
2024 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2025 : null;
2026 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2027 vers = ri.activityInfo.applicationInfo.metaData.getString(
2028 Intent.METADATA_SETUP_VERSION);
2029 }
2030 String lastVers = Settings.Secure.getString(
2031 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2032 if (vers != null && !vers.equals(lastVers)) {
2033 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2034 intent.setComponent(new ComponentName(
2035 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002036 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002037 null, null, 0, 0, 0, false, false);
2038 }
2039 }
2040 }
2041 }
2042
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002043 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002044 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002045
2046 final int identHash = System.identityHashCode(r);
2047 updateUsageStats(r, true);
2048
2049 int i = mWatchers.beginBroadcast();
2050 while (i > 0) {
2051 i--;
2052 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2053 if (w != null) {
2054 try {
2055 w.activityResuming(identHash);
2056 } catch (RemoteException e) {
2057 }
2058 }
2059 }
2060 mWatchers.finishBroadcast();
2061 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002063 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002064 final int N = mPendingActivityLaunches.size();
2065 if (N <= 0) {
2066 return;
2067 }
2068 for (int i=0; i<N; i++) {
2069 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002070 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002071 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2072 doResume && i == (N-1));
2073 }
2074 mPendingActivityLaunches.clear();
2075 }
2076
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002077 public final int startActivity(IApplicationThread caller,
2078 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2079 int grantedMode, IBinder resultTo,
2080 String resultWho, int requestCode, boolean onlyIfNeeded,
2081 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002082 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002083 grantedUriPermissions, grantedMode, resultTo, resultWho,
2084 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002085 }
2086
2087 public final WaitResult startActivityAndWait(IApplicationThread caller,
2088 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2089 int grantedMode, IBinder resultTo,
2090 String resultWho, int requestCode, boolean onlyIfNeeded,
2091 boolean debug) {
2092 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002093 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002094 grantedUriPermissions, grantedMode, resultTo, resultWho,
2095 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002096 return res;
2097 }
2098
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002099 public final int startActivityWithConfig(IApplicationThread caller,
2100 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2101 int grantedMode, IBinder resultTo,
2102 String resultWho, int requestCode, boolean onlyIfNeeded,
2103 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002104 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002105 grantedUriPermissions, grantedMode, resultTo, resultWho,
2106 requestCode, onlyIfNeeded, debug, null, config);
2107 }
2108
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002109 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002110 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002111 IBinder resultTo, String resultWho, int requestCode,
2112 int flagsMask, int flagsValues) {
2113 // Refuse possible leaked file descriptors
2114 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2115 throw new IllegalArgumentException("File descriptors passed in Intent");
2116 }
2117
2118 IIntentSender sender = intent.getTarget();
2119 if (!(sender instanceof PendingIntentRecord)) {
2120 throw new IllegalArgumentException("Bad PendingIntent object");
2121 }
2122
2123 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002124
2125 synchronized (this) {
2126 // If this is coming from the currently resumed activity, it is
2127 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002128 if (mMainStack.mResumedActivity != null
2129 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002130 Binder.getCallingUid()) {
2131 mAppSwitchesAllowedTime = 0;
2132 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002133 }
2134
2135 return pir.sendInner(0, fillInIntent, resolvedType,
2136 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2137 }
2138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139 public boolean startNextMatchingActivity(IBinder callingActivity,
2140 Intent intent) {
2141 // Refuse possible leaked file descriptors
2142 if (intent != null && intent.hasFileDescriptors() == true) {
2143 throw new IllegalArgumentException("File descriptors passed in Intent");
2144 }
2145
2146 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002147 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 if (index < 0) {
2149 return false;
2150 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002151 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152 if (r.app == null || r.app.thread == null) {
2153 // The caller is not running... d'oh!
2154 return false;
2155 }
2156 intent = new Intent(intent);
2157 // The caller is not allowed to change the data.
2158 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2159 // And we are resetting to find the next component...
2160 intent.setComponent(null);
2161
2162 ActivityInfo aInfo = null;
2163 try {
2164 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002165 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002167 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168
2169 // Look for the original activity in the list...
2170 final int N = resolves != null ? resolves.size() : 0;
2171 for (int i=0; i<N; i++) {
2172 ResolveInfo rInfo = resolves.get(i);
2173 if (rInfo.activityInfo.packageName.equals(r.packageName)
2174 && rInfo.activityInfo.name.equals(r.info.name)) {
2175 // We found the current one... the next matching is
2176 // after it.
2177 i++;
2178 if (i<N) {
2179 aInfo = resolves.get(i).activityInfo;
2180 }
2181 break;
2182 }
2183 }
2184 } catch (RemoteException e) {
2185 }
2186
2187 if (aInfo == null) {
2188 // Nobody who is next!
2189 return false;
2190 }
2191
2192 intent.setComponent(new ComponentName(
2193 aInfo.applicationInfo.packageName, aInfo.name));
2194 intent.setFlags(intent.getFlags()&~(
2195 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2196 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2197 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2198 Intent.FLAG_ACTIVITY_NEW_TASK));
2199
2200 // Okay now we need to start the new activity, replacing the
2201 // currently running activity. This is a little tricky because
2202 // we want to start the new one as if the current one is finished,
2203 // but not finish the current one first so that there is no flicker.
2204 // And thus...
2205 final boolean wasFinishing = r.finishing;
2206 r.finishing = true;
2207
2208 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002209 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 final String resultWho = r.resultWho;
2211 final int requestCode = r.requestCode;
2212 r.resultTo = null;
2213 if (resultTo != null) {
2214 resultTo.removeResultsLocked(r, resultWho, requestCode);
2215 }
2216
2217 final long origId = Binder.clearCallingIdentity();
2218 // XXX we are not dealing with propagating grantedUriPermissions...
2219 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002220 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002221 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002222 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002223 Binder.restoreCallingIdentity(origId);
2224
2225 r.finishing = wasFinishing;
2226 if (res != START_SUCCESS) {
2227 return false;
2228 }
2229 return true;
2230 }
2231 }
2232
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002233 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234 Intent intent, String resolvedType, IBinder resultTo,
2235 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002236
2237 // This is so super not safe, that only the system (or okay root)
2238 // can do it.
2239 final int callingUid = Binder.getCallingUid();
2240 if (callingUid != 0 && callingUid != Process.myUid()) {
2241 throw new SecurityException(
2242 "startActivityInPackage only available to the system");
2243 }
2244
The Android Open Source Project4df24232009-03-05 14:34:35 -08002245 final boolean componentSpecified = intent.getComponent() != null;
2246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 // Don't modify the client's object!
2248 intent = new Intent(intent);
2249
2250 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002251 ActivityInfo aInfo;
2252 try {
2253 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002254 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002255 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002256 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 aInfo = rInfo != null ? rInfo.activityInfo : null;
2258 } catch (RemoteException e) {
2259 aInfo = null;
2260 }
2261
2262 if (aInfo != null) {
2263 // Store the found target back into the intent, because now that
2264 // we have it we never want to do this again. For example, if the
2265 // user navigates back to this point in the history, we should
2266 // always restart the exact same activity.
2267 intent.setComponent(new ComponentName(
2268 aInfo.applicationInfo.packageName, aInfo.name));
2269 }
2270
2271 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002272 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002274 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 }
2276 }
2277
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002278 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 // Remove any existing entries that are the same kind of task.
2280 int N = mRecentTasks.size();
2281 for (int i=0; i<N; i++) {
2282 TaskRecord tr = mRecentTasks.get(i);
2283 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2284 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2285 mRecentTasks.remove(i);
2286 i--;
2287 N--;
2288 if (task.intent == null) {
2289 // If the new recent task we are adding is not fully
2290 // specified, then replace it with the existing recent task.
2291 task = tr;
2292 }
2293 }
2294 }
2295 if (N >= MAX_RECENT_TASKS) {
2296 mRecentTasks.remove(N-1);
2297 }
2298 mRecentTasks.add(0, task);
2299 }
2300
2301 public void setRequestedOrientation(IBinder token,
2302 int requestedOrientation) {
2303 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002304 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 if (index < 0) {
2306 return;
2307 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002308 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 final long origId = Binder.clearCallingIdentity();
2310 mWindowManager.setAppOrientation(r, requestedOrientation);
2311 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002312 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 r.mayFreezeScreenLocked(r.app) ? r : null);
2314 if (config != null) {
2315 r.frozenBeforeDestroy = true;
2316 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002317 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 }
2319 }
2320 Binder.restoreCallingIdentity(origId);
2321 }
2322 }
2323
2324 public int getRequestedOrientation(IBinder token) {
2325 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002326 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002327 if (index < 0) {
2328 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2329 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002330 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 return mWindowManager.getAppOrientation(r);
2332 }
2333 }
2334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 /**
2336 * This is the internal entry point for handling Activity.finish().
2337 *
2338 * @param token The Binder token referencing the Activity we want to finish.
2339 * @param resultCode Result code, if any, from this Activity.
2340 * @param resultData Result data (Intent), if any, from this Activity.
2341 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002342 * @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 -08002343 */
2344 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2345 // Refuse possible leaked file descriptors
2346 if (resultData != null && resultData.hasFileDescriptors() == true) {
2347 throw new IllegalArgumentException("File descriptors passed in Intent");
2348 }
2349
2350 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002351 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002353 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 if (next != null) {
2355 // ask watcher if this is allowed
2356 boolean resumeOK = true;
2357 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002358 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002359 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002360 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 }
2362
2363 if (!resumeOK) {
2364 return false;
2365 }
2366 }
2367 }
2368 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002369 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 resultData, "app-request");
2371 Binder.restoreCallingIdentity(origId);
2372 return res;
2373 }
2374 }
2375
Dianne Hackborn860755f2010-06-03 18:47:52 -07002376 public final void finishHeavyWeightApp() {
2377 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2378 != PackageManager.PERMISSION_GRANTED) {
2379 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2380 + Binder.getCallingPid()
2381 + ", uid=" + Binder.getCallingUid()
2382 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2383 Slog.w(TAG, msg);
2384 throw new SecurityException(msg);
2385 }
2386
2387 synchronized(this) {
2388 if (mHeavyWeightProcess == null) {
2389 return;
2390 }
2391
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002392 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002393 mHeavyWeightProcess.activities);
2394 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002395 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002396 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002397 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002398 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002399 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002400 null, "finish-heavy");
2401 }
2402 }
2403 }
2404
2405 mHeavyWeightProcess = null;
2406 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2407 }
2408 }
2409
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002410 public void crashApplication(int uid, int initialPid, String packageName,
2411 String message) {
2412 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2413 != PackageManager.PERMISSION_GRANTED) {
2414 String msg = "Permission Denial: crashApplication() from pid="
2415 + Binder.getCallingPid()
2416 + ", uid=" + Binder.getCallingUid()
2417 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2418 Slog.w(TAG, msg);
2419 throw new SecurityException(msg);
2420 }
2421
2422 synchronized(this) {
2423 ProcessRecord proc = null;
2424
2425 // Figure out which process to kill. We don't trust that initialPid
2426 // still has any relation to current pids, so must scan through the
2427 // list.
2428 synchronized (mPidsSelfLocked) {
2429 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2430 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2431 if (p.info.uid != uid) {
2432 continue;
2433 }
2434 if (p.pid == initialPid) {
2435 proc = p;
2436 break;
2437 }
2438 for (String str : p.pkgList) {
2439 if (str.equals(packageName)) {
2440 proc = p;
2441 }
2442 }
2443 }
2444 }
2445
2446 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002447 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002448 + " initialPid=" + initialPid
2449 + " packageName=" + packageName);
2450 return;
2451 }
2452
2453 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002454 if (proc.pid == Process.myPid()) {
2455 Log.w(TAG, "crashApplication: trying to crash self!");
2456 return;
2457 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002458 long ident = Binder.clearCallingIdentity();
2459 try {
2460 proc.thread.scheduleCrash(message);
2461 } catch (RemoteException e) {
2462 }
2463 Binder.restoreCallingIdentity(ident);
2464 }
2465 }
2466 }
2467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468 public final void finishSubActivity(IBinder token, String resultWho,
2469 int requestCode) {
2470 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002471 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002472 if (index < 0) {
2473 return;
2474 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002475 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002476
2477 final long origId = Binder.clearCallingIdentity();
2478
2479 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002480 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2481 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 if (r.resultTo == self && r.requestCode == requestCode) {
2483 if ((r.resultWho == null && resultWho == null) ||
2484 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002485 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002486 Activity.RESULT_CANCELED, null, "request-sub");
2487 }
2488 }
2489 }
2490
2491 Binder.restoreCallingIdentity(origId);
2492 }
2493 }
2494
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002495 public boolean willActivityBeVisible(IBinder token) {
2496 synchronized(this) {
2497 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002498 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2499 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002500 if (r == token) {
2501 return true;
2502 }
2503 if (r.fullscreen && !r.finishing) {
2504 return false;
2505 }
2506 }
2507 return true;
2508 }
2509 }
2510
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002511 public void overridePendingTransition(IBinder token, String packageName,
2512 int enterAnim, int exitAnim) {
2513 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002514 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002515 if (index < 0) {
2516 return;
2517 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002518 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002519
2520 final long origId = Binder.clearCallingIdentity();
2521
2522 if (self.state == ActivityState.RESUMED
2523 || self.state == ActivityState.PAUSING) {
2524 mWindowManager.overridePendingAppTransition(packageName,
2525 enterAnim, exitAnim);
2526 }
2527
2528 Binder.restoreCallingIdentity(origId);
2529 }
2530 }
2531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 * Main function for removing an existing process from the activity manager
2534 * as a result of that process going away. Clears out all connections
2535 * to the process.
2536 */
2537 private final void handleAppDiedLocked(ProcessRecord app,
2538 boolean restarting) {
2539 cleanUpApplicationRecordLocked(app, restarting, -1);
2540 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002541 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 }
2543
2544 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002545 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2546 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2547 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002548 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002549 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2550 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551 }
2552
2553 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002554 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555
2556 boolean atTop = true;
2557 boolean hasVisibleActivities = false;
2558
2559 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002560 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002561 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 TAG, "Removing app " + app + " from history with " + i + " entries");
2563 while (i > 0) {
2564 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002565 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002566 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2568 if (r.app == app) {
2569 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002570 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 TAG, "Removing this entry! frozen=" + r.haveState
2572 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002573 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574
2575 r.inHistory = false;
2576 mWindowManager.removeAppToken(r);
2577 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002578 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002579 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002580 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581
2582 } else {
2583 // We have the current state for this activity, so
2584 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002585 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 TAG, "Keeping entry, setting app to null");
2587 if (r.visible) {
2588 hasVisibleActivities = true;
2589 }
2590 r.app = null;
2591 r.nowVisible = false;
2592 if (!r.haveState) {
2593 r.icicle = null;
2594 }
2595 }
2596
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002597 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002598 r.state = ActivityState.STOPPED;
2599 }
2600 atTop = false;
2601 }
2602
2603 app.activities.clear();
2604
2605 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002606 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 + " running instrumentation " + app.instrumentationClass);
2608 Bundle info = new Bundle();
2609 info.putString("shortMsg", "Process crashed.");
2610 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2611 }
2612
2613 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002614 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 // If there was nothing to resume, and we are not already
2616 // restarting this process, but there is a visible activity that
2617 // is hosted by the process... then make sure all visible
2618 // activities are running, taking care of restarting this
2619 // process.
2620 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002621 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 }
2623 }
2624 }
2625 }
2626
2627 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2628 IBinder threadBinder = thread.asBinder();
2629
2630 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002631 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2632 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002633 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2634 return i;
2635 }
2636 }
2637 return -1;
2638 }
2639
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002640 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 IApplicationThread thread) {
2642 if (thread == null) {
2643 return null;
2644 }
2645
2646 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002647 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002648 }
2649
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002650 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 IApplicationThread thread) {
2652
2653 mProcDeaths[0]++;
2654
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002655 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2656 synchronized (stats) {
2657 stats.noteProcessDiedLocked(app.info.uid, pid);
2658 }
2659
Magnus Edlund7bb25812010-02-24 15:45:06 +01002660 // Clean up already done if the process has been re-started.
2661 if (app.pid == pid && app.thread != null &&
2662 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002663 if (!app.killedBackground) {
2664 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2665 + ") has died.");
2666 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002667 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002668 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002669 TAG, "Dying app: " + app + ", pid: " + pid
2670 + ", thread: " + thread.asBinder());
2671 boolean doLowMem = app.instrumentationClass == null;
2672 handleAppDiedLocked(app, false);
2673
2674 if (doLowMem) {
2675 // If there are no longer any background processes running,
2676 // and the app that died was not running instrumentation,
2677 // then tell everyone we are now low on memory.
2678 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002679 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2680 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2682 haveBg = true;
2683 break;
2684 }
2685 }
2686
2687 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002688 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002689 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002690 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002691 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2692 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002693 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002694 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2695 // The low memory report is overriding any current
2696 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002697 // heavy/important/visible/foreground processes first.
2698 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002699 rec.lastRequestedGc = 0;
2700 } else {
2701 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002703 rec.reportLowMemory = true;
2704 rec.lastLowMemory = now;
2705 mProcessesToGc.remove(rec);
2706 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002707 }
2708 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002709 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002710 }
2711 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002712 } else if (app.pid != pid) {
2713 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002714 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002715 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002716 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002717 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002718 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 + thread.asBinder());
2720 }
2721 }
2722
Dan Egnor42471dd2010-01-07 17:25:22 -08002723 /**
2724 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002725 * @param clearTraces causes the dump file to be erased prior to the new
2726 * traces being written, if true; when false, the new traces will be
2727 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002728 * @param firstPids of dalvik VM processes to dump stack traces for first
2729 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002730 * @return file containing stack traces, or null if no dump file is configured
2731 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002732 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2733 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002734 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2735 if (tracesPath == null || tracesPath.length() == 0) {
2736 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002738
2739 File tracesFile = new File(tracesPath);
2740 try {
2741 File tracesDir = tracesFile.getParentFile();
2742 if (!tracesDir.exists()) tracesFile.mkdirs();
2743 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2744
Christopher Tate6ee412d2010-05-28 12:01:56 -07002745 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002746 tracesFile.createNewFile();
2747 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2748 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002749 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002750 return null;
2751 }
2752
2753 // Use a FileObserver to detect when traces finish writing.
2754 // The order of traces is considered important to maintain for legibility.
2755 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2756 public synchronized void onEvent(int event, String path) { notify(); }
2757 };
2758
2759 try {
2760 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002761
2762 // First collect all of the stacks of the most important pids.
2763 try {
2764 int num = firstPids.size();
2765 for (int i = 0; i < num; i++) {
2766 synchronized (observer) {
2767 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2768 observer.wait(200); // Wait for write-close, give up after 200msec
2769 }
2770 }
2771 } catch (InterruptedException e) {
2772 Log.wtf(TAG, e);
2773 }
2774
2775 // Next measure CPU usage.
2776 if (processStats != null) {
2777 processStats.init();
2778 System.gc();
2779 processStats.update();
2780 try {
2781 synchronized (processStats) {
2782 processStats.wait(500); // measure over 1/2 second.
2783 }
2784 } catch (InterruptedException e) {
2785 }
2786 processStats.update();
2787
2788 // We'll take the stack crawls of just the top apps using CPU.
2789 final int N = processStats.countWorkingStats();
2790 int numProcs = 0;
2791 for (int i=0; i<N && numProcs<5; i++) {
2792 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2793 if (lastPids.indexOfKey(stats.pid) >= 0) {
2794 numProcs++;
2795 try {
2796 synchronized (observer) {
2797 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2798 observer.wait(200); // Wait for write-close, give up after 200msec
2799 }
2800 } catch (InterruptedException e) {
2801 Log.wtf(TAG, e);
2802 }
2803
2804 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002805 }
2806 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002807
2808 return tracesFile;
2809
Dan Egnor42471dd2010-01-07 17:25:22 -08002810 } finally {
2811 observer.stopWatching();
2812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813 }
2814
Jeff Brown4d94a762010-09-23 11:33:28 -07002815 private final class AppNotResponding implements Runnable {
2816 private final ProcessRecord mApp;
2817 private final String mAnnotation;
2818
2819 public AppNotResponding(ProcessRecord app, String annotation) {
2820 mApp = app;
2821 mAnnotation = annotation;
2822 }
2823
2824 @Override
2825 public void run() {
2826 appNotResponding(mApp, null, null, mAnnotation);
2827 }
2828 }
2829
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002830 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2831 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002832 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2833 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2834
Dianne Hackborn287952c2010-09-22 22:34:31 -07002835 if (mController != null) {
2836 try {
2837 // 0 == continue, -1 = kill process immediately
2838 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2839 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2840 } catch (RemoteException e) {
2841 mController = null;
2842 }
2843 }
2844
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002845 long anrTime = SystemClock.uptimeMillis();
2846 if (MONITOR_CPU_USAGE) {
2847 updateCpuStatsNow();
2848 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002849
2850 synchronized (this) {
2851 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2852 if (mShuttingDown) {
2853 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2854 return;
2855 } else if (app.notResponding) {
2856 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2857 return;
2858 } else if (app.crashing) {
2859 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2860 return;
2861 }
2862
2863 // In case we come through here for the same app before completing
2864 // this one, mark as anring now so we will bail out.
2865 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002866
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002867 // Log the ANR to the event log.
2868 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2869 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002870
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002871 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002872 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002873
2874 int parentPid = app.pid;
2875 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002876 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002877
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002878 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002879
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002880 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2881 ProcessRecord r = mLruProcesses.get(i);
2882 if (r != null && r.thread != null) {
2883 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002884 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2885 if (r.persistent) {
2886 firstPids.add(pid);
2887 } else {
2888 lastPids.put(pid, Boolean.TRUE);
2889 }
2890 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002891 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 }
2893 }
2894
Dan Egnor42471dd2010-01-07 17:25:22 -08002895 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002896 StringBuilder info = mStringBuilder;
2897 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002898 info.append("ANR in ").append(app.processName);
2899 if (activity != null && activity.shortComponentName != null) {
2900 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002901 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002902 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002904 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002906 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002907 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002909
Dianne Hackborn287952c2010-09-22 22:34:31 -07002910 final ProcessStats processStats = new ProcessStats(true);
2911
2912 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2913
Dan Egnor42471dd2010-01-07 17:25:22 -08002914 String cpuInfo = null;
2915 if (MONITOR_CPU_USAGE) {
2916 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002917 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002918 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002919 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002920 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002921 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002922 }
2923
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002924 info.append(processStats.printCurrentState(anrTime));
2925
Joe Onorato8a9b2202010-02-26 18:56:32 -08002926 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002927 if (tracesFile == null) {
2928 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2929 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2930 }
2931
2932 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2933
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002934 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002936 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2937 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002939 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2940 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 }
2942 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002943 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 }
2945 }
2946
Dan Egnor42471dd2010-01-07 17:25:22 -08002947 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2948 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2949 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002950
2951 synchronized (this) {
2952 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2953 Process.killProcess(app.pid);
2954 return;
2955 }
2956
2957 // Set the app's notResponding state, and look up the errorReportReceiver
2958 makeAppNotRespondingLocked(app,
2959 activity != null ? activity.shortComponentName : null,
2960 annotation != null ? "ANR " + annotation : "ANR",
2961 info.toString());
2962
2963 // Bring up the infamous App Not Responding dialog
2964 Message msg = Message.obtain();
2965 HashMap map = new HashMap();
2966 msg.what = SHOW_NOT_RESPONDING_MSG;
2967 msg.obj = map;
2968 map.put("app", app);
2969 if (activity != null) {
2970 map.put("activity", activity);
2971 }
2972
2973 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 }
2976
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002977 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2978 if (!mLaunchWarningShown) {
2979 mLaunchWarningShown = true;
2980 mHandler.post(new Runnable() {
2981 @Override
2982 public void run() {
2983 synchronized (ActivityManagerService.this) {
2984 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
2985 d.show();
2986 mHandler.postDelayed(new Runnable() {
2987 @Override
2988 public void run() {
2989 synchronized (ActivityManagerService.this) {
2990 d.dismiss();
2991 mLaunchWarningShown = false;
2992 }
2993 }
2994 }, 4000);
2995 }
2996 }
2997 });
2998 }
2999 }
3000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001 public boolean clearApplicationUserData(final String packageName,
3002 final IPackageDataObserver observer) {
3003 int uid = Binder.getCallingUid();
3004 int pid = Binder.getCallingPid();
3005 long callingId = Binder.clearCallingIdentity();
3006 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003007 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003008 int pkgUid = -1;
3009 synchronized(this) {
3010 try {
3011 pkgUid = pm.getPackageUid(packageName);
3012 } catch (RemoteException e) {
3013 }
3014 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003015 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003016 return false;
3017 }
3018 if (uid == pkgUid || checkComponentPermission(
3019 android.Manifest.permission.CLEAR_APP_USER_DATA,
3020 pid, uid, -1)
3021 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003022 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 } else {
3024 throw new SecurityException(pid+" does not have permission:"+
3025 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3026 "for process:"+packageName);
3027 }
3028 }
3029
3030 try {
3031 //clear application user data
3032 pm.clearApplicationUserData(packageName, observer);
3033 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3034 Uri.fromParts("package", packageName, null));
3035 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003036 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3037 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003038 } catch (RemoteException e) {
3039 }
3040 } finally {
3041 Binder.restoreCallingIdentity(callingId);
3042 }
3043 return true;
3044 }
3045
Dianne Hackborn03abb812010-01-04 18:43:19 -08003046 public void killBackgroundProcesses(final String packageName) {
3047 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3048 != PackageManager.PERMISSION_GRANTED &&
3049 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3050 != PackageManager.PERMISSION_GRANTED) {
3051 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 + Binder.getCallingPid()
3053 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003054 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003055 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003056 throw new SecurityException(msg);
3057 }
3058
3059 long callingId = Binder.clearCallingIdentity();
3060 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003061 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 int pkgUid = -1;
3063 synchronized(this) {
3064 try {
3065 pkgUid = pm.getPackageUid(packageName);
3066 } catch (RemoteException e) {
3067 }
3068 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003069 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003070 return;
3071 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003072 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003073 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003074 }
3075 } finally {
3076 Binder.restoreCallingIdentity(callingId);
3077 }
3078 }
3079
3080 public void forceStopPackage(final String packageName) {
3081 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3082 != PackageManager.PERMISSION_GRANTED) {
3083 String msg = "Permission Denial: forceStopPackage() from pid="
3084 + Binder.getCallingPid()
3085 + ", uid=" + Binder.getCallingUid()
3086 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003087 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003088 throw new SecurityException(msg);
3089 }
3090
3091 long callingId = Binder.clearCallingIdentity();
3092 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003093 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003094 int pkgUid = -1;
3095 synchronized(this) {
3096 try {
3097 pkgUid = pm.getPackageUid(packageName);
3098 } catch (RemoteException e) {
3099 }
3100 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003101 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003102 return;
3103 }
3104 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 }
3106 } finally {
3107 Binder.restoreCallingIdentity(callingId);
3108 }
3109 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003110
3111 /*
3112 * The pkg name and uid have to be specified.
3113 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3114 */
3115 public void killApplicationWithUid(String pkg, int uid) {
3116 if (pkg == null) {
3117 return;
3118 }
3119 // Make sure the uid is valid.
3120 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003121 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003122 return;
3123 }
3124 int callerUid = Binder.getCallingUid();
3125 // Only the system server can kill an application
3126 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003127 // Post an aysnc message to kill the application
3128 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3129 msg.arg1 = uid;
3130 msg.arg2 = 0;
3131 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003132 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003133 } else {
3134 throw new SecurityException(callerUid + " cannot kill pkg: " +
3135 pkg);
3136 }
3137 }
3138
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003139 public void closeSystemDialogs(String reason) {
3140 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003141 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003142 if (reason != null) {
3143 intent.putExtra("reason", reason);
3144 }
3145
3146 final int uid = Binder.getCallingUid();
3147 final long origId = Binder.clearCallingIdentity();
3148 synchronized (this) {
3149 int i = mWatchers.beginBroadcast();
3150 while (i > 0) {
3151 i--;
3152 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3153 if (w != null) {
3154 try {
3155 w.closingSystemDialogs(reason);
3156 } catch (RemoteException e) {
3157 }
3158 }
3159 }
3160 mWatchers.finishBroadcast();
3161
Dianne Hackbornffa42482009-09-23 22:20:11 -07003162 mWindowManager.closeSystemDialogs(reason);
3163
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003164 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3165 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003166 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003167 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003168 Activity.RESULT_CANCELED, null, "close-sys");
3169 }
3170 }
3171
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003172 broadcastIntentLocked(null, null, intent, null,
3173 null, 0, null, null, null, false, false, -1, uid);
3174 }
3175 Binder.restoreCallingIdentity(origId);
3176 }
3177
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003178 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003179 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003180 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3181 for (int i=pids.length-1; i>=0; i--) {
3182 infos[i] = new Debug.MemoryInfo();
3183 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003184 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003185 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003186 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003187
3188 public void killApplicationProcess(String processName, int uid) {
3189 if (processName == null) {
3190 return;
3191 }
3192
3193 int callerUid = Binder.getCallingUid();
3194 // Only the system server can kill an application
3195 if (callerUid == Process.SYSTEM_UID) {
3196 synchronized (this) {
3197 ProcessRecord app = getProcessRecordLocked(processName, uid);
3198 if (app != null) {
3199 try {
3200 app.thread.scheduleSuicide();
3201 } catch (RemoteException e) {
3202 // If the other end already died, then our work here is done.
3203 }
3204 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003205 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003206 + processName + " / " + uid);
3207 }
3208 }
3209 } else {
3210 throw new SecurityException(callerUid + " cannot kill app process: " +
3211 processName);
3212 }
3213 }
3214
Dianne Hackborn03abb812010-01-04 18:43:19 -08003215 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003216 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003217 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3218 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003219 if (!mProcessesReady) {
3220 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 intent.putExtra(Intent.EXTRA_UID, uid);
3223 broadcastIntentLocked(null, null, intent,
3224 null, null, 0, null, null, null,
3225 false, false, MY_PID, Process.SYSTEM_UID);
3226 }
3227
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003228 private final boolean killPackageProcessesLocked(String packageName, int uid,
3229 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003230 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231
Dianne Hackborn03abb812010-01-04 18:43:19 -08003232 // Remove all processes this package may have touched: all with the
3233 // same UID (except for the system or root user), and all whose name
3234 // matches the package name.
3235 final String procNamePrefix = packageName + ":";
3236 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3237 final int NA = apps.size();
3238 for (int ia=0; ia<NA; ia++) {
3239 ProcessRecord app = apps.valueAt(ia);
3240 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003241 if (doit) {
3242 procs.add(app);
3243 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003244 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3245 || app.processName.equals(packageName)
3246 || app.processName.startsWith(procNamePrefix)) {
3247 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003248 if (!doit) {
3249 return true;
3250 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003251 app.removed = true;
3252 procs.add(app);
3253 }
3254 }
3255 }
3256 }
3257
3258 int N = procs.size();
3259 for (int i=0; i<N; i++) {
3260 removeProcessLocked(procs.get(i), callerWillRestart);
3261 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003262 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003263 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003264
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003265 private final boolean forceStopPackageLocked(String name, int uid,
3266 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 int i, N;
3268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269 if (uid < 0) {
3270 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003271 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003272 } catch (RemoteException e) {
3273 }
3274 }
3275
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003276 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003277 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003278
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003279 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3280 while (badApps.hasNext()) {
3281 SparseArray<Long> ba = badApps.next();
3282 if (ba.get(uid) != null) {
3283 badApps.remove();
3284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285 }
3286 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003287
3288 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3289 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003290
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003291 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3292 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003293 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003294 if (!doit) {
3295 return true;
3296 }
3297 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003298 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 if (r.app != null) {
3300 r.app.removed = true;
3301 }
3302 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003303 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003304 }
3305 }
3306
3307 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3308 for (ServiceRecord service : mServices.values()) {
3309 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003310 if (!doit) {
3311 return true;
3312 }
3313 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003314 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 if (service.app != null) {
3316 service.app.removed = true;
3317 }
3318 service.app = null;
3319 services.add(service);
3320 }
3321 }
3322
3323 N = services.size();
3324 for (i=0; i<N; i++) {
3325 bringDownServiceLocked(services.get(i), true);
3326 }
3327
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003328 if (doit) {
3329 if (purgeCache) {
3330 AttributeCache ac = AttributeCache.instance();
3331 if (ac != null) {
3332 ac.removePackage(name);
3333 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003334 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003335 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003336 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003337
3338 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 }
3340
3341 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3342 final String name = app.processName;
3343 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003344 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 TAG, "Force removing process " + app + " (" + name
3346 + "/" + uid + ")");
3347
3348 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003349 if (mHeavyWeightProcess == app) {
3350 mHeavyWeightProcess = null;
3351 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 boolean needRestart = false;
3354 if (app.pid > 0 && app.pid != MY_PID) {
3355 int pid = app.pid;
3356 synchronized (mPidsSelfLocked) {
3357 mPidsSelfLocked.remove(pid);
3358 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3359 }
3360 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003361 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 Process.killProcess(pid);
3363
3364 if (app.persistent) {
3365 if (!callerWillRestart) {
3366 addAppLocked(app.info);
3367 } else {
3368 needRestart = true;
3369 }
3370 }
3371 } else {
3372 mRemovedProcesses.add(app);
3373 }
3374
3375 return needRestart;
3376 }
3377
3378 private final void processStartTimedOutLocked(ProcessRecord app) {
3379 final int pid = app.pid;
3380 boolean gone = false;
3381 synchronized (mPidsSelfLocked) {
3382 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3383 if (knownApp != null && knownApp.thread == null) {
3384 mPidsSelfLocked.remove(pid);
3385 gone = true;
3386 }
3387 }
3388
3389 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003390 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003391 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003392 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003394 if (mHeavyWeightProcess == app) {
3395 mHeavyWeightProcess = null;
3396 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3397 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003398 // Take care of any launching providers waiting for this process.
3399 checkAppInLaunchingProvidersLocked(app, true);
3400 // Take care of any services that are waiting for the process.
3401 for (int i=0; i<mPendingServices.size(); i++) {
3402 ServiceRecord sr = mPendingServices.get(i);
3403 if (app.info.uid == sr.appInfo.uid
3404 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003405 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003406 mPendingServices.remove(i);
3407 i--;
3408 bringDownServiceLocked(sr, true);
3409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003411 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003412 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003413 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003414 try {
3415 IBackupManager bm = IBackupManager.Stub.asInterface(
3416 ServiceManager.getService(Context.BACKUP_SERVICE));
3417 bm.agentDisconnected(app.info.packageName);
3418 } catch (RemoteException e) {
3419 // Can't happen; the backup manager is local
3420 }
3421 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003422 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003423 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003424 mPendingBroadcast.state = BroadcastRecord.IDLE;
3425 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003426 mPendingBroadcast = null;
3427 scheduleBroadcastsLocked();
3428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003430 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003431 }
3432 }
3433
3434 private final boolean attachApplicationLocked(IApplicationThread thread,
3435 int pid) {
3436
3437 // Find the application record that is being attached... either via
3438 // the pid if we are running in multiple processes, or just pull the
3439 // next app record if we are emulating process with anonymous threads.
3440 ProcessRecord app;
3441 if (pid != MY_PID && pid >= 0) {
3442 synchronized (mPidsSelfLocked) {
3443 app = mPidsSelfLocked.get(pid);
3444 }
3445 } else if (mStartingProcesses.size() > 0) {
3446 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003447 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 } else {
3449 app = null;
3450 }
3451
3452 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003453 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003455 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 if (pid > 0 && pid != MY_PID) {
3457 Process.killProcess(pid);
3458 } else {
3459 try {
3460 thread.scheduleExit();
3461 } catch (Exception e) {
3462 // Ignore exceptions.
3463 }
3464 }
3465 return false;
3466 }
3467
3468 // If this application record is still attached to a previous
3469 // process, clean it up now.
3470 if (app.thread != null) {
3471 handleAppDiedLocked(app, true);
3472 }
3473
3474 // Tell the process all about itself.
3475
Joe Onorato8a9b2202010-02-26 18:56:32 -08003476 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003477 TAG, "Binding process pid " + pid + " to record " + app);
3478
3479 String processName = app.processName;
3480 try {
3481 thread.asBinder().linkToDeath(new AppDeathRecipient(
3482 app, pid, thread), 0);
3483 } catch (RemoteException e) {
3484 app.resetPackageList();
3485 startProcessLocked(app, "link fail", processName);
3486 return false;
3487 }
3488
Doug Zongker2bec3d42009-12-04 12:52:44 -08003489 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003490
3491 app.thread = thread;
3492 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003493 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3494 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 app.forcingToForeground = null;
3496 app.foregroundServices = false;
3497 app.debugging = false;
3498
3499 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3500
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003501 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003502 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003503
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003504 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003505 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003506 }
3507
Joe Onorato8a9b2202010-02-26 18:56:32 -08003508 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003509 TAG, "New app record " + app
3510 + " thread=" + thread.asBinder() + " pid=" + pid);
3511 try {
3512 int testMode = IApplicationThread.DEBUG_OFF;
3513 if (mDebugApp != null && mDebugApp.equals(processName)) {
3514 testMode = mWaitForDebugger
3515 ? IApplicationThread.DEBUG_WAIT
3516 : IApplicationThread.DEBUG_ON;
3517 app.debugging = true;
3518 if (mDebugTransient) {
3519 mDebugApp = mOrigDebugApp;
3520 mWaitForDebugger = mOrigWaitForDebugger;
3521 }
3522 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003523
Christopher Tate181fafa2009-05-14 11:12:14 -07003524 // If the app is being launched for restore or full backup, set it up specially
3525 boolean isRestrictedBackupMode = false;
3526 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3527 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3528 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3529 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003530
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003531 ensurePackageDexOpt(app.instrumentationInfo != null
3532 ? app.instrumentationInfo.packageName
3533 : app.info.packageName);
3534 if (app.instrumentationClass != null) {
3535 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003536 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003537 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003538 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003539 thread.bindApplication(processName, app.instrumentationInfo != null
3540 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003541 app.instrumentationClass, app.instrumentationProfileFile,
3542 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003543 isRestrictedBackupMode || !normalMode,
3544 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003545 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003546 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003547 } catch (Exception e) {
3548 // todo: Yikes! What should we do? For now we will try to
3549 // start another process, but that could easily get us in
3550 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003551 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552
3553 app.resetPackageList();
3554 startProcessLocked(app, "bind fail", processName);
3555 return false;
3556 }
3557
3558 // Remove this record from the list of starting applications.
3559 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003560 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3561 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 mProcessesOnHold.remove(app);
3563
3564 boolean badApp = false;
3565 boolean didSomething = false;
3566
3567 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003568 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003569 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3571 && processName.equals(hr.processName)) {
3572 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003573 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003574 didSomething = true;
3575 }
3576 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003577 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 + hr.intent.getComponent().flattenToShortString(), e);
3579 badApp = true;
3580 }
3581 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003582 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 }
3584 }
3585
3586 // Find any services that should be running in this process...
3587 if (!badApp && mPendingServices.size() > 0) {
3588 ServiceRecord sr = null;
3589 try {
3590 for (int i=0; i<mPendingServices.size(); i++) {
3591 sr = mPendingServices.get(i);
3592 if (app.info.uid != sr.appInfo.uid
3593 || !processName.equals(sr.processName)) {
3594 continue;
3595 }
3596
3597 mPendingServices.remove(i);
3598 i--;
3599 realStartServiceLocked(sr, app);
3600 didSomething = true;
3601 }
3602 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003603 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003604 + sr.shortName, e);
3605 badApp = true;
3606 }
3607 }
3608
3609 // Check if the next broadcast receiver is in this process...
3610 BroadcastRecord br = mPendingBroadcast;
3611 if (!badApp && br != null && br.curApp == app) {
3612 try {
3613 mPendingBroadcast = null;
3614 processCurBroadcastLocked(br, app);
3615 didSomething = true;
3616 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003617 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 + br.curComponent.flattenToShortString(), e);
3619 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003620 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3622 br.resultExtras, br.resultAbort, true);
3623 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003624 // We need to reset the state if we fails to start the receiver.
3625 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 }
3627 }
3628
Christopher Tate181fafa2009-05-14 11:12:14 -07003629 // Check whether the next backup agent is in this process...
3630 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003631 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003632 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003633 try {
3634 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3635 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003636 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003637 e.printStackTrace();
3638 }
3639 }
3640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 if (badApp) {
3642 // todo: Also need to kill application to deal with all
3643 // kinds of exceptions.
3644 handleAppDiedLocked(app, false);
3645 return false;
3646 }
3647
3648 if (!didSomething) {
3649 updateOomAdjLocked();
3650 }
3651
3652 return true;
3653 }
3654
3655 public final void attachApplication(IApplicationThread thread) {
3656 synchronized (this) {
3657 int callingPid = Binder.getCallingPid();
3658 final long origId = Binder.clearCallingIdentity();
3659 attachApplicationLocked(thread, callingPid);
3660 Binder.restoreCallingIdentity(origId);
3661 }
3662 }
3663
Dianne Hackborne88846e2009-09-30 21:34:25 -07003664 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003665 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003666 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 Binder.restoreCallingIdentity(origId);
3668 }
3669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003670 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003671 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003672 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003673 mWindowManager.enableScreenAfterBoot();
3674 }
3675
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003676 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003677 IntentFilter pkgFilter = new IntentFilter();
3678 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3679 pkgFilter.addDataScheme("package");
3680 mContext.registerReceiver(new BroadcastReceiver() {
3681 @Override
3682 public void onReceive(Context context, Intent intent) {
3683 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3684 if (pkgs != null) {
3685 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003686 synchronized (ActivityManagerService.this) {
3687 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3688 setResultCode(Activity.RESULT_OK);
3689 return;
3690 }
3691 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003692 }
3693 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003694 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003695 }, pkgFilter);
3696
3697 synchronized (this) {
3698 // Ensure that any processes we had put on hold are now started
3699 // up.
3700 final int NP = mProcessesOnHold.size();
3701 if (NP > 0) {
3702 ArrayList<ProcessRecord> procs =
3703 new ArrayList<ProcessRecord>(mProcessesOnHold);
3704 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003705 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3706 + procs.get(ip));
3707 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003708 }
3709 }
3710
3711 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003712 // Start looking for apps that are abusing wake locks.
3713 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003714 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003715 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003716 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003717 broadcastIntentLocked(null, null,
3718 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3719 null, null, 0, null, null,
3720 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3721 false, false, MY_PID, Process.SYSTEM_UID);
3722 }
3723 }
3724 }
3725
3726 final void ensureBootCompleted() {
3727 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003728 boolean enableScreen;
3729 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003730 booting = mBooting;
3731 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003732 enableScreen = !mBooted;
3733 mBooted = true;
3734 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003735
3736 if (booting) {
3737 finishBooting();
3738 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003739
3740 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003741 enableScreenAfterBoot();
3742 }
3743 }
3744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 public final void activityPaused(IBinder token, Bundle icicle) {
3746 // Refuse possible leaked file descriptors
3747 if (icicle != null && icicle.hasFileDescriptors()) {
3748 throw new IllegalArgumentException("File descriptors passed in Bundle");
3749 }
3750
3751 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003752 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003753 Binder.restoreCallingIdentity(origId);
3754 }
3755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003756 public final void activityStopped(IBinder token, Bitmap thumbnail,
3757 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003758 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003759 TAG, "Activity stopped: token=" + token);
3760
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003761 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003762
3763 final long origId = Binder.clearCallingIdentity();
3764
3765 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003766 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003768 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003769 r.thumbnail = thumbnail;
3770 r.description = description;
3771 r.stopped = true;
3772 r.state = ActivityState.STOPPED;
3773 if (!r.finishing) {
3774 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003775 r.stack.destroyActivityLocked(r, true);
3776 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003777 }
3778 }
3779 }
3780 }
3781
3782 if (r != null) {
3783 sendPendingThumbnail(r, null, null, null, false);
3784 }
3785
3786 trimApplications();
3787
3788 Binder.restoreCallingIdentity(origId);
3789 }
3790
3791 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003792 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003793 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 }
3795
3796 public String getCallingPackage(IBinder token) {
3797 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003798 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003799 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 }
3801 }
3802
3803 public ComponentName getCallingActivity(IBinder token) {
3804 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003805 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003806 return r != null ? r.intent.getComponent() : null;
3807 }
3808 }
3809
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003810 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003811 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003812 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003813 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 if (r != null) {
3815 return r.resultTo;
3816 }
3817 }
3818 return null;
3819 }
3820
3821 public ComponentName getActivityClassForToken(IBinder token) {
3822 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003823 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003825 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 return r.intent.getComponent();
3827 }
3828 return null;
3829 }
3830 }
3831
3832 public String getPackageForToken(IBinder token) {
3833 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003834 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003836 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003837 return r.packageName;
3838 }
3839 return null;
3840 }
3841 }
3842
3843 public IIntentSender getIntentSender(int type,
3844 String packageName, IBinder token, String resultWho,
3845 int requestCode, Intent intent, String resolvedType, int flags) {
3846 // Refuse possible leaked file descriptors
3847 if (intent != null && intent.hasFileDescriptors() == true) {
3848 throw new IllegalArgumentException("File descriptors passed in Intent");
3849 }
3850
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003851 if (type == INTENT_SENDER_BROADCAST) {
3852 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3853 throw new IllegalArgumentException(
3854 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3855 }
3856 }
3857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003858 synchronized(this) {
3859 int callingUid = Binder.getCallingUid();
3860 try {
3861 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3862 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003863 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 .getPackageUid(packageName);
3865 if (uid != Binder.getCallingUid()) {
3866 String msg = "Permission Denial: getIntentSender() from pid="
3867 + Binder.getCallingPid()
3868 + ", uid=" + Binder.getCallingUid()
3869 + ", (need uid=" + uid + ")"
3870 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003871 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 throw new SecurityException(msg);
3873 }
3874 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003875
3876 return getIntentSenderLocked(type, packageName, callingUid,
3877 token, resultWho, requestCode, intent, resolvedType, flags);
3878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 } catch (RemoteException e) {
3880 throw new SecurityException(e);
3881 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003882 }
3883 }
3884
3885 IIntentSender getIntentSenderLocked(int type,
3886 String packageName, int callingUid, IBinder token, String resultWho,
3887 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003888 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003889 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003890 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003891 if (index < 0) {
3892 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003894 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003895 if (activity.finishing) {
3896 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003898 }
3899
3900 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3901 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3902 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3903 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3904 |PendingIntent.FLAG_UPDATE_CURRENT);
3905
3906 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3907 type, packageName, activity, resultWho,
3908 requestCode, intent, resolvedType, flags);
3909 WeakReference<PendingIntentRecord> ref;
3910 ref = mIntentSenderRecords.get(key);
3911 PendingIntentRecord rec = ref != null ? ref.get() : null;
3912 if (rec != null) {
3913 if (!cancelCurrent) {
3914 if (updateCurrent) {
3915 rec.key.requestIntent.replaceExtras(intent);
3916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 return rec;
3918 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003919 rec.canceled = true;
3920 mIntentSenderRecords.remove(key);
3921 }
3922 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003923 return rec;
3924 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003925 rec = new PendingIntentRecord(this, key, callingUid);
3926 mIntentSenderRecords.put(key, rec.ref);
3927 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3928 if (activity.pendingResults == null) {
3929 activity.pendingResults
3930 = new HashSet<WeakReference<PendingIntentRecord>>();
3931 }
3932 activity.pendingResults.add(rec.ref);
3933 }
3934 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 }
3936
3937 public void cancelIntentSender(IIntentSender sender) {
3938 if (!(sender instanceof PendingIntentRecord)) {
3939 return;
3940 }
3941 synchronized(this) {
3942 PendingIntentRecord rec = (PendingIntentRecord)sender;
3943 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003944 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 .getPackageUid(rec.key.packageName);
3946 if (uid != Binder.getCallingUid()) {
3947 String msg = "Permission Denial: cancelIntentSender() from pid="
3948 + Binder.getCallingPid()
3949 + ", uid=" + Binder.getCallingUid()
3950 + " is not allowed to cancel packges "
3951 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003952 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 throw new SecurityException(msg);
3954 }
3955 } catch (RemoteException e) {
3956 throw new SecurityException(e);
3957 }
3958 cancelIntentSenderLocked(rec, true);
3959 }
3960 }
3961
3962 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3963 rec.canceled = true;
3964 mIntentSenderRecords.remove(rec.key);
3965 if (cleanActivity && rec.key.activity != null) {
3966 rec.key.activity.pendingResults.remove(rec.ref);
3967 }
3968 }
3969
3970 public String getPackageForIntentSender(IIntentSender pendingResult) {
3971 if (!(pendingResult instanceof PendingIntentRecord)) {
3972 return null;
3973 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003974 try {
3975 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3976 return res.key.packageName;
3977 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003978 }
3979 return null;
3980 }
3981
3982 public void setProcessLimit(int max) {
3983 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3984 "setProcessLimit()");
3985 mProcessLimit = max;
3986 }
3987
3988 public int getProcessLimit() {
3989 return mProcessLimit;
3990 }
3991
3992 void foregroundTokenDied(ForegroundToken token) {
3993 synchronized (ActivityManagerService.this) {
3994 synchronized (mPidsSelfLocked) {
3995 ForegroundToken cur
3996 = mForegroundProcesses.get(token.pid);
3997 if (cur != token) {
3998 return;
3999 }
4000 mForegroundProcesses.remove(token.pid);
4001 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4002 if (pr == null) {
4003 return;
4004 }
4005 pr.forcingToForeground = null;
4006 pr.foregroundServices = false;
4007 }
4008 updateOomAdjLocked();
4009 }
4010 }
4011
4012 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4013 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4014 "setProcessForeground()");
4015 synchronized(this) {
4016 boolean changed = false;
4017
4018 synchronized (mPidsSelfLocked) {
4019 ProcessRecord pr = mPidsSelfLocked.get(pid);
4020 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004021 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004022 return;
4023 }
4024 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4025 if (oldToken != null) {
4026 oldToken.token.unlinkToDeath(oldToken, 0);
4027 mForegroundProcesses.remove(pid);
4028 pr.forcingToForeground = null;
4029 changed = true;
4030 }
4031 if (isForeground && token != null) {
4032 ForegroundToken newToken = new ForegroundToken() {
4033 public void binderDied() {
4034 foregroundTokenDied(this);
4035 }
4036 };
4037 newToken.pid = pid;
4038 newToken.token = token;
4039 try {
4040 token.linkToDeath(newToken, 0);
4041 mForegroundProcesses.put(pid, newToken);
4042 pr.forcingToForeground = token;
4043 changed = true;
4044 } catch (RemoteException e) {
4045 // If the process died while doing this, we will later
4046 // do the cleanup with the process death link.
4047 }
4048 }
4049 }
4050
4051 if (changed) {
4052 updateOomAdjLocked();
4053 }
4054 }
4055 }
4056
4057 // =========================================================
4058 // PERMISSIONS
4059 // =========================================================
4060
4061 static class PermissionController extends IPermissionController.Stub {
4062 ActivityManagerService mActivityManagerService;
4063 PermissionController(ActivityManagerService activityManagerService) {
4064 mActivityManagerService = activityManagerService;
4065 }
4066
4067 public boolean checkPermission(String permission, int pid, int uid) {
4068 return mActivityManagerService.checkPermission(permission, pid,
4069 uid) == PackageManager.PERMISSION_GRANTED;
4070 }
4071 }
4072
4073 /**
4074 * This can be called with or without the global lock held.
4075 */
4076 int checkComponentPermission(String permission, int pid, int uid,
4077 int reqUid) {
4078 // We might be performing an operation on behalf of an indirect binder
4079 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4080 // client identity accordingly before proceeding.
4081 Identity tlsIdentity = sCallerIdentity.get();
4082 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004083 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004084 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4085 uid = tlsIdentity.uid;
4086 pid = tlsIdentity.pid;
4087 }
4088
4089 // Root, system server and our own process get to do everything.
4090 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4091 !Process.supportsProcesses()) {
4092 return PackageManager.PERMISSION_GRANTED;
4093 }
4094 // If the target requires a specific UID, always fail for others.
4095 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004096 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 return PackageManager.PERMISSION_DENIED;
4098 }
4099 if (permission == null) {
4100 return PackageManager.PERMISSION_GRANTED;
4101 }
4102 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004103 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 .checkUidPermission(permission, uid);
4105 } catch (RemoteException e) {
4106 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004107 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108 }
4109 return PackageManager.PERMISSION_DENIED;
4110 }
4111
4112 /**
4113 * As the only public entry point for permissions checking, this method
4114 * can enforce the semantic that requesting a check on a null global
4115 * permission is automatically denied. (Internally a null permission
4116 * string is used when calling {@link #checkComponentPermission} in cases
4117 * when only uid-based security is needed.)
4118 *
4119 * This can be called with or without the global lock held.
4120 */
4121 public int checkPermission(String permission, int pid, int uid) {
4122 if (permission == null) {
4123 return PackageManager.PERMISSION_DENIED;
4124 }
4125 return checkComponentPermission(permission, pid, uid, -1);
4126 }
4127
4128 /**
4129 * Binder IPC calls go through the public entry point.
4130 * This can be called with or without the global lock held.
4131 */
4132 int checkCallingPermission(String permission) {
4133 return checkPermission(permission,
4134 Binder.getCallingPid(),
4135 Binder.getCallingUid());
4136 }
4137
4138 /**
4139 * This can be called with or without the global lock held.
4140 */
4141 void enforceCallingPermission(String permission, String func) {
4142 if (checkCallingPermission(permission)
4143 == PackageManager.PERMISSION_GRANTED) {
4144 return;
4145 }
4146
4147 String msg = "Permission Denial: " + func + " from pid="
4148 + Binder.getCallingPid()
4149 + ", uid=" + Binder.getCallingUid()
4150 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004151 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004152 throw new SecurityException(msg);
4153 }
4154
4155 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004156 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4157 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4158 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4159 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4160 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004162 // Is the component private from the target uid?
4163 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4164
4165 // Acceptable if the there is no read permission needed from the
4166 // target or the target is holding the read permission.
4167 if (!readPerm) {
4168 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004170 == PackageManager.PERMISSION_GRANTED)) {
4171 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 }
4173 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004174
4175 // Acceptable if the there is no write permission needed from the
4176 // target or the target is holding the read permission.
4177 if (!writePerm) {
4178 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004180 == PackageManager.PERMISSION_GRANTED)) {
4181 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004182 }
4183 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004184
4185 // Acceptable if there is a path permission matching the URI that
4186 // the target holds the permission on.
4187 PathPermission[] pps = pi.pathPermissions;
4188 if (pps != null && (!readPerm || !writePerm)) {
4189 final String path = uri.getPath();
4190 int i = pps.length;
4191 while (i > 0 && (!readPerm || !writePerm)) {
4192 i--;
4193 PathPermission pp = pps[i];
4194 if (!readPerm) {
4195 final String pprperm = pp.getReadPermission();
4196 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4197 + pprperm + " for " + pp.getPath()
4198 + ": match=" + pp.match(path)
4199 + " check=" + pm.checkUidPermission(pprperm, uid));
4200 if (pprperm != null && pp.match(path) &&
4201 (pm.checkUidPermission(pprperm, uid)
4202 == PackageManager.PERMISSION_GRANTED)) {
4203 readPerm = true;
4204 }
4205 }
4206 if (!writePerm) {
4207 final String ppwperm = pp.getWritePermission();
4208 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4209 + ppwperm + " for " + pp.getPath()
4210 + ": match=" + pp.match(path)
4211 + " check=" + pm.checkUidPermission(ppwperm, uid));
4212 if (ppwperm != null && pp.match(path) &&
4213 (pm.checkUidPermission(ppwperm, uid)
4214 == PackageManager.PERMISSION_GRANTED)) {
4215 writePerm = true;
4216 }
4217 }
4218 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004220 } catch (RemoteException e) {
4221 return false;
4222 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004223
4224 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 }
4226
4227 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4228 int modeFlags) {
4229 // Root gets to do everything.
4230 if (uid == 0 || !Process.supportsProcesses()) {
4231 return true;
4232 }
4233 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4234 if (perms == null) return false;
4235 UriPermission perm = perms.get(uri);
4236 if (perm == null) return false;
4237 return (modeFlags&perm.modeFlags) == modeFlags;
4238 }
4239
4240 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4241 // Another redirected-binder-call permissions check as in
4242 // {@link checkComponentPermission}.
4243 Identity tlsIdentity = sCallerIdentity.get();
4244 if (tlsIdentity != null) {
4245 uid = tlsIdentity.uid;
4246 pid = tlsIdentity.pid;
4247 }
4248
4249 // Our own process gets to do everything.
4250 if (pid == MY_PID) {
4251 return PackageManager.PERMISSION_GRANTED;
4252 }
4253 synchronized(this) {
4254 return checkUriPermissionLocked(uri, uid, modeFlags)
4255 ? PackageManager.PERMISSION_GRANTED
4256 : PackageManager.PERMISSION_DENIED;
4257 }
4258 }
4259
Dianne Hackborn39792d22010-08-19 18:01:52 -07004260 /**
4261 * Check if the targetPkg can be granted permission to access uri by
4262 * the callingUid using the given modeFlags. Throws a security exception
4263 * if callingUid is not allowed to do this. Returns the uid of the target
4264 * if the URI permission grant should be performed; returns -1 if it is not
4265 * needed (for example targetPkg already has permission to access the URI).
4266 */
4267 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4268 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4270 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4271 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004272 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004273 }
4274
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004275 if (targetPkg != null) {
4276 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4277 "Checking grant " + targetPkg + " permission to " + uri);
4278 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004279
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004280 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281
4282 // If this is not a content: uri, we can't do anything with it.
4283 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004284 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004285 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004286 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287 }
4288
4289 String name = uri.getAuthority();
4290 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004291 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 if (cpr != null) {
4293 pi = cpr.info;
4294 } else {
4295 try {
4296 pi = pm.resolveContentProvider(name,
4297 PackageManager.GET_URI_PERMISSION_PATTERNS);
4298 } catch (RemoteException ex) {
4299 }
4300 }
4301 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004302 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004303 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 }
4305
4306 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004307 if (targetPkg != null) {
4308 try {
4309 targetUid = pm.getPackageUid(targetPkg);
4310 if (targetUid < 0) {
4311 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4312 "Can't grant URI permission no uid for: " + targetPkg);
4313 return -1;
4314 }
4315 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004316 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004318 } else {
4319 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 }
4321
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004322 if (targetUid >= 0) {
4323 // First... does the target actually need this permission?
4324 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4325 // No need to grant the target this permission.
4326 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4327 "Target " + targetPkg + " already has full permission to " + uri);
4328 return -1;
4329 }
4330 } else {
4331 // First... there is no target package, so can anyone access it?
4332 boolean allowed = pi.exported;
4333 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4334 if (pi.readPermission != null) {
4335 allowed = false;
4336 }
4337 }
4338 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4339 if (pi.writePermission != null) {
4340 allowed = false;
4341 }
4342 }
4343 if (allowed) {
4344 return -1;
4345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346 }
4347
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004348 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 if (!pi.grantUriPermissions) {
4350 throw new SecurityException("Provider " + pi.packageName
4351 + "/" + pi.name
4352 + " does not allow granting of Uri permissions (uri "
4353 + uri + ")");
4354 }
4355 if (pi.uriPermissionPatterns != null) {
4356 final int N = pi.uriPermissionPatterns.length;
4357 boolean allowed = false;
4358 for (int i=0; i<N; i++) {
4359 if (pi.uriPermissionPatterns[i] != null
4360 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4361 allowed = true;
4362 break;
4363 }
4364 }
4365 if (!allowed) {
4366 throw new SecurityException("Provider " + pi.packageName
4367 + "/" + pi.name
4368 + " does not allow granting of permission to path of Uri "
4369 + uri);
4370 }
4371 }
4372
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004373 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004375 if (callingUid != Process.myUid()) {
4376 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4377 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4378 throw new SecurityException("Uid " + callingUid
4379 + " does not have permission to uri " + uri);
4380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004381 }
4382 }
4383
Dianne Hackborn39792d22010-08-19 18:01:52 -07004384 return targetUid;
4385 }
4386
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004387 public int checkGrantUriPermission(int callingUid, String targetPkg,
4388 Uri uri, int modeFlags) {
4389 synchronized(this) {
4390 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4391 }
4392 }
4393
Dianne Hackborn39792d22010-08-19 18:01:52 -07004394 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4395 Uri uri, int modeFlags, UriPermissionOwner owner) {
4396 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4397 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4398 if (modeFlags == 0) {
4399 return;
4400 }
4401
4402 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 // to the uri, and the target doesn't. Let's now give this to
4404 // the target.
4405
Joe Onorato8a9b2202010-02-26 18:56:32 -08004406 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004407 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004409 HashMap<Uri, UriPermission> targetUris
4410 = mGrantedUriPermissions.get(targetUid);
4411 if (targetUris == null) {
4412 targetUris = new HashMap<Uri, UriPermission>();
4413 mGrantedUriPermissions.put(targetUid, targetUris);
4414 }
4415
4416 UriPermission perm = targetUris.get(uri);
4417 if (perm == null) {
4418 perm = new UriPermission(targetUid, uri);
4419 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004420 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004422 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004423 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 perm.globalModeFlags |= modeFlags;
4425 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004426 perm.readOwners.add(owner);
4427 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004428 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004429 perm.writeOwners.add(owner);
4430 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 }
4432 }
4433
Dianne Hackborn39792d22010-08-19 18:01:52 -07004434 void grantUriPermissionLocked(int callingUid,
4435 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004436 if (targetPkg == null) {
4437 throw new NullPointerException("targetPkg");
4438 }
4439
Dianne Hackborn39792d22010-08-19 18:01:52 -07004440 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4441 if (targetUid < 0) {
4442 return;
4443 }
4444
4445 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4446 }
4447
4448 /**
4449 * Like checkGrantUriPermissionLocked, but takes an Intent.
4450 */
4451 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4452 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004453 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004454 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004455 + " from " + intent + "; flags=0x"
4456 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4457
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004458 if (targetPkg == null) {
4459 throw new NullPointerException("targetPkg");
4460 }
4461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004462 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004463 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004464 }
4465 Uri data = intent.getData();
4466 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004467 return -1;
4468 }
4469 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4470 intent.getFlags());
4471 }
4472
4473 /**
4474 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4475 */
4476 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4477 String targetPkg, Intent intent, UriPermissionOwner owner) {
4478 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4479 intent.getFlags(), owner);
4480 }
4481
4482 void grantUriPermissionFromIntentLocked(int callingUid,
4483 String targetPkg, Intent intent, UriPermissionOwner owner) {
4484 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4485 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486 return;
4487 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004488
4489 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 }
4491
4492 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4493 Uri uri, int modeFlags) {
4494 synchronized(this) {
4495 final ProcessRecord r = getRecordForAppLocked(caller);
4496 if (r == null) {
4497 throw new SecurityException("Unable to find app for caller "
4498 + caller
4499 + " when granting permission to uri " + uri);
4500 }
4501 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004502 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 }
4504 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004505 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 }
4507
4508 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4509 null);
4510 }
4511 }
4512
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004513 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004514 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4515 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4516 HashMap<Uri, UriPermission> perms
4517 = mGrantedUriPermissions.get(perm.uid);
4518 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004519 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004520 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 perms.remove(perm.uri);
4522 if (perms.size() == 0) {
4523 mGrantedUriPermissions.remove(perm.uid);
4524 }
4525 }
4526 }
4527 }
4528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004529 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4530 int modeFlags) {
4531 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4532 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4533 if (modeFlags == 0) {
4534 return;
4535 }
4536
Joe Onorato8a9b2202010-02-26 18:56:32 -08004537 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004538 "Revoking all granted permissions to " + uri);
4539
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004540 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004541
4542 final String authority = uri.getAuthority();
4543 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004544 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 if (cpr != null) {
4546 pi = cpr.info;
4547 } else {
4548 try {
4549 pi = pm.resolveContentProvider(authority,
4550 PackageManager.GET_URI_PERMISSION_PATTERNS);
4551 } catch (RemoteException ex) {
4552 }
4553 }
4554 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004555 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 return;
4557 }
4558
4559 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004560 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 // Right now, if you are not the original owner of the permission,
4562 // you are not allowed to revoke it.
4563 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4564 throw new SecurityException("Uid " + callingUid
4565 + " does not have permission to uri " + uri);
4566 //}
4567 }
4568
4569 // Go through all of the permissions and remove any that match.
4570 final List<String> SEGMENTS = uri.getPathSegments();
4571 if (SEGMENTS != null) {
4572 final int NS = SEGMENTS.size();
4573 int N = mGrantedUriPermissions.size();
4574 for (int i=0; i<N; i++) {
4575 HashMap<Uri, UriPermission> perms
4576 = mGrantedUriPermissions.valueAt(i);
4577 Iterator<UriPermission> it = perms.values().iterator();
4578 toploop:
4579 while (it.hasNext()) {
4580 UriPermission perm = it.next();
4581 Uri targetUri = perm.uri;
4582 if (!authority.equals(targetUri.getAuthority())) {
4583 continue;
4584 }
4585 List<String> targetSegments = targetUri.getPathSegments();
4586 if (targetSegments == null) {
4587 continue;
4588 }
4589 if (targetSegments.size() < NS) {
4590 continue;
4591 }
4592 for (int j=0; j<NS; j++) {
4593 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4594 continue toploop;
4595 }
4596 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004597 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004598 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 perm.clearModes(modeFlags);
4600 if (perm.modeFlags == 0) {
4601 it.remove();
4602 }
4603 }
4604 if (perms.size() == 0) {
4605 mGrantedUriPermissions.remove(
4606 mGrantedUriPermissions.keyAt(i));
4607 N--;
4608 i--;
4609 }
4610 }
4611 }
4612 }
4613
4614 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4615 int modeFlags) {
4616 synchronized(this) {
4617 final ProcessRecord r = getRecordForAppLocked(caller);
4618 if (r == null) {
4619 throw new SecurityException("Unable to find app for caller "
4620 + caller
4621 + " when revoking permission to uri " + uri);
4622 }
4623 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004624 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 return;
4626 }
4627
4628 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4629 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4630 if (modeFlags == 0) {
4631 return;
4632 }
4633
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004634 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635
4636 final String authority = uri.getAuthority();
4637 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004638 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004639 if (cpr != null) {
4640 pi = cpr.info;
4641 } else {
4642 try {
4643 pi = pm.resolveContentProvider(authority,
4644 PackageManager.GET_URI_PERMISSION_PATTERNS);
4645 } catch (RemoteException ex) {
4646 }
4647 }
4648 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004649 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 return;
4651 }
4652
4653 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4654 }
4655 }
4656
Dianne Hackborn7e269642010-08-25 19:50:20 -07004657 @Override
4658 public IBinder newUriPermissionOwner(String name) {
4659 synchronized(this) {
4660 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4661 return owner.getExternalTokenLocked();
4662 }
4663 }
4664
4665 @Override
4666 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4667 Uri uri, int modeFlags) {
4668 synchronized(this) {
4669 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4670 if (owner == null) {
4671 throw new IllegalArgumentException("Unknown owner: " + token);
4672 }
4673 if (fromUid != Binder.getCallingUid()) {
4674 if (Binder.getCallingUid() != Process.myUid()) {
4675 // Only system code can grant URI permissions on behalf
4676 // of other users.
4677 throw new SecurityException("nice try");
4678 }
4679 }
4680 if (targetPkg == null) {
4681 throw new IllegalArgumentException("null target");
4682 }
4683 if (uri == null) {
4684 throw new IllegalArgumentException("null uri");
4685 }
4686
4687 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4688 }
4689 }
4690
4691 @Override
4692 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4693 synchronized(this) {
4694 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4695 if (owner == null) {
4696 throw new IllegalArgumentException("Unknown owner: " + token);
4697 }
4698
4699 if (uri == null) {
4700 owner.removeUriPermissionsLocked(mode);
4701 } else {
4702 owner.removeUriPermissionLocked(uri, mode);
4703 }
4704 }
4705 }
4706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4708 synchronized (this) {
4709 ProcessRecord app =
4710 who != null ? getRecordForAppLocked(who) : null;
4711 if (app == null) return;
4712
4713 Message msg = Message.obtain();
4714 msg.what = WAIT_FOR_DEBUGGER_MSG;
4715 msg.obj = app;
4716 msg.arg1 = waiting ? 1 : 0;
4717 mHandler.sendMessage(msg);
4718 }
4719 }
4720
4721 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4722 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004723 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004725 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 }
4727
4728 // =========================================================
4729 // TASK MANAGEMENT
4730 // =========================================================
4731
4732 public List getTasks(int maxNum, int flags,
4733 IThumbnailReceiver receiver) {
4734 ArrayList list = new ArrayList();
4735
4736 PendingThumbnailsRecord pending = null;
4737 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004738 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739
4740 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004741 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4743 + ", receiver=" + receiver);
4744
4745 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4746 != PackageManager.PERMISSION_GRANTED) {
4747 if (receiver != null) {
4748 // If the caller wants to wait for pending thumbnails,
4749 // it ain't gonna get them.
4750 try {
4751 receiver.finished();
4752 } catch (RemoteException ex) {
4753 }
4754 }
4755 String msg = "Permission Denial: getTasks() from pid="
4756 + Binder.getCallingPid()
4757 + ", uid=" + Binder.getCallingUid()
4758 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004759 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004760 throw new SecurityException(msg);
4761 }
4762
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004763 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004764 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004765 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004766 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 CharSequence topDescription = null;
4768 TaskRecord curTask = null;
4769 int numActivities = 0;
4770 int numRunning = 0;
4771 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004772 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004774 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775
4776 // Initialize state for next task if needed.
4777 if (top == null ||
4778 (top.state == ActivityState.INITIALIZING
4779 && top.task == r.task)) {
4780 top = r;
4781 topDescription = r.description;
4782 curTask = r.task;
4783 numActivities = numRunning = 0;
4784 }
4785
4786 // Add 'r' into the current task.
4787 numActivities++;
4788 if (r.app != null && r.app.thread != null) {
4789 numRunning++;
4790 }
4791 if (topDescription == null) {
4792 topDescription = r.description;
4793 }
4794
Joe Onorato8a9b2202010-02-26 18:56:32 -08004795 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 TAG, r.intent.getComponent().flattenToShortString()
4797 + ": task=" + r.task);
4798
4799 // If the next one is a different task, generate a new
4800 // TaskInfo entry for what we have.
4801 if (next == null || next.task != curTask) {
4802 ActivityManager.RunningTaskInfo ci
4803 = new ActivityManager.RunningTaskInfo();
4804 ci.id = curTask.taskId;
4805 ci.baseActivity = r.intent.getComponent();
4806 ci.topActivity = top.intent.getComponent();
4807 ci.thumbnail = top.thumbnail;
4808 ci.description = topDescription;
4809 ci.numActivities = numActivities;
4810 ci.numRunning = numRunning;
4811 //System.out.println(
4812 // "#" + maxNum + ": " + " descr=" + ci.description);
4813 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004814 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 TAG, "State=" + top.state + "Idle=" + top.idle
4816 + " app=" + top.app
4817 + " thr=" + (top.app != null ? top.app.thread : null));
4818 if (top.state == ActivityState.RESUMED
4819 || top.state == ActivityState.PAUSING) {
4820 if (top.idle && top.app != null
4821 && top.app.thread != null) {
4822 topRecord = top;
4823 topThumbnail = top.app.thread;
4824 } else {
4825 top.thumbnailNeeded = true;
4826 }
4827 }
4828 if (pending == null) {
4829 pending = new PendingThumbnailsRecord(receiver);
4830 }
4831 pending.pendingRecords.add(top);
4832 }
4833 list.add(ci);
4834 maxNum--;
4835 top = null;
4836 }
4837 }
4838
4839 if (pending != null) {
4840 mPendingThumbnails.add(pending);
4841 }
4842 }
4843
Joe Onorato8a9b2202010-02-26 18:56:32 -08004844 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845
4846 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004847 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004848 try {
4849 topThumbnail.requestThumbnail(topRecord);
4850 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004851 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004852 sendPendingThumbnail(null, topRecord, null, null, true);
4853 }
4854 }
4855
4856 if (pending == null && receiver != null) {
4857 // In this case all thumbnails were available and the client
4858 // is being asked to be told when the remaining ones come in...
4859 // which is unusually, since the top-most currently running
4860 // activity should never have a canned thumbnail! Oh well.
4861 try {
4862 receiver.finished();
4863 } catch (RemoteException ex) {
4864 }
4865 }
4866
4867 return list;
4868 }
4869
4870 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4871 int flags) {
4872 synchronized (this) {
4873 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4874 "getRecentTasks()");
4875
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004876 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004878 final int N = mRecentTasks.size();
4879 ArrayList<ActivityManager.RecentTaskInfo> res
4880 = new ArrayList<ActivityManager.RecentTaskInfo>(
4881 maxNum < N ? maxNum : N);
4882 for (int i=0; i<N && maxNum > 0; i++) {
4883 TaskRecord tr = mRecentTasks.get(i);
4884 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4885 || (tr.intent == null)
4886 || ((tr.intent.getFlags()
4887 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4888 ActivityManager.RecentTaskInfo rti
4889 = new ActivityManager.RecentTaskInfo();
4890 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4891 rti.baseIntent = new Intent(
4892 tr.intent != null ? tr.intent : tr.affinityIntent);
4893 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004894
4895 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4896 // Check whether this activity is currently available.
4897 try {
4898 if (rti.origActivity != null) {
4899 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4900 continue;
4901 }
4902 } else if (rti.baseIntent != null) {
4903 if (pm.queryIntentActivities(rti.baseIntent,
4904 null, 0) == null) {
4905 continue;
4906 }
4907 }
4908 } catch (RemoteException e) {
4909 // Will never happen.
4910 }
4911 }
4912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004913 res.add(rti);
4914 maxNum--;
4915 }
4916 }
4917 return res;
4918 }
4919 }
4920
4921 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4922 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004923 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004924 TaskRecord jt = startTask;
4925
4926 // First look backwards
4927 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004928 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 if (r.task != jt) {
4930 jt = r.task;
4931 if (affinity.equals(jt.affinity)) {
4932 return j;
4933 }
4934 }
4935 }
4936
4937 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004938 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 jt = startTask;
4940 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004941 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942 if (r.task != jt) {
4943 if (affinity.equals(jt.affinity)) {
4944 return j;
4945 }
4946 jt = r.task;
4947 }
4948 }
4949
4950 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004951 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 return N-1;
4953 }
4954
4955 return -1;
4956 }
4957
4958 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004959 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 */
4961 public void moveTaskToFront(int task) {
4962 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4963 "moveTaskToFront()");
4964
4965 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004966 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4967 Binder.getCallingUid(), "Task to front")) {
4968 return;
4969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004970 final long origId = Binder.clearCallingIdentity();
4971 try {
4972 int N = mRecentTasks.size();
4973 for (int i=0; i<N; i++) {
4974 TaskRecord tr = mRecentTasks.get(i);
4975 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004976 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 return;
4978 }
4979 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004980 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4981 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004983 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004984 return;
4985 }
4986 }
4987 } finally {
4988 Binder.restoreCallingIdentity(origId);
4989 }
4990 }
4991 }
4992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 public void moveTaskToBack(int task) {
4994 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4995 "moveTaskToBack()");
4996
4997 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004998 if (mMainStack.mResumedActivity != null
4999 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005000 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5001 Binder.getCallingUid(), "Task to back")) {
5002 return;
5003 }
5004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005005 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005006 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005007 Binder.restoreCallingIdentity(origId);
5008 }
5009 }
5010
5011 /**
5012 * Moves an activity, and all of the other activities within the same task, to the bottom
5013 * of the history stack. The activity's order within the task is unchanged.
5014 *
5015 * @param token A reference to the activity we wish to move
5016 * @param nonRoot If false then this only works if the activity is the root
5017 * of a task; if true it will work for any activity in a task.
5018 * @return Returns true if the move completed, false if not.
5019 */
5020 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5021 synchronized(this) {
5022 final long origId = Binder.clearCallingIdentity();
5023 int taskId = getTaskForActivityLocked(token, !nonRoot);
5024 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005025 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 }
5027 Binder.restoreCallingIdentity(origId);
5028 }
5029 return false;
5030 }
5031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 public void moveTaskBackwards(int task) {
5033 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5034 "moveTaskBackwards()");
5035
5036 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005037 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5038 Binder.getCallingUid(), "Task backwards")) {
5039 return;
5040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005041 final long origId = Binder.clearCallingIdentity();
5042 moveTaskBackwardsLocked(task);
5043 Binder.restoreCallingIdentity(origId);
5044 }
5045 }
5046
5047 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005048 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 }
5050
5051 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5052 synchronized(this) {
5053 return getTaskForActivityLocked(token, onlyRoot);
5054 }
5055 }
5056
5057 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005058 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005059 TaskRecord lastTask = null;
5060 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005061 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 if (r == token) {
5063 if (!onlyRoot || lastTask != r.task) {
5064 return r.task.taskId;
5065 }
5066 return -1;
5067 }
5068 lastTask = r.task;
5069 }
5070
5071 return -1;
5072 }
5073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 public void finishOtherInstances(IBinder token, ComponentName className) {
5075 synchronized(this) {
5076 final long origId = Binder.clearCallingIdentity();
5077
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005078 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.realActivity.equals(className)
5083 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005084 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005085 null, "others")) {
5086 i--;
5087 N--;
5088 }
5089 }
5090 lastTask = r.task;
5091 }
5092
5093 Binder.restoreCallingIdentity(origId);
5094 }
5095 }
5096
5097 // =========================================================
5098 // THUMBNAILS
5099 // =========================================================
5100
5101 public void reportThumbnail(IBinder token,
5102 Bitmap thumbnail, CharSequence description) {
5103 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5104 final long origId = Binder.clearCallingIdentity();
5105 sendPendingThumbnail(null, token, thumbnail, description, true);
5106 Binder.restoreCallingIdentity(origId);
5107 }
5108
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005109 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 Bitmap thumbnail, CharSequence description, boolean always) {
5111 TaskRecord task = null;
5112 ArrayList receivers = null;
5113
5114 //System.out.println("Send pending thumbnail: " + r);
5115
5116 synchronized(this) {
5117 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005118 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 if (index < 0) {
5120 return;
5121 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005122 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005123 }
5124 if (thumbnail == null) {
5125 thumbnail = r.thumbnail;
5126 description = r.description;
5127 }
5128 if (thumbnail == null && !always) {
5129 // If there is no thumbnail, and this entry is not actually
5130 // going away, then abort for now and pick up the next
5131 // thumbnail we get.
5132 return;
5133 }
5134 task = r.task;
5135
5136 int N = mPendingThumbnails.size();
5137 int i=0;
5138 while (i<N) {
5139 PendingThumbnailsRecord pr =
5140 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5141 //System.out.println("Looking in " + pr.pendingRecords);
5142 if (pr.pendingRecords.remove(r)) {
5143 if (receivers == null) {
5144 receivers = new ArrayList();
5145 }
5146 receivers.add(pr);
5147 if (pr.pendingRecords.size() == 0) {
5148 pr.finished = true;
5149 mPendingThumbnails.remove(i);
5150 N--;
5151 continue;
5152 }
5153 }
5154 i++;
5155 }
5156 }
5157
5158 if (receivers != null) {
5159 final int N = receivers.size();
5160 for (int i=0; i<N; i++) {
5161 try {
5162 PendingThumbnailsRecord pr =
5163 (PendingThumbnailsRecord)receivers.get(i);
5164 pr.receiver.newThumbnail(
5165 task != null ? task.taskId : -1, thumbnail, description);
5166 if (pr.finished) {
5167 pr.receiver.finished();
5168 }
5169 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005170 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005171 }
5172 }
5173 }
5174 }
5175
5176 // =========================================================
5177 // CONTENT PROVIDERS
5178 // =========================================================
5179
5180 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5181 List providers = null;
5182 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005183 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005185 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 } catch (RemoteException ex) {
5187 }
5188 if (providers != null) {
5189 final int N = providers.size();
5190 for (int i=0; i<N; i++) {
5191 ProviderInfo cpi =
5192 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005193 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005194 if (cpr == null) {
5195 cpr = new ContentProviderRecord(cpi, app.info);
5196 mProvidersByClass.put(cpi.name, cpr);
5197 }
5198 app.pubProviders.put(cpi.name, cpr);
5199 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005200 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 }
5202 }
5203 return providers;
5204 }
5205
5206 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005207 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005208 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5209 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5210 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5211 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005212 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005213 return null;
5214 }
5215 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5216 cpi.exported ? -1 : cpi.applicationInfo.uid)
5217 == PackageManager.PERMISSION_GRANTED) {
5218 return null;
5219 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005220
5221 PathPermission[] pps = cpi.pathPermissions;
5222 if (pps != null) {
5223 int i = pps.length;
5224 while (i > 0) {
5225 i--;
5226 PathPermission pp = pps[i];
5227 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5228 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005229 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005230 return null;
5231 }
5232 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5233 cpi.exported ? -1 : cpi.applicationInfo.uid)
5234 == PackageManager.PERMISSION_GRANTED) {
5235 return null;
5236 }
5237 }
5238 }
5239
Dianne Hackbornb424b632010-08-18 15:59:05 -07005240 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5241 if (perms != null) {
5242 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5243 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5244 return null;
5245 }
5246 }
5247 }
5248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 String msg = "Permission Denial: opening provider " + cpi.name
5250 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5251 + ", uid=" + callingUid + ") requires "
5252 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005253 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 return msg;
5255 }
5256
5257 private final ContentProviderHolder getContentProviderImpl(
5258 IApplicationThread caller, String name) {
5259 ContentProviderRecord cpr;
5260 ProviderInfo cpi = null;
5261
5262 synchronized(this) {
5263 ProcessRecord r = null;
5264 if (caller != null) {
5265 r = getRecordForAppLocked(caller);
5266 if (r == null) {
5267 throw new SecurityException(
5268 "Unable to find app for caller " + caller
5269 + " (pid=" + Binder.getCallingPid()
5270 + ") when getting content provider " + name);
5271 }
5272 }
5273
5274 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005275 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 if (cpr != null) {
5277 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005278 String msg;
5279 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5280 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005281 }
5282
5283 if (r != null && cpr.canRunHere(r)) {
5284 // This provider has been published or is in the process
5285 // of being published... but it is also allowed to run
5286 // in the caller's process, so don't make a connection
5287 // and just let the caller instantiate its own instance.
5288 if (cpr.provider != null) {
5289 // don't give caller the provider object, it needs
5290 // to make its own.
5291 cpr = new ContentProviderRecord(cpr);
5292 }
5293 return cpr;
5294 }
5295
5296 final long origId = Binder.clearCallingIdentity();
5297
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005298 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 // return it right away.
5300 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005301 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005302 "Adding provider requested by "
5303 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005304 + cpr.info.processName);
5305 Integer cnt = r.conProviders.get(cpr);
5306 if (cnt == null) {
5307 r.conProviders.put(cpr, new Integer(1));
5308 } else {
5309 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005312 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5313 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005314 // make sure to count it as being accessed and thus
5315 // back up on the LRU list. This is good because
5316 // content providers are often expensive to start.
5317 updateLruProcessLocked(cpr.app, false, true);
5318 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005319 } else {
5320 cpr.externals++;
5321 }
5322
5323 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 updateOomAdjLocked(cpr.app);
5325 }
5326
5327 Binder.restoreCallingIdentity(origId);
5328
5329 } else {
5330 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005331 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005332 resolveContentProvider(name,
5333 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005334 } catch (RemoteException ex) {
5335 }
5336 if (cpi == null) {
5337 return null;
5338 }
5339
Dianne Hackbornb424b632010-08-18 15:59:05 -07005340 String msg;
5341 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5342 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 }
5344
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005345 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005346 && !cpi.processName.equals("system")) {
5347 // If this content provider does not run in the system
5348 // process, and the system is not yet ready to run other
5349 // processes, then fail fast instead of hanging.
5350 throw new IllegalArgumentException(
5351 "Attempt to launch content provider before system ready");
5352 }
5353
Dianne Hackborn860755f2010-06-03 18:47:52 -07005354 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 final boolean firstClass = cpr == null;
5356 if (firstClass) {
5357 try {
5358 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005359 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005360 getApplicationInfo(
5361 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005362 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005364 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365 + cpi.name);
5366 return null;
5367 }
5368 cpr = new ContentProviderRecord(cpi, ai);
5369 } catch (RemoteException ex) {
5370 // pm is in same process, this will never happen.
5371 }
5372 }
5373
5374 if (r != null && cpr.canRunHere(r)) {
5375 // If this is a multiprocess provider, then just return its
5376 // info and allow the caller to instantiate it. Only do
5377 // this if the provider is the same user as the caller's
5378 // process, or can run as root (so can be in any process).
5379 return cpr;
5380 }
5381
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005382 if (DEBUG_PROVIDER) {
5383 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005384 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005385 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005386 }
5387
5388 // This is single process, and our app is now connecting to it.
5389 // See if we are already in the process of launching this
5390 // provider.
5391 final int N = mLaunchingProviders.size();
5392 int i;
5393 for (i=0; i<N; i++) {
5394 if (mLaunchingProviders.get(i) == cpr) {
5395 break;
5396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005397 }
5398
5399 // If the provider is not already being launched, then get it
5400 // started.
5401 if (i >= N) {
5402 final long origId = Binder.clearCallingIdentity();
5403 ProcessRecord proc = startProcessLocked(cpi.processName,
5404 cpr.appInfo, false, 0, "content provider",
5405 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005406 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005407 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005408 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005409 + cpi.applicationInfo.packageName + "/"
5410 + cpi.applicationInfo.uid + " for provider "
5411 + name + ": process is bad");
5412 return null;
5413 }
5414 cpr.launchingApp = proc;
5415 mLaunchingProviders.add(cpr);
5416 Binder.restoreCallingIdentity(origId);
5417 }
5418
5419 // Make sure the provider is published (the same provider class
5420 // may be published under multiple names).
5421 if (firstClass) {
5422 mProvidersByClass.put(cpi.name, cpr);
5423 }
5424 mProvidersByName.put(name, cpr);
5425
5426 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005427 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005428 "Adding provider requested by "
5429 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005430 + cpr.info.processName);
5431 Integer cnt = r.conProviders.get(cpr);
5432 if (cnt == null) {
5433 r.conProviders.put(cpr, new Integer(1));
5434 } else {
5435 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005437 cpr.clients.add(r);
5438 } else {
5439 cpr.externals++;
5440 }
5441 }
5442 }
5443
5444 // Wait for the provider to be published...
5445 synchronized (cpr) {
5446 while (cpr.provider == null) {
5447 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005448 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 + cpi.applicationInfo.packageName + "/"
5450 + cpi.applicationInfo.uid + " for provider "
5451 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005452 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005453 cpi.applicationInfo.packageName,
5454 cpi.applicationInfo.uid, name);
5455 return null;
5456 }
5457 try {
5458 cpr.wait();
5459 } catch (InterruptedException ex) {
5460 }
5461 }
5462 }
5463 return cpr;
5464 }
5465
5466 public final ContentProviderHolder getContentProvider(
5467 IApplicationThread caller, String name) {
5468 if (caller == null) {
5469 String msg = "null IApplicationThread when getting content provider "
5470 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005471 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472 throw new SecurityException(msg);
5473 }
5474
5475 return getContentProviderImpl(caller, name);
5476 }
5477
5478 private ContentProviderHolder getContentProviderExternal(String name) {
5479 return getContentProviderImpl(null, name);
5480 }
5481
5482 /**
5483 * Drop a content provider from a ProcessRecord's bookkeeping
5484 * @param cpr
5485 */
5486 public void removeContentProvider(IApplicationThread caller, String name) {
5487 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005488 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005489 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005490 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005491 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005492 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 return;
5494 }
5495 final ProcessRecord r = getRecordForAppLocked(caller);
5496 if (r == null) {
5497 throw new SecurityException(
5498 "Unable to find app for caller " + caller +
5499 " when removing content provider " + name);
5500 }
5501 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005502 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005503 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005504 + r.info.processName + " from process "
5505 + localCpr.appInfo.processName);
5506 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005507 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005508 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005509 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 return;
5511 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005512 Integer cnt = r.conProviders.get(localCpr);
5513 if (cnt == null || cnt.intValue() <= 1) {
5514 localCpr.clients.remove(r);
5515 r.conProviders.remove(localCpr);
5516 } else {
5517 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 }
5520 updateOomAdjLocked();
5521 }
5522 }
5523
5524 private void removeContentProviderExternal(String name) {
5525 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005526 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527 if(cpr == null) {
5528 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005529 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 return;
5531 }
5532
5533 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005534 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005535 localCpr.externals--;
5536 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005537 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005538 }
5539 updateOomAdjLocked();
5540 }
5541 }
5542
5543 public final void publishContentProviders(IApplicationThread caller,
5544 List<ContentProviderHolder> providers) {
5545 if (providers == null) {
5546 return;
5547 }
5548
5549 synchronized(this) {
5550 final ProcessRecord r = getRecordForAppLocked(caller);
5551 if (r == null) {
5552 throw new SecurityException(
5553 "Unable to find app for caller " + caller
5554 + " (pid=" + Binder.getCallingPid()
5555 + ") when publishing content providers");
5556 }
5557
5558 final long origId = Binder.clearCallingIdentity();
5559
5560 final int N = providers.size();
5561 for (int i=0; i<N; i++) {
5562 ContentProviderHolder src = providers.get(i);
5563 if (src == null || src.info == null || src.provider == null) {
5564 continue;
5565 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005566 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 if (dst != null) {
5568 mProvidersByClass.put(dst.info.name, dst);
5569 String names[] = dst.info.authority.split(";");
5570 for (int j = 0; j < names.length; j++) {
5571 mProvidersByName.put(names[j], dst);
5572 }
5573
5574 int NL = mLaunchingProviders.size();
5575 int j;
5576 for (j=0; j<NL; j++) {
5577 if (mLaunchingProviders.get(j) == dst) {
5578 mLaunchingProviders.remove(j);
5579 j--;
5580 NL--;
5581 }
5582 }
5583 synchronized (dst) {
5584 dst.provider = src.provider;
5585 dst.app = r;
5586 dst.notifyAll();
5587 }
5588 updateOomAdjLocked(r);
5589 }
5590 }
5591
5592 Binder.restoreCallingIdentity(origId);
5593 }
5594 }
5595
5596 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005597 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005598 synchronized (mSelf) {
5599 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5600 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005601 if (providers != null) {
5602 for (int i=providers.size()-1; i>=0; i--) {
5603 ProviderInfo pi = (ProviderInfo)providers.get(i);
5604 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5605 Slog.w(TAG, "Not installing system proc provider " + pi.name
5606 + ": not system .apk");
5607 providers.remove(i);
5608 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005609 }
5610 }
5611 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005612 if (providers != null) {
5613 mSystemThread.installSystemProviders(providers);
5614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615 }
5616
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005617 /**
5618 * Allows app to retrieve the MIME type of a URI without having permission
5619 * to access its content provider.
5620 *
5621 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5622 *
5623 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5624 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5625 */
5626 public String getProviderMimeType(Uri uri) {
5627 final String name = uri.getAuthority();
5628 final long ident = Binder.clearCallingIdentity();
5629 ContentProviderHolder holder = null;
5630
5631 try {
5632 holder = getContentProviderExternal(name);
5633 if (holder != null) {
5634 return holder.provider.getType(uri);
5635 }
5636 } catch (RemoteException e) {
5637 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5638 return null;
5639 } finally {
5640 if (holder != null) {
5641 removeContentProviderExternal(name);
5642 }
5643 Binder.restoreCallingIdentity(ident);
5644 }
5645
5646 return null;
5647 }
5648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 // =========================================================
5650 // GLOBAL MANAGEMENT
5651 // =========================================================
5652
5653 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5654 ApplicationInfo info, String customProcess) {
5655 String proc = customProcess != null ? customProcess : info.processName;
5656 BatteryStatsImpl.Uid.Proc ps = null;
5657 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5658 synchronized (stats) {
5659 ps = stats.getProcessStatsLocked(info.uid, proc);
5660 }
5661 return new ProcessRecord(ps, thread, info, proc);
5662 }
5663
5664 final ProcessRecord addAppLocked(ApplicationInfo info) {
5665 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5666
5667 if (app == null) {
5668 app = newProcessRecordLocked(null, info, null);
5669 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005670 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 }
5672
5673 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5674 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5675 app.persistent = true;
5676 app.maxAdj = CORE_SERVER_ADJ;
5677 }
5678 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5679 mPersistentStartingProcesses.add(app);
5680 startProcessLocked(app, "added application", app.processName);
5681 }
5682
5683 return app;
5684 }
5685
5686 public void unhandledBack() {
5687 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5688 "unhandledBack()");
5689
5690 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005691 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005692 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005693 TAG, "Performing unhandledBack(): stack size = " + count);
5694 if (count > 1) {
5695 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005696 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005697 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5698 Binder.restoreCallingIdentity(origId);
5699 }
5700 }
5701 }
5702
5703 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5704 String name = uri.getAuthority();
5705 ContentProviderHolder cph = getContentProviderExternal(name);
5706 ParcelFileDescriptor pfd = null;
5707 if (cph != null) {
5708 // We record the binder invoker's uid in thread-local storage before
5709 // going to the content provider to open the file. Later, in the code
5710 // that handles all permissions checks, we look for this uid and use
5711 // that rather than the Activity Manager's own uid. The effect is that
5712 // we do the check against the caller's permissions even though it looks
5713 // to the content provider like the Activity Manager itself is making
5714 // the request.
5715 sCallerIdentity.set(new Identity(
5716 Binder.getCallingPid(), Binder.getCallingUid()));
5717 try {
5718 pfd = cph.provider.openFile(uri, "r");
5719 } catch (FileNotFoundException e) {
5720 // do nothing; pfd will be returned null
5721 } finally {
5722 // Ensure that whatever happens, we clean up the identity state
5723 sCallerIdentity.remove();
5724 }
5725
5726 // We've got the fd now, so we're done with the provider.
5727 removeContentProviderExternal(name);
5728 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005729 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 }
5731 return pfd;
5732 }
5733
5734 public void goingToSleep() {
5735 synchronized(this) {
5736 mSleeping = true;
5737 mWindowManager.setEventDispatching(false);
5738
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005739 if (mMainStack.mResumedActivity != null) {
5740 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005741 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005742 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005743 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005744
5745 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005746 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005747 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5748 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005749 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005750 }
5751 }
5752
Dianne Hackborn55280a92009-05-07 15:53:46 -07005753 public boolean shutdown(int timeout) {
5754 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5755 != PackageManager.PERMISSION_GRANTED) {
5756 throw new SecurityException("Requires permission "
5757 + android.Manifest.permission.SHUTDOWN);
5758 }
5759
5760 boolean timedout = false;
5761
5762 synchronized(this) {
5763 mShuttingDown = true;
5764 mWindowManager.setEventDispatching(false);
5765
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005766 if (mMainStack.mResumedActivity != null) {
5767 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005768 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005769 while (mMainStack.mResumedActivity != null
5770 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005771 long delay = endTime - System.currentTimeMillis();
5772 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005773 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005774 timedout = true;
5775 break;
5776 }
5777 try {
5778 this.wait();
5779 } catch (InterruptedException e) {
5780 }
5781 }
5782 }
5783 }
5784
5785 mUsageStatsService.shutdown();
5786 mBatteryStatsService.shutdown();
5787
5788 return timedout;
5789 }
5790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 public void wakingUp() {
5792 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005793 if (mMainStack.mGoingToSleep.isHeld()) {
5794 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005795 }
5796 mWindowManager.setEventDispatching(true);
5797 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005798 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005799 }
5800 }
5801
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005802 public void stopAppSwitches() {
5803 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5804 != PackageManager.PERMISSION_GRANTED) {
5805 throw new SecurityException("Requires permission "
5806 + android.Manifest.permission.STOP_APP_SWITCHES);
5807 }
5808
5809 synchronized(this) {
5810 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5811 + APP_SWITCH_DELAY_TIME;
5812 mDidAppSwitch = false;
5813 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5814 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5815 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5816 }
5817 }
5818
5819 public void resumeAppSwitches() {
5820 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5821 != PackageManager.PERMISSION_GRANTED) {
5822 throw new SecurityException("Requires permission "
5823 + android.Manifest.permission.STOP_APP_SWITCHES);
5824 }
5825
5826 synchronized(this) {
5827 // Note that we don't execute any pending app switches... we will
5828 // let those wait until either the timeout, or the next start
5829 // activity request.
5830 mAppSwitchesAllowedTime = 0;
5831 }
5832 }
5833
5834 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5835 String name) {
5836 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5837 return true;
5838 }
5839
5840 final int perm = checkComponentPermission(
5841 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5842 callingUid, -1);
5843 if (perm == PackageManager.PERMISSION_GRANTED) {
5844 return true;
5845 }
5846
Joe Onorato8a9b2202010-02-26 18:56:32 -08005847 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005848 return false;
5849 }
5850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 public void setDebugApp(String packageName, boolean waitForDebugger,
5852 boolean persistent) {
5853 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5854 "setDebugApp()");
5855
5856 // Note that this is not really thread safe if there are multiple
5857 // callers into it at the same time, but that's not a situation we
5858 // care about.
5859 if (persistent) {
5860 final ContentResolver resolver = mContext.getContentResolver();
5861 Settings.System.putString(
5862 resolver, Settings.System.DEBUG_APP,
5863 packageName);
5864 Settings.System.putInt(
5865 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5866 waitForDebugger ? 1 : 0);
5867 }
5868
5869 synchronized (this) {
5870 if (!persistent) {
5871 mOrigDebugApp = mDebugApp;
5872 mOrigWaitForDebugger = mWaitForDebugger;
5873 }
5874 mDebugApp = packageName;
5875 mWaitForDebugger = waitForDebugger;
5876 mDebugTransient = !persistent;
5877 if (packageName != null) {
5878 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005879 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005880 Binder.restoreCallingIdentity(origId);
5881 }
5882 }
5883 }
5884
5885 public void setAlwaysFinish(boolean enabled) {
5886 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5887 "setAlwaysFinish()");
5888
5889 Settings.System.putInt(
5890 mContext.getContentResolver(),
5891 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5892
5893 synchronized (this) {
5894 mAlwaysFinishActivities = enabled;
5895 }
5896 }
5897
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005898 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005899 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005900 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005901 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005902 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005903 }
5904 }
5905
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005906 public boolean isUserAMonkey() {
5907 // For now the fact that there is a controller implies
5908 // we have a monkey.
5909 synchronized (this) {
5910 return mController != null;
5911 }
5912 }
5913
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005914 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005915 synchronized (this) {
5916 mWatchers.register(watcher);
5917 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005918 }
5919
5920 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005921 synchronized (this) {
5922 mWatchers.unregister(watcher);
5923 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005924 }
5925
Daniel Sandler69a48172010-06-23 16:29:36 -04005926 public void setImmersive(IBinder token, boolean immersive) {
5927 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005928 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005929 if (index < 0) {
5930 throw new IllegalArgumentException();
5931 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005932 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005933 r.immersive = immersive;
5934 }
5935 }
5936
5937 public boolean isImmersive(IBinder token) {
5938 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005939 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005940 if (index < 0) {
5941 throw new IllegalArgumentException();
5942 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005943 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005944 return r.immersive;
5945 }
5946 }
5947
5948 public boolean isTopActivityImmersive() {
5949 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005950 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005951 return (r != null) ? r.immersive : false;
5952 }
5953 }
5954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 public final void enterSafeMode() {
5956 synchronized(this) {
5957 // It only makes sense to do this before the system is ready
5958 // and started launching other packages.
5959 if (!mSystemReady) {
5960 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005961 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 } catch (RemoteException e) {
5963 }
5964
5965 View v = LayoutInflater.from(mContext).inflate(
5966 com.android.internal.R.layout.safe_mode, null);
5967 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown3b2b3542010-10-15 00:54:27 -07005968 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005969 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5970 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5971 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5972 lp.format = v.getBackground().getOpacity();
5973 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5974 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5975 ((WindowManager)mContext.getSystemService(
5976 Context.WINDOW_SERVICE)).addView(v, lp);
5977 }
5978 }
5979 }
5980
5981 public void noteWakeupAlarm(IIntentSender sender) {
5982 if (!(sender instanceof PendingIntentRecord)) {
5983 return;
5984 }
5985 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5986 synchronized (stats) {
5987 if (mBatteryStatsService.isOnBattery()) {
5988 mBatteryStatsService.enforceCallingPermission();
5989 PendingIntentRecord rec = (PendingIntentRecord)sender;
5990 int MY_UID = Binder.getCallingUid();
5991 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5992 BatteryStatsImpl.Uid.Pkg pkg =
5993 stats.getPackageStatsLocked(uid, rec.key.packageName);
5994 pkg.incWakeupsLocked();
5995 }
5996 }
5997 }
5998
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005999 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006000 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006001 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006002 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006003 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006004 // XXX Note: don't acquire main activity lock here, because the window
6005 // manager calls in with its locks held.
6006
6007 boolean killed = false;
6008 synchronized (mPidsSelfLocked) {
6009 int[] types = new int[pids.length];
6010 int worstType = 0;
6011 for (int i=0; i<pids.length; i++) {
6012 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6013 if (proc != null) {
6014 int type = proc.setAdj;
6015 types[i] = type;
6016 if (type > worstType) {
6017 worstType = type;
6018 }
6019 }
6020 }
6021
6022 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6023 // then constrain it so we will kill all hidden procs.
6024 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6025 worstType = HIDDEN_APP_MIN_ADJ;
6026 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006027 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006028 for (int i=0; i<pids.length; i++) {
6029 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6030 if (proc == null) {
6031 continue;
6032 }
6033 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006034 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006035 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006036 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6037 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006039 proc.killedBackground = true;
6040 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 }
6042 }
6043 }
6044 return killed;
6045 }
6046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 public final void startRunning(String pkg, String cls, String action,
6048 String data) {
6049 synchronized(this) {
6050 if (mStartRunning) {
6051 return;
6052 }
6053 mStartRunning = true;
6054 mTopComponent = pkg != null && cls != null
6055 ? new ComponentName(pkg, cls) : null;
6056 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6057 mTopData = data;
6058 if (!mSystemReady) {
6059 return;
6060 }
6061 }
6062
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006063 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006064 }
6065
6066 private void retrieveSettings() {
6067 final ContentResolver resolver = mContext.getContentResolver();
6068 String debugApp = Settings.System.getString(
6069 resolver, Settings.System.DEBUG_APP);
6070 boolean waitForDebugger = Settings.System.getInt(
6071 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6072 boolean alwaysFinishActivities = Settings.System.getInt(
6073 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6074
6075 Configuration configuration = new Configuration();
6076 Settings.System.getConfiguration(resolver, configuration);
6077
6078 synchronized (this) {
6079 mDebugApp = mOrigDebugApp = debugApp;
6080 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6081 mAlwaysFinishActivities = alwaysFinishActivities;
6082 // This happens before any activities are started, so we can
6083 // change mConfiguration in-place.
6084 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006085 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006086 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006087 }
6088 }
6089
6090 public boolean testIsSystemReady() {
6091 // no need to synchronize(this) just to read & return the value
6092 return mSystemReady;
6093 }
6094
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006095 private static File getCalledPreBootReceiversFile() {
6096 File dataDir = Environment.getDataDirectory();
6097 File systemDir = new File(dataDir, "system");
6098 File fname = new File(systemDir, "called_pre_boots.dat");
6099 return fname;
6100 }
6101
6102 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6103 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6104 File file = getCalledPreBootReceiversFile();
6105 FileInputStream fis = null;
6106 try {
6107 fis = new FileInputStream(file);
6108 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6109 int vers = dis.readInt();
6110 String codename = dis.readUTF();
6111 if (vers == android.os.Build.VERSION.SDK_INT
6112 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6113 int num = dis.readInt();
6114 while (num > 0) {
6115 num--;
6116 String pkg = dis.readUTF();
6117 String cls = dis.readUTF();
6118 lastDoneReceivers.add(new ComponentName(pkg, cls));
6119 }
6120 }
6121 } catch (FileNotFoundException e) {
6122 } catch (IOException e) {
6123 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6124 } finally {
6125 if (fis != null) {
6126 try {
6127 fis.close();
6128 } catch (IOException e) {
6129 }
6130 }
6131 }
6132 return lastDoneReceivers;
6133 }
6134
6135 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6136 File file = getCalledPreBootReceiversFile();
6137 FileOutputStream fos = null;
6138 DataOutputStream dos = null;
6139 try {
6140 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6141 fos = new FileOutputStream(file);
6142 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6143 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6144 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6145 dos.writeInt(list.size());
6146 for (int i=0; i<list.size(); i++) {
6147 dos.writeUTF(list.get(i).getPackageName());
6148 dos.writeUTF(list.get(i).getClassName());
6149 }
6150 } catch (IOException e) {
6151 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6152 file.delete();
6153 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006154 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006155 if (dos != null) {
6156 try {
6157 dos.close();
6158 } catch (IOException e) {
6159 // TODO Auto-generated catch block
6160 e.printStackTrace();
6161 }
6162 }
6163 }
6164 }
6165
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006166 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167 // In the simulator, startRunning will never have been called, which
6168 // normally sets a few crucial variables. Do it here instead.
6169 if (!Process.supportsProcesses()) {
6170 mStartRunning = true;
6171 mTopAction = Intent.ACTION_MAIN;
6172 }
6173
6174 synchronized(this) {
6175 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006176 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006177 return;
6178 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006179
6180 // Check to see if there are any update receivers to run.
6181 if (!mDidUpdate) {
6182 if (mWaitingUpdate) {
6183 return;
6184 }
6185 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6186 List<ResolveInfo> ris = null;
6187 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006188 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006189 intent, null, 0);
6190 } catch (RemoteException e) {
6191 }
6192 if (ris != null) {
6193 for (int i=ris.size()-1; i>=0; i--) {
6194 if ((ris.get(i).activityInfo.applicationInfo.flags
6195 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6196 ris.remove(i);
6197 }
6198 }
6199 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006200
6201 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6202
6203 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006204 for (int i=0; i<ris.size(); i++) {
6205 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006206 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6207 if (lastDoneReceivers.contains(comp)) {
6208 ris.remove(i);
6209 i--;
6210 }
6211 }
6212
6213 for (int i=0; i<ris.size(); i++) {
6214 ActivityInfo ai = ris.get(i).activityInfo;
6215 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6216 doneReceivers.add(comp);
6217 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006218 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006219 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006220 finisher = new IIntentReceiver.Stub() {
6221 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006222 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006223 boolean sticky) {
6224 // The raw IIntentReceiver interface is called
6225 // with the AM lock held, so redispatch to
6226 // execute our code without the lock.
6227 mHandler.post(new Runnable() {
6228 public void run() {
6229 synchronized (ActivityManagerService.this) {
6230 mDidUpdate = true;
6231 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006232 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006233 systemReady(goingCallback);
6234 }
6235 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006236 }
6237 };
6238 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006239 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006240 broadcastIntentLocked(null, null, intent, null, finisher,
6241 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006242 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006243 mWaitingUpdate = true;
6244 }
6245 }
6246 }
6247 if (mWaitingUpdate) {
6248 return;
6249 }
6250 mDidUpdate = true;
6251 }
6252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006253 mSystemReady = true;
6254 if (!mStartRunning) {
6255 return;
6256 }
6257 }
6258
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006259 ArrayList<ProcessRecord> procsToKill = null;
6260 synchronized(mPidsSelfLocked) {
6261 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6262 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6263 if (!isAllowedWhileBooting(proc.info)){
6264 if (procsToKill == null) {
6265 procsToKill = new ArrayList<ProcessRecord>();
6266 }
6267 procsToKill.add(proc);
6268 }
6269 }
6270 }
6271
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006272 synchronized(this) {
6273 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006274 for (int i=procsToKill.size()-1; i>=0; i--) {
6275 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006276 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006277 removeProcessLocked(proc, true);
6278 }
6279 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006280
6281 // Now that we have cleaned up any update processes, we
6282 // are ready to start launching real processes and know that
6283 // we won't trample on them any more.
6284 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006285 }
6286
Joe Onorato8a9b2202010-02-26 18:56:32 -08006287 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006288 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289 SystemClock.uptimeMillis());
6290
6291 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006292 // Make sure we have no pre-ready processes sitting around.
6293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006294 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6295 ResolveInfo ri = mContext.getPackageManager()
6296 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006297 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006298 CharSequence errorMsg = null;
6299 if (ri != null) {
6300 ActivityInfo ai = ri.activityInfo;
6301 ApplicationInfo app = ai.applicationInfo;
6302 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6303 mTopAction = Intent.ACTION_FACTORY_TEST;
6304 mTopData = null;
6305 mTopComponent = new ComponentName(app.packageName,
6306 ai.name);
6307 } else {
6308 errorMsg = mContext.getResources().getText(
6309 com.android.internal.R.string.factorytest_not_system);
6310 }
6311 } else {
6312 errorMsg = mContext.getResources().getText(
6313 com.android.internal.R.string.factorytest_no_action);
6314 }
6315 if (errorMsg != null) {
6316 mTopAction = null;
6317 mTopData = null;
6318 mTopComponent = null;
6319 Message msg = Message.obtain();
6320 msg.what = SHOW_FACTORY_ERROR_MSG;
6321 msg.getData().putCharSequence("msg", errorMsg);
6322 mHandler.sendMessage(msg);
6323 }
6324 }
6325 }
6326
6327 retrieveSettings();
6328
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006329 if (goingCallback != null) goingCallback.run();
6330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 synchronized (this) {
6332 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6333 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006334 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006335 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006336 if (apps != null) {
6337 int N = apps.size();
6338 int i;
6339 for (i=0; i<N; i++) {
6340 ApplicationInfo info
6341 = (ApplicationInfo)apps.get(i);
6342 if (info != null &&
6343 !info.packageName.equals("android")) {
6344 addAppLocked(info);
6345 }
6346 }
6347 }
6348 } catch (RemoteException ex) {
6349 // pm is in same process, this will never happen.
6350 }
6351 }
6352
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006353 // Start up initial activity.
6354 mBooting = true;
6355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006357 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006358 Message msg = Message.obtain();
6359 msg.what = SHOW_UID_ERROR_MSG;
6360 mHandler.sendMessage(msg);
6361 }
6362 } catch (RemoteException e) {
6363 }
6364
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006365 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006366 }
6367 }
6368
Dan Egnorb7f03672009-12-09 16:22:32 -08006369 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006370 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006371 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006372 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006373 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 startAppProblemLocked(app);
6375 app.stopFreezingAllLocked();
6376 return handleAppCrashLocked(app);
6377 }
6378
Dan Egnorb7f03672009-12-09 16:22:32 -08006379 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006380 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006381 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006382 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006383 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6384 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006385 startAppProblemLocked(app);
6386 app.stopFreezingAllLocked();
6387 }
6388
6389 /**
6390 * Generate a process error record, suitable for attachment to a ProcessRecord.
6391 *
6392 * @param app The ProcessRecord in which the error occurred.
6393 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6394 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006395 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006396 * @param shortMsg Short message describing the crash.
6397 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006398 * @param stackTrace Full crash stack trace, may be null.
6399 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006400 * @return Returns a fully-formed AppErrorStateInfo record.
6401 */
6402 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006403 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006404 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006406 report.condition = condition;
6407 report.processName = app.processName;
6408 report.pid = app.pid;
6409 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006410 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006411 report.shortMsg = shortMsg;
6412 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006413 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006414
6415 return report;
6416 }
6417
Dan Egnor42471dd2010-01-07 17:25:22 -08006418 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006419 synchronized (this) {
6420 app.crashing = false;
6421 app.crashingReport = null;
6422 app.notResponding = false;
6423 app.notRespondingReport = null;
6424 if (app.anrDialog == fromDialog) {
6425 app.anrDialog = null;
6426 }
6427 if (app.waitDialog == fromDialog) {
6428 app.waitDialog = null;
6429 }
6430 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006431 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006432 Slog.i(ActivityManagerService.TAG, "Killing "
6433 + app.processName + " (pid=" + app.pid + "): user's request");
6434 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6435 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006436 Process.killProcess(app.pid);
6437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006438 }
6439 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006440
Dan Egnorb7f03672009-12-09 16:22:32 -08006441 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 long now = SystemClock.uptimeMillis();
6443
6444 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6445 app.info.uid);
6446 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6447 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006448 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006449 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006450 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451 app.info.processName, app.info.uid);
6452 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006453 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6454 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006455 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006456 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006457 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006458 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006459 }
6460 }
6461 if (!app.persistent) {
6462 // We don't want to start this process again until the user
6463 // explicitly does so... but for persistent process, we really
6464 // need to keep it running. If a persistent process is actually
6465 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006466 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 app.info.processName);
6468 mBadProcesses.put(app.info.processName, app.info.uid, now);
6469 app.bad = true;
6470 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6471 app.removed = true;
6472 removeProcessLocked(app, false);
6473 return false;
6474 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006475 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006476 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006477 if (r.app == app) {
6478 // If the top running activity is from this crashing
6479 // process, then terminate it to avoid getting in a loop.
6480 Slog.w(TAG, " Force finishing activity "
6481 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006482 int index = mMainStack.indexOfTokenLocked(r);
6483 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006484 Activity.RESULT_CANCELED, null, "crashed");
6485 // Also terminate an activities below it that aren't yet
6486 // stopped, to avoid a situation where one will get
6487 // re-start our crashing activity once it gets resumed again.
6488 index--;
6489 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006490 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006491 if (r.state == ActivityState.RESUMED
6492 || r.state == ActivityState.PAUSING
6493 || r.state == ActivityState.PAUSED) {
6494 if (!r.isHomeActivity) {
6495 Slog.w(TAG, " Force finishing activity "
6496 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006497 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006498 Activity.RESULT_CANCELED, null, "crashed");
6499 }
6500 }
6501 }
6502 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006503 }
6504
6505 // Bump up the crash count of any services currently running in the proc.
6506 if (app.services.size() != 0) {
6507 // Any services running in the application need to be placed
6508 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006509 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006510 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006511 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006512 sr.crashCount++;
6513 }
6514 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006515
6516 // If the crashing process is what we consider to be the "home process" and it has been
6517 // replaced by a third-party app, clear the package preferred activities from packages
6518 // with a home activity running in the process to prevent a repeatedly crashing app
6519 // from blocking the user to manually clear the list.
6520 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6521 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6522 Iterator it = mHomeProcess.activities.iterator();
6523 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006524 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006525 if (r.isHomeActivity) {
6526 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6527 try {
6528 ActivityThread.getPackageManager()
6529 .clearPackagePreferredActivities(r.packageName);
6530 } catch (RemoteException c) {
6531 // pm is in same process, this will never happen.
6532 }
6533 }
6534 }
6535 }
6536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006537 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6538 return true;
6539 }
6540
6541 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006542 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6543 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006544 skipCurrentReceiverLocked(app);
6545 }
6546
6547 void skipCurrentReceiverLocked(ProcessRecord app) {
6548 boolean reschedule = false;
6549 BroadcastRecord r = app.curReceiver;
6550 if (r != null) {
6551 // The current broadcast is waiting for this app's receiver
6552 // to be finished. Looks like that's not going to happen, so
6553 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006554 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006555 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6556 r.resultExtras, r.resultAbort, true);
6557 reschedule = true;
6558 }
6559 r = mPendingBroadcast;
6560 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006561 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006562 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006563 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6565 r.resultExtras, r.resultAbort, true);
6566 reschedule = true;
6567 }
6568 if (reschedule) {
6569 scheduleBroadcastsLocked();
6570 }
6571 }
6572
Dan Egnor60d87622009-12-16 16:32:58 -08006573 /**
6574 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6575 * The application process will exit immediately after this call returns.
6576 * @param app object of the crashing app, null for the system server
6577 * @param crashInfo describing the exception
6578 */
6579 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6580 ProcessRecord r = findAppProcess(app);
6581
6582 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6583 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006584 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006585 crashInfo.exceptionClassName,
6586 crashInfo.exceptionMessage,
6587 crashInfo.throwFileName,
6588 crashInfo.throwLineNumber);
6589
Dan Egnor42471dd2010-01-07 17:25:22 -08006590 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006591
6592 crashApplication(r, crashInfo);
6593 }
6594
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006595 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006596 IBinder app,
6597 int violationMask,
6598 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006599 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006600
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006601 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006602 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006603 boolean logIt = true;
6604 synchronized (mAlreadyLoggedViolatedStacks) {
6605 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6606 logIt = false;
6607 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006608 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006609 // the relative pain numbers, without logging all
6610 // the stack traces repeatedly. We'd want to do
6611 // likewise in the client code, which also does
6612 // dup suppression, before the Binder call.
6613 } else {
6614 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6615 mAlreadyLoggedViolatedStacks.clear();
6616 }
6617 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6618 }
6619 }
6620 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006621 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006622 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006623 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006624
6625 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6626 AppErrorResult result = new AppErrorResult();
6627 synchronized (this) {
6628 final long origId = Binder.clearCallingIdentity();
6629
6630 Message msg = Message.obtain();
6631 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6632 HashMap<String, Object> data = new HashMap<String, Object>();
6633 data.put("result", result);
6634 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006635 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006636 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006637 msg.obj = data;
6638 mHandler.sendMessage(msg);
6639
6640 Binder.restoreCallingIdentity(origId);
6641 }
6642 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006643 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006644 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006645 }
6646
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006647 // Depending on the policy in effect, there could be a bunch of
6648 // these in quick succession so we try to batch these together to
6649 // minimize disk writes, number of dropbox entries, and maximize
6650 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006651 private void logStrictModeViolationToDropBox(
6652 ProcessRecord process,
6653 StrictMode.ViolationInfo info) {
6654 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006655 return;
6656 }
6657 final boolean isSystemApp = process == null ||
6658 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6659 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6660 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6661 final DropBoxManager dbox = (DropBoxManager)
6662 mContext.getSystemService(Context.DROPBOX_SERVICE);
6663
6664 // Exit early if the dropbox isn't configured to accept this report type.
6665 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6666
6667 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006668 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006669 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6670 synchronized (sb) {
6671 bufferWasEmpty = sb.length() == 0;
6672 appendDropBoxProcessHeaders(process, sb);
6673 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6674 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006675 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6676 if (info.violationNumThisLoop != 0) {
6677 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6678 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006679 if (info.numAnimationsRunning != 0) {
6680 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6681 }
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006682 if (info != null && info.durationMillis != -1) {
6683 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006684 }
6685 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006686 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6687 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006688 }
6689 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006690
6691 // Only buffer up to ~64k. Various logging bits truncate
6692 // things at 128k.
6693 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006694 }
6695
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006696 // Flush immediately if the buffer's grown too large, or this
6697 // is a non-system app. Non-system apps are isolated with a
6698 // different tag & policy and not batched.
6699 //
6700 // Batching is useful during internal testing with
6701 // StrictMode settings turned up high. Without batching,
6702 // thousands of separate files could be created on boot.
6703 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006704 new Thread("Error dump: " + dropboxTag) {
6705 @Override
6706 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006707 String report;
6708 synchronized (sb) {
6709 report = sb.toString();
6710 sb.delete(0, sb.length());
6711 sb.trimToSize();
6712 }
6713 if (report.length() != 0) {
6714 dbox.addText(dropboxTag, report);
6715 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006716 }
6717 }.start();
6718 return;
6719 }
6720
6721 // System app batching:
6722 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006723 // An existing dropbox-writing thread is outstanding, so
6724 // we don't need to start it up. The existing thread will
6725 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006726 return;
6727 }
6728
6729 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6730 // (After this point, we shouldn't access AMS internal data structures.)
6731 new Thread("Error dump: " + dropboxTag) {
6732 @Override
6733 public void run() {
6734 // 5 second sleep to let stacks arrive and be batched together
6735 try {
6736 Thread.sleep(5000); // 5 seconds
6737 } catch (InterruptedException e) {}
6738
6739 String errorReport;
6740 synchronized (mStrictModeBuffer) {
6741 errorReport = mStrictModeBuffer.toString();
6742 if (errorReport.length() == 0) {
6743 return;
6744 }
6745 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6746 mStrictModeBuffer.trimToSize();
6747 }
6748 dbox.addText(dropboxTag, errorReport);
6749 }
6750 }.start();
6751 }
6752
Dan Egnor60d87622009-12-16 16:32:58 -08006753 /**
6754 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6755 * @param app object of the crashing app, null for the system server
6756 * @param tag reported by the caller
6757 * @param crashInfo describing the context of the error
6758 * @return true if the process should exit immediately (WTF is fatal)
6759 */
6760 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006761 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006762 ProcessRecord r = findAppProcess(app);
6763
6764 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6765 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006766 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006767 tag, crashInfo.exceptionMessage);
6768
Dan Egnor42471dd2010-01-07 17:25:22 -08006769 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006770
Doug Zongker43866e02010-01-07 12:09:54 -08006771 if (Settings.Secure.getInt(mContext.getContentResolver(),
6772 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006773 crashApplication(r, crashInfo);
6774 return true;
6775 } else {
6776 return false;
6777 }
6778 }
6779
6780 /**
6781 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6782 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6783 */
6784 private ProcessRecord findAppProcess(IBinder app) {
6785 if (app == null) {
6786 return null;
6787 }
6788
6789 synchronized (this) {
6790 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6791 final int NA = apps.size();
6792 for (int ia=0; ia<NA; ia++) {
6793 ProcessRecord p = apps.valueAt(ia);
6794 if (p.thread != null && p.thread.asBinder() == app) {
6795 return p;
6796 }
6797 }
6798 }
6799
Joe Onorato8a9b2202010-02-26 18:56:32 -08006800 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006801 return null;
6802 }
6803 }
6804
6805 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006806 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6807 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006808 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006809 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6810 // Note: ProcessRecord 'process' is guarded by the service
6811 // instance. (notably process.pkgList, which could otherwise change
6812 // concurrently during execution of this method)
6813 synchronized (this) {
6814 if (process == null || process.pid == MY_PID) {
6815 sb.append("Process: system_server\n");
6816 } else {
6817 sb.append("Process: ").append(process.processName).append("\n");
6818 }
6819 if (process == null) {
6820 return;
6821 }
Dan Egnora455d192010-03-12 08:52:28 -08006822 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006823 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006824 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6825 for (String pkg : process.pkgList) {
6826 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006827 try {
Dan Egnora455d192010-03-12 08:52:28 -08006828 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6829 if (pi != null) {
6830 sb.append(" v").append(pi.versionCode);
6831 if (pi.versionName != null) {
6832 sb.append(" (").append(pi.versionName).append(")");
6833 }
6834 }
6835 } catch (RemoteException e) {
6836 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006837 }
Dan Egnora455d192010-03-12 08:52:28 -08006838 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006839 }
Dan Egnora455d192010-03-12 08:52:28 -08006840 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006841 }
6842
6843 private static String processClass(ProcessRecord process) {
6844 if (process == null || process.pid == MY_PID) {
6845 return "system_server";
6846 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6847 return "system_app";
6848 } else {
6849 return "data_app";
6850 }
6851 }
6852
6853 /**
6854 * Write a description of an error (crash, WTF, ANR) to the drop box.
6855 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6856 * @param process which caused the error, null means the system server
6857 * @param activity which triggered the error, null if unknown
6858 * @param parent activity related to the error, null if unknown
6859 * @param subject line related to the error, null if absent
6860 * @param report in long form describing the error, null if absent
6861 * @param logFile to include in the report, null if none
6862 * @param crashInfo giving an application stack trace, null if absent
6863 */
6864 public void addErrorToDropBox(String eventType,
6865 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6866 final String report, final File logFile,
6867 final ApplicationErrorReport.CrashInfo crashInfo) {
6868 // NOTE -- this must never acquire the ActivityManagerService lock,
6869 // otherwise the watchdog may be prevented from resetting the system.
6870
6871 final String dropboxTag = processClass(process) + "_" + eventType;
6872 final DropBoxManager dbox = (DropBoxManager)
6873 mContext.getSystemService(Context.DROPBOX_SERVICE);
6874
6875 // Exit early if the dropbox isn't configured to accept this report type.
6876 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6877
6878 final StringBuilder sb = new StringBuilder(1024);
6879 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006880 if (activity != null) {
6881 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6882 }
6883 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6884 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6885 }
6886 if (parent != null && parent != activity) {
6887 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6888 }
6889 if (subject != null) {
6890 sb.append("Subject: ").append(subject).append("\n");
6891 }
6892 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02006893 if (Debug.isDebuggerConnected()) {
6894 sb.append("Debugger: Connected\n");
6895 }
Dan Egnora455d192010-03-12 08:52:28 -08006896 sb.append("\n");
6897
6898 // Do the rest in a worker thread to avoid blocking the caller on I/O
6899 // (After this point, we shouldn't access AMS internal data structures.)
6900 Thread worker = new Thread("Error dump: " + dropboxTag) {
6901 @Override
6902 public void run() {
6903 if (report != null) {
6904 sb.append(report);
6905 }
6906 if (logFile != null) {
6907 try {
6908 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6909 } catch (IOException e) {
6910 Slog.e(TAG, "Error reading " + logFile, e);
6911 }
6912 }
6913 if (crashInfo != null && crashInfo.stackTrace != null) {
6914 sb.append(crashInfo.stackTrace);
6915 }
6916
6917 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6918 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6919 if (lines > 0) {
6920 sb.append("\n");
6921
6922 // Merge several logcat streams, and take the last N lines
6923 InputStreamReader input = null;
6924 try {
6925 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6926 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6927 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6928
6929 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6930 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6931 input = new InputStreamReader(logcat.getInputStream());
6932
6933 int num;
6934 char[] buf = new char[8192];
6935 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6936 } catch (IOException e) {
6937 Slog.e(TAG, "Error running logcat", e);
6938 } finally {
6939 if (input != null) try { input.close(); } catch (IOException e) {}
6940 }
6941 }
6942
6943 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006944 }
Dan Egnora455d192010-03-12 08:52:28 -08006945 };
6946
6947 if (process == null || process.pid == MY_PID) {
6948 worker.run(); // We may be about to die -- need to run this synchronously
6949 } else {
6950 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006951 }
6952 }
6953
6954 /**
6955 * Bring up the "unexpected error" dialog box for a crashing app.
6956 * Deal with edge cases (intercepts from instrumented applications,
6957 * ActivityController, error intent receivers, that sort of thing).
6958 * @param r the application crashing
6959 * @param crashInfo describing the failure
6960 */
6961 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006962 long timeMillis = System.currentTimeMillis();
6963 String shortMsg = crashInfo.exceptionClassName;
6964 String longMsg = crashInfo.exceptionMessage;
6965 String stackTrace = crashInfo.stackTrace;
6966 if (shortMsg != null && longMsg != null) {
6967 longMsg = shortMsg + ": " + longMsg;
6968 } else if (shortMsg != null) {
6969 longMsg = shortMsg;
6970 }
6971
Dan Egnor60d87622009-12-16 16:32:58 -08006972 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006973 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006974 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006975 try {
6976 String name = r != null ? r.processName : null;
6977 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006978 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006979 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006980 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006981 + " at watcher's request");
6982 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006983 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006984 }
6985 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006986 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006987 }
6988 }
6989
6990 final long origId = Binder.clearCallingIdentity();
6991
6992 // If this process is running instrumentation, finish it.
6993 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006994 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006995 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006996 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6997 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006998 Bundle info = new Bundle();
6999 info.putString("shortMsg", shortMsg);
7000 info.putString("longMsg", longMsg);
7001 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7002 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007003 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007004 }
7005
Dan Egnor60d87622009-12-16 16:32:58 -08007006 // If we can't identify the process or it's already exceeded its crash quota,
7007 // quit right away without showing a crash dialog.
7008 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007009 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007010 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007011 }
7012
7013 Message msg = Message.obtain();
7014 msg.what = SHOW_ERROR_MSG;
7015 HashMap data = new HashMap();
7016 data.put("result", result);
7017 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007018 msg.obj = data;
7019 mHandler.sendMessage(msg);
7020
7021 Binder.restoreCallingIdentity(origId);
7022 }
7023
7024 int res = result.get();
7025
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007026 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007027 synchronized (this) {
7028 if (r != null) {
7029 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7030 SystemClock.uptimeMillis());
7031 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007032 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007033 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007034 }
7035 }
7036
7037 if (appErrorIntent != null) {
7038 try {
7039 mContext.startActivity(appErrorIntent);
7040 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007041 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007044 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007045
7046 Intent createAppErrorIntentLocked(ProcessRecord r,
7047 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7048 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007049 if (report == null) {
7050 return null;
7051 }
7052 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7053 result.setComponent(r.errorReportReceiver);
7054 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7055 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7056 return result;
7057 }
7058
Dan Egnorb7f03672009-12-09 16:22:32 -08007059 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7060 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007061 if (r.errorReportReceiver == null) {
7062 return null;
7063 }
7064
7065 if (!r.crashing && !r.notResponding) {
7066 return null;
7067 }
7068
Dan Egnorb7f03672009-12-09 16:22:32 -08007069 ApplicationErrorReport report = new ApplicationErrorReport();
7070 report.packageName = r.info.packageName;
7071 report.installerPackageName = r.errorReportReceiver.getPackageName();
7072 report.processName = r.processName;
7073 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007074 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007075
Dan Egnorb7f03672009-12-09 16:22:32 -08007076 if (r.crashing) {
7077 report.type = ApplicationErrorReport.TYPE_CRASH;
7078 report.crashInfo = crashInfo;
7079 } else if (r.notResponding) {
7080 report.type = ApplicationErrorReport.TYPE_ANR;
7081 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007082
Dan Egnorb7f03672009-12-09 16:22:32 -08007083 report.anrInfo.activity = r.notRespondingReport.tag;
7084 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7085 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007086 }
7087
Dan Egnorb7f03672009-12-09 16:22:32 -08007088 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007089 }
7090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007091 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7092 // assume our apps are happy - lazy create the list
7093 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7094
7095 synchronized (this) {
7096
7097 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007098 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7099 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007100 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7101 // This one's in trouble, so we'll generate a report for it
7102 // crashes are higher priority (in case there's a crash *and* an anr)
7103 ActivityManager.ProcessErrorStateInfo report = null;
7104 if (app.crashing) {
7105 report = app.crashingReport;
7106 } else if (app.notResponding) {
7107 report = app.notRespondingReport;
7108 }
7109
7110 if (report != null) {
7111 if (errList == null) {
7112 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7113 }
7114 errList.add(report);
7115 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007116 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117 " crashing = " + app.crashing +
7118 " notResponding = " + app.notResponding);
7119 }
7120 }
7121 }
7122 }
7123
7124 return errList;
7125 }
7126
7127 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7128 // Lazy instantiation of list
7129 List<ActivityManager.RunningAppProcessInfo> runList = null;
7130 synchronized (this) {
7131 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007132 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7133 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007134 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7135 // Generate process state info for running application
7136 ActivityManager.RunningAppProcessInfo currApp =
7137 new ActivityManager.RunningAppProcessInfo(app.processName,
7138 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007139 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007140 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007141 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007142 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007143 if (app.persistent) {
7144 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007146 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007147 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007148 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7149 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7150 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007151 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7152 } else if (adj >= HOME_APP_ADJ) {
7153 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7154 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007155 } else if (adj >= SECONDARY_SERVER_ADJ) {
7156 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007157 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007158 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007159 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7160 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007161 } else if (adj >= VISIBLE_APP_ADJ) {
7162 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7163 } else {
7164 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7165 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007166 currApp.importanceReasonCode = app.adjTypeCode;
7167 if (app.adjSource instanceof ProcessRecord) {
7168 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007169 } else if (app.adjSource instanceof ActivityRecord) {
7170 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007171 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7172 }
7173 if (app.adjTarget instanceof ComponentName) {
7174 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7175 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007176 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007177 // + " lru=" + currApp.lru);
7178 if (runList == null) {
7179 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7180 }
7181 runList.add(currApp);
7182 }
7183 }
7184 }
7185 return runList;
7186 }
7187
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007188 public List<ApplicationInfo> getRunningExternalApplications() {
7189 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7190 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7191 if (runningApps != null && runningApps.size() > 0) {
7192 Set<String> extList = new HashSet<String>();
7193 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7194 if (app.pkgList != null) {
7195 for (String pkg : app.pkgList) {
7196 extList.add(pkg);
7197 }
7198 }
7199 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007200 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007201 for (String pkg : extList) {
7202 try {
7203 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7204 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7205 retList.add(info);
7206 }
7207 } catch (RemoteException e) {
7208 }
7209 }
7210 }
7211 return retList;
7212 }
7213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007214 @Override
7215 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007216 if (checkCallingPermission(android.Manifest.permission.DUMP)
7217 != PackageManager.PERMISSION_GRANTED) {
7218 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7219 + Binder.getCallingPid()
7220 + ", uid=" + Binder.getCallingUid()
7221 + " without permission "
7222 + android.Manifest.permission.DUMP);
7223 return;
7224 }
7225
7226 boolean dumpAll = false;
7227
7228 int opti = 0;
7229 while (opti < args.length) {
7230 String opt = args[opti];
7231 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7232 break;
7233 }
7234 opti++;
7235 if ("-a".equals(opt)) {
7236 dumpAll = true;
7237 } else if ("-h".equals(opt)) {
7238 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007239 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007240 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007241 pw.println(" a[ctivities]: activity stack state");
7242 pw.println(" b[roadcasts]: broadcast state");
7243 pw.println(" i[ntents]: pending intent state");
7244 pw.println(" p[rocesses]: process state");
7245 pw.println(" o[om]: out of memory management");
7246 pw.println(" prov[iders]: content provider state");
7247 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007248 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007249 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007250 } else {
7251 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007253 }
7254
7255 // Is the caller requesting to dump a particular piece of data?
7256 if (opti < args.length) {
7257 String cmd = args[opti];
7258 opti++;
7259 if ("activities".equals(cmd) || "a".equals(cmd)) {
7260 synchronized (this) {
7261 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007262 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007263 return;
7264 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7265 synchronized (this) {
7266 dumpBroadcastsLocked(fd, pw, args, opti, true);
7267 }
7268 return;
7269 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7270 synchronized (this) {
7271 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7272 }
7273 return;
7274 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7275 synchronized (this) {
7276 dumpProcessesLocked(fd, pw, args, opti, true);
7277 }
7278 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007279 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7280 synchronized (this) {
7281 dumpOomLocked(fd, pw, args, opti, true);
7282 }
7283 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007284 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7285 synchronized (this) {
7286 dumpProvidersLocked(fd, pw, args, opti, true);
7287 }
7288 return;
7289 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007290 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007291 return;
7292 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7293 synchronized (this) {
7294 dumpServicesLocked(fd, pw, args, opti, true);
7295 }
7296 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007297 } else {
7298 // Dumping a single activity?
7299 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7300 return;
7301 }
7302 pw.println("Bad activity command: " + cmd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007303 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007304 }
7305
7306 // No piece of data specified, dump everything.
7307 synchronized (this) {
7308 boolean needSep;
7309 if (dumpAll) {
7310 pw.println("Providers in Current Activity Manager State:");
7311 }
7312 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7313 if (needSep) {
7314 pw.println(" ");
7315 }
7316 if (dumpAll) {
7317 pw.println("-------------------------------------------------------------------------------");
7318 pw.println("Broadcasts in Current Activity Manager State:");
7319 }
7320 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7321 if (needSep) {
7322 pw.println(" ");
7323 }
7324 if (dumpAll) {
7325 pw.println("-------------------------------------------------------------------------------");
7326 pw.println("Services in Current Activity Manager State:");
7327 }
7328 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7329 if (needSep) {
7330 pw.println(" ");
7331 }
7332 if (dumpAll) {
7333 pw.println("-------------------------------------------------------------------------------");
7334 pw.println("PendingIntents in Current Activity Manager State:");
7335 }
7336 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7337 if (needSep) {
7338 pw.println(" ");
7339 }
7340 if (dumpAll) {
7341 pw.println("-------------------------------------------------------------------------------");
7342 pw.println("Activities in Current Activity Manager State:");
7343 }
7344 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7345 if (needSep) {
7346 pw.println(" ");
7347 }
7348 if (dumpAll) {
7349 pw.println("-------------------------------------------------------------------------------");
7350 pw.println("Processes in Current Activity Manager State:");
7351 }
7352 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7353 }
7354 }
7355
7356 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7357 int opti, boolean dumpAll, boolean needHeader) {
7358 if (needHeader) {
7359 pw.println(" Activity stack:");
7360 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007361 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007362 pw.println(" ");
7363 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007364 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7365 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007366 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007367 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007368 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007369 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007370 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007372 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007373 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007374 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007375 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007376 pw.println(" ");
7377 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007378 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007379 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007381 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007382 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7383 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007384 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007385 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007386
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007387 if (dumpAll && mRecentTasks.size() > 0) {
7388 pw.println(" ");
7389 pw.println("Recent tasks in Current Activity Manager State:");
7390
7391 final int N = mRecentTasks.size();
7392 for (int i=0; i<N; i++) {
7393 TaskRecord tr = mRecentTasks.get(i);
7394 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7395 pw.println(tr);
7396 mRecentTasks.get(i).dump(pw, " ");
7397 }
7398 }
7399
7400 pw.println(" ");
7401 pw.println(" mCurTask: " + mCurTask);
7402
7403 return true;
7404 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007405
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007406 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7407 int opti, boolean dumpAll) {
7408 boolean needSep = false;
7409 int numPers = 0;
7410
7411 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007412 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7413 final int NA = procs.size();
7414 for (int ia=0; ia<NA; ia++) {
7415 if (!needSep) {
7416 pw.println(" All known processes:");
7417 needSep = true;
7418 }
7419 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007420 pw.print(r.persistent ? " *PERS*" : " *APP*");
7421 pw.print(" UID "); pw.print(procs.keyAt(ia));
7422 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 r.dump(pw, " ");
7424 if (r.persistent) {
7425 numPers++;
7426 }
7427 }
7428 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007429 }
7430
7431 if (mLruProcesses.size() > 0) {
7432 if (needSep) pw.println(" ");
7433 needSep = true;
7434 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007435 dumpProcessOomList(pw, this, mLruProcesses, " ",
7436 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007437 needSep = true;
7438 }
7439
7440 synchronized (mPidsSelfLocked) {
7441 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007442 if (needSep) pw.println(" ");
7443 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007444 pw.println(" PID mappings:");
7445 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7446 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7447 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007448 }
7449 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007450 }
7451
7452 if (mForegroundProcesses.size() > 0) {
7453 if (needSep) pw.println(" ");
7454 needSep = true;
7455 pw.println(" Foreground Processes:");
7456 for (int i=0; i<mForegroundProcesses.size(); i++) {
7457 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7458 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007459 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007460 }
7461
7462 if (mPersistentStartingProcesses.size() > 0) {
7463 if (needSep) pw.println(" ");
7464 needSep = true;
7465 pw.println(" Persisent processes that are starting:");
7466 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007467 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007469
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007470 if (mStartingProcesses.size() > 0) {
7471 if (needSep) pw.println(" ");
7472 needSep = true;
7473 pw.println(" Processes that are starting:");
7474 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007475 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007476 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007477
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007478 if (mRemovedProcesses.size() > 0) {
7479 if (needSep) pw.println(" ");
7480 needSep = true;
7481 pw.println(" Processes that are being removed:");
7482 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007483 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007484 }
7485
7486 if (mProcessesOnHold.size() > 0) {
7487 if (needSep) pw.println(" ");
7488 needSep = true;
7489 pw.println(" Processes that are on old until the system is ready:");
7490 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007491 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007493
Dianne Hackborn287952c2010-09-22 22:34:31 -07007494 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007495
7496 if (mProcessCrashTimes.getMap().size() > 0) {
7497 if (needSep) pw.println(" ");
7498 needSep = true;
7499 pw.println(" Time since processes crashed:");
7500 long now = SystemClock.uptimeMillis();
7501 for (Map.Entry<String, SparseArray<Long>> procs
7502 : mProcessCrashTimes.getMap().entrySet()) {
7503 SparseArray<Long> uids = procs.getValue();
7504 final int N = uids.size();
7505 for (int i=0; i<N; i++) {
7506 pw.print(" Process "); pw.print(procs.getKey());
7507 pw.print(" uid "); pw.print(uids.keyAt(i));
7508 pw.print(": last crashed ");
7509 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007510 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007511 }
7512 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007514
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007515 if (mBadProcesses.getMap().size() > 0) {
7516 if (needSep) pw.println(" ");
7517 needSep = true;
7518 pw.println(" Bad processes:");
7519 for (Map.Entry<String, SparseArray<Long>> procs
7520 : mBadProcesses.getMap().entrySet()) {
7521 SparseArray<Long> uids = procs.getValue();
7522 final int N = uids.size();
7523 for (int i=0; i<N; i++) {
7524 pw.print(" Bad process "); pw.print(procs.getKey());
7525 pw.print(" uid "); pw.print(uids.keyAt(i));
7526 pw.print(": crashed at time ");
7527 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007528 }
7529 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007531
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007532 pw.println(" ");
7533 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007534 if (mHeavyWeightProcess != null) {
7535 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7536 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007537 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007538 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007539 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7540 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7541 || mOrigWaitForDebugger) {
7542 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7543 + " mDebugTransient=" + mDebugTransient
7544 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7545 }
7546 if (mAlwaysFinishActivities || mController != null) {
7547 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7548 + " mController=" + mController);
7549 }
7550 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007552 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007553 + " mProcessesReady=" + mProcessesReady
7554 + " mSystemReady=" + mSystemReady);
7555 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007556 + " mBooted=" + mBooted
7557 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007558 pw.print(" mLastPowerCheckRealtime=");
7559 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7560 pw.println("");
7561 pw.print(" mLastPowerCheckUptime=");
7562 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7563 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007564 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7565 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007566 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007567 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007568
7569 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 }
7571
Dianne Hackborn287952c2010-09-22 22:34:31 -07007572 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7573 int opti, boolean needSep, boolean dumpAll) {
7574 if (mProcessesToGc.size() > 0) {
7575 if (needSep) pw.println(" ");
7576 needSep = true;
7577 pw.println(" Processes that are waiting to GC:");
7578 long now = SystemClock.uptimeMillis();
7579 for (int i=0; i<mProcessesToGc.size(); i++) {
7580 ProcessRecord proc = mProcessesToGc.get(i);
7581 pw.print(" Process "); pw.println(proc);
7582 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7583 pw.print(", last gced=");
7584 pw.print(now-proc.lastRequestedGc);
7585 pw.print(" ms ago, last lowMem=");
7586 pw.print(now-proc.lastLowMemory);
7587 pw.println(" ms ago");
7588
7589 }
7590 }
7591 return needSep;
7592 }
7593
7594 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7595 int opti, boolean dumpAll) {
7596 boolean needSep = false;
7597
7598 if (mLruProcesses.size() > 0) {
7599 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7600
7601 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7602 @Override
7603 public int compare(ProcessRecord object1, ProcessRecord object2) {
7604 if (object1.setAdj != object2.setAdj) {
7605 return object1.setAdj > object2.setAdj ? -1 : 1;
7606 }
7607 if (object1.setSchedGroup != object2.setSchedGroup) {
7608 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7609 }
7610 if (object1.keeping != object2.keeping) {
7611 return object1.keeping ? -1 : 1;
7612 }
7613 if (object1.pid != object2.pid) {
7614 return object1.pid > object2.pid ? -1 : 1;
7615 }
7616 return 0;
7617 }
7618 };
7619
7620 Collections.sort(procs, comparator);
7621
7622 if (needSep) pw.println(" ");
7623 needSep = true;
7624 pw.println(" Process OOM control:");
7625 dumpProcessOomList(pw, this, procs, " ",
7626 "Proc", "PERS", true);
7627 needSep = true;
7628 }
7629
7630 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7631
7632 pw.println(" ");
7633 pw.println(" mHomeProcess: " + mHomeProcess);
7634 if (mHeavyWeightProcess != null) {
7635 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7636 }
7637
7638 return true;
7639 }
7640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007641 /**
7642 * There are three ways to call this:
7643 * - no service specified: dump all the services
7644 * - a flattened component name that matched an existing service was specified as the
7645 * first arg: dump that one service
7646 * - the first arg isn't the flattened component name of an existing service:
7647 * dump all services whose component contains the first arg as a substring
7648 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007649 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650 String[] newArgs;
7651 String componentNameString;
7652 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007653 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007654 componentNameString = null;
7655 newArgs = EMPTY_STRING_ARRAY;
7656 r = null;
7657 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007658 componentNameString = args[opti];
7659 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007660 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007661 synchronized (this) {
7662 r = componentName != null ? mServices.get(componentName) : null;
7663 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007664 newArgs = new String[args.length - opti];
7665 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666 }
7667
7668 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007669 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007670 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007671 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7672 synchronized (this) {
7673 for (ServiceRecord r1 : mServices.values()) {
7674 if (componentNameString == null
7675 || r1.name.flattenToString().contains(componentNameString)) {
7676 services.add(r1);
7677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007678 }
7679 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007680 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007681 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007683 }
7684 }
7685
7686 /**
7687 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7688 * there is a thread associated with the service.
7689 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007690 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7691 pw.println("------------------------------------------------------------"
7692 + "-------------------");
7693 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007694 if (r.app != null && r.app.thread != null) {
7695 try {
7696 // flush anything that is already in the PrintWriter since the thread is going
7697 // to write to the file descriptor directly
7698 pw.flush();
7699 r.app.thread.dumpService(fd, r, args);
7700 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007701 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007702 } catch (RemoteException e) {
7703 pw.println("got a RemoteException while dumping the service");
7704 }
7705 }
7706 }
7707
Dianne Hackborn625ac272010-09-17 18:29:22 -07007708 /**
7709 * There are three things that cmd can be:
7710 * - a flattened component name that matched an existing activity
7711 * - the cmd arg isn't the flattened component name of an existing activity:
7712 * dump all activity whose component contains the cmd as a substring
7713 * - A hex number of the ActivityRecord object instance.
7714 */
7715 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7716 int opti, boolean dumpAll) {
7717 String[] newArgs;
7718 ComponentName componentName = ComponentName.unflattenFromString(name);
7719 int objectId = 0;
7720 try {
7721 objectId = Integer.parseInt(name, 16);
7722 name = null;
7723 componentName = null;
7724 } catch (RuntimeException e) {
7725 }
7726 newArgs = new String[args.length - opti];
7727 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7728
7729 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7730 synchronized (this) {
7731 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7732 if (componentName != null) {
7733 if (r1.intent.getComponent().equals(componentName)) {
7734 activities.add(r1);
7735 }
7736 } else if (name != null) {
7737 if (r1.intent.getComponent().flattenToString().contains(name)) {
7738 activities.add(r1);
7739 }
7740 } else if (System.identityHashCode(this) == objectId) {
7741 activities.add(r1);
7742 }
7743 }
7744 }
7745
7746 if (activities.size() <= 0) {
7747 return false;
7748 }
7749
7750 for (int i=0; i<activities.size(); i++) {
7751 dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
7752 }
7753 return true;
7754 }
7755
7756 /**
7757 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7758 * there is a thread associated with the activity.
7759 */
7760 private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
7761 boolean dumpAll) {
7762 pw.println(" Activity " + r.intent.getComponent().flattenToString());
7763 if (dumpAll) {
7764 synchronized (this) {
7765 pw.print(" * "); pw.println(r);
7766 r.dump(pw, " ");
7767 }
7768 pw.println("");
7769 }
7770 if (r.app != null && r.app.thread != null) {
7771 try {
7772 // flush anything that is already in the PrintWriter since the thread is going
7773 // to write to the file descriptor directly
7774 pw.flush();
7775 r.app.thread.dumpActivity(fd, r, args);
7776 pw.print("\n");
7777 pw.flush();
7778 } catch (RemoteException e) {
7779 pw.println("got a RemoteException while dumping the activity");
7780 }
7781 }
7782 }
7783
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007784 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7785 int opti, boolean dumpAll) {
7786 boolean needSep = false;
7787
7788 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007789 if (mRegisteredReceivers.size() > 0) {
7790 pw.println(" ");
7791 pw.println(" Registered Receivers:");
7792 Iterator it = mRegisteredReceivers.values().iterator();
7793 while (it.hasNext()) {
7794 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007795 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007796 r.dump(pw, " ");
7797 }
7798 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 pw.println(" ");
7801 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007802 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007803 needSep = true;
7804 }
7805
7806 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7807 || mPendingBroadcast != null) {
7808 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007809 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007810 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007811 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007812 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7813 pw.println(" Broadcast #" + i + ":");
7814 mParallelBroadcasts.get(i).dump(pw, " ");
7815 }
7816 if (mOrderedBroadcasts.size() > 0) {
7817 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007818 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007819 }
7820 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7821 pw.println(" Serialized Broadcast #" + i + ":");
7822 mOrderedBroadcasts.get(i).dump(pw, " ");
7823 }
7824 pw.println(" ");
7825 pw.println(" Pending broadcast:");
7826 if (mPendingBroadcast != null) {
7827 mPendingBroadcast.dump(pw, " ");
7828 } else {
7829 pw.println(" (null)");
7830 }
7831 needSep = true;
7832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007833
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007834 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007835 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007836 pw.println(" Historical broadcasts:");
7837 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7838 BroadcastRecord r = mBroadcastHistory[i];
7839 if (r == null) {
7840 break;
7841 }
7842 pw.println(" Historical Broadcast #" + i + ":");
7843 r.dump(pw, " ");
7844 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007845 needSep = true;
7846 }
7847
7848 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007849 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007850 pw.println(" Sticky broadcasts:");
7851 StringBuilder sb = new StringBuilder(128);
7852 for (Map.Entry<String, ArrayList<Intent>> ent
7853 : mStickyBroadcasts.entrySet()) {
7854 pw.print(" * Sticky action "); pw.print(ent.getKey());
7855 pw.println(":");
7856 ArrayList<Intent> intents = ent.getValue();
7857 final int N = intents.size();
7858 for (int i=0; i<N; i++) {
7859 sb.setLength(0);
7860 sb.append(" Intent: ");
7861 intents.get(i).toShortString(sb, true, false);
7862 pw.println(sb.toString());
7863 Bundle bundle = intents.get(i).getExtras();
7864 if (bundle != null) {
7865 pw.print(" ");
7866 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007867 }
7868 }
7869 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007870 needSep = true;
7871 }
7872
7873 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007874 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007875 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007876 pw.println(" mHandler:");
7877 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007878 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007879 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007880
7881 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 }
7883
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007884 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7885 int opti, boolean dumpAll) {
7886 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007887
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007888 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007889 if (mServices.size() > 0) {
7890 pw.println(" Active services:");
7891 Iterator<ServiceRecord> it = mServices.values().iterator();
7892 while (it.hasNext()) {
7893 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007894 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 r.dump(pw, " ");
7896 }
7897 needSep = true;
7898 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007901 if (mPendingServices.size() > 0) {
7902 if (needSep) pw.println(" ");
7903 pw.println(" Pending services:");
7904 for (int i=0; i<mPendingServices.size(); i++) {
7905 ServiceRecord r = mPendingServices.get(i);
7906 pw.print(" * Pending "); pw.println(r);
7907 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007909 needSep = true;
7910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007912 if (mRestartingServices.size() > 0) {
7913 if (needSep) pw.println(" ");
7914 pw.println(" Restarting services:");
7915 for (int i=0; i<mRestartingServices.size(); i++) {
7916 ServiceRecord r = mRestartingServices.get(i);
7917 pw.print(" * Restarting "); pw.println(r);
7918 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007919 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007920 needSep = true;
7921 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007922
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007923 if (mStoppingServices.size() > 0) {
7924 if (needSep) pw.println(" ");
7925 pw.println(" Stopping services:");
7926 for (int i=0; i<mStoppingServices.size(); i++) {
7927 ServiceRecord r = mStoppingServices.get(i);
7928 pw.print(" * Stopping "); pw.println(r);
7929 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007930 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007931 needSep = true;
7932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007933
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007934 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935 if (mServiceConnections.size() > 0) {
7936 if (needSep) pw.println(" ");
7937 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007938 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007939 = mServiceConnections.values().iterator();
7940 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007941 ArrayList<ConnectionRecord> r = it.next();
7942 for (int i=0; i<r.size(); i++) {
7943 pw.print(" * "); pw.println(r.get(i));
7944 r.get(i).dump(pw, " ");
7945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007947 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007948 }
7949 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007950
7951 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007952 }
7953
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007954 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7955 int opti, boolean dumpAll) {
7956 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007957
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007958 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007959 if (mProvidersByClass.size() > 0) {
7960 if (needSep) pw.println(" ");
7961 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007962 Iterator<Map.Entry<String, ContentProviderRecord>> it
7963 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007964 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007965 Map.Entry<String, ContentProviderRecord> e = it.next();
7966 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007967 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007968 r.dump(pw, " ");
7969 }
7970 needSep = true;
7971 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007972
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007973 if (mProvidersByName.size() > 0) {
7974 pw.println(" ");
7975 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007976 Iterator<Map.Entry<String, ContentProviderRecord>> it
7977 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007978 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007979 Map.Entry<String, ContentProviderRecord> e = it.next();
7980 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007981 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7982 pw.println(r);
7983 }
7984 needSep = true;
7985 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007986 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007987
7988 if (mLaunchingProviders.size() > 0) {
7989 if (needSep) pw.println(" ");
7990 pw.println(" Launching content providers:");
7991 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7992 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7993 pw.println(mLaunchingProviders.get(i));
7994 }
7995 needSep = true;
7996 }
7997
7998 if (mGrantedUriPermissions.size() > 0) {
7999 pw.println();
8000 pw.println("Granted Uri Permissions:");
8001 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8002 int uid = mGrantedUriPermissions.keyAt(i);
8003 HashMap<Uri, UriPermission> perms
8004 = mGrantedUriPermissions.valueAt(i);
8005 pw.print(" * UID "); pw.print(uid);
8006 pw.println(" holds:");
8007 for (UriPermission perm : perms.values()) {
8008 pw.print(" "); pw.println(perm);
8009 perm.dump(pw, " ");
8010 }
8011 }
8012 needSep = true;
8013 }
8014
8015 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008016 }
8017
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008018 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8019 int opti, boolean dumpAll) {
8020 boolean needSep = false;
8021
8022 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008023 if (this.mIntentSenderRecords.size() > 0) {
8024 Iterator<WeakReference<PendingIntentRecord>> it
8025 = mIntentSenderRecords.values().iterator();
8026 while (it.hasNext()) {
8027 WeakReference<PendingIntentRecord> ref = it.next();
8028 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008029 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008030 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008031 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 rec.dump(pw, " ");
8033 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008034 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008035 }
8036 }
8037 }
8038 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008039
8040 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008041 }
8042
8043 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008044 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045 TaskRecord lastTask = null;
8046 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008047 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008048 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008049 if (lastTask != r.task) {
8050 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008051 pw.print(prefix);
8052 pw.print(full ? "* " : " ");
8053 pw.println(lastTask);
8054 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008055 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008057 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008058 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8059 pw.print(" #"); pw.print(i); pw.print(": ");
8060 pw.println(r);
8061 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008062 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008064 }
8065 }
8066
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008067 private static String buildOomTag(String prefix, String space, int val, int base) {
8068 if (val == base) {
8069 if (space == null) return prefix;
8070 return prefix + " ";
8071 }
8072 return prefix + "+" + Integer.toString(val-base);
8073 }
8074
8075 private static final int dumpProcessList(PrintWriter pw,
8076 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008077 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008078 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008079 final int N = list.size()-1;
8080 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008082 pw.println(String.format("%s%s #%2d: %s",
8083 prefix, (r.persistent ? persistentLabel : normalLabel),
8084 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008085 if (r.persistent) {
8086 numPers++;
8087 }
8088 }
8089 return numPers;
8090 }
8091
Dianne Hackborn287952c2010-09-22 22:34:31 -07008092 private static final void dumpProcessOomList(PrintWriter pw,
8093 ActivityManagerService service, List<ProcessRecord> list,
8094 String prefix, String normalLabel, String persistentLabel,
8095 boolean inclDetails) {
8096
8097 final long curRealtime = SystemClock.elapsedRealtime();
8098 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8099 final long curUptime = SystemClock.uptimeMillis();
8100 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8101
8102 final int N = list.size()-1;
8103 for (int i=N; i>=0; i--) {
8104 ProcessRecord r = list.get(i);
8105 String oomAdj;
8106 if (r.setAdj >= EMPTY_APP_ADJ) {
8107 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8108 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8109 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8110 } else if (r.setAdj >= HOME_APP_ADJ) {
8111 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8112 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8113 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8114 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8115 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8116 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8117 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8118 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8119 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8120 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8121 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8122 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8123 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8124 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8125 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8126 } else if (r.setAdj >= SYSTEM_ADJ) {
8127 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8128 } else {
8129 oomAdj = Integer.toString(r.setAdj);
8130 }
8131 String schedGroup;
8132 switch (r.setSchedGroup) {
8133 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8134 schedGroup = "B";
8135 break;
8136 case Process.THREAD_GROUP_DEFAULT:
8137 schedGroup = "F";
8138 break;
8139 default:
8140 schedGroup = Integer.toString(r.setSchedGroup);
8141 break;
8142 }
8143 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8144 prefix, (r.persistent ? persistentLabel : normalLabel),
8145 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8146 if (r.adjSource != null || r.adjTarget != null) {
8147 pw.print(prefix);
8148 pw.print(" ");
8149 if (r.adjTarget instanceof ComponentName) {
8150 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8151 } else if (r.adjTarget != null) {
8152 pw.print(r.adjTarget.toString());
8153 } else {
8154 pw.print("{null}");
8155 }
8156 pw.print("<=");
8157 if (r.adjSource instanceof ProcessRecord) {
8158 pw.print("Proc{");
8159 pw.print(((ProcessRecord)r.adjSource).toShortString());
8160 pw.println("}");
8161 } else if (r.adjSource != null) {
8162 pw.println(r.adjSource.toString());
8163 } else {
8164 pw.println("{null}");
8165 }
8166 }
8167 if (inclDetails) {
8168 pw.print(prefix);
8169 pw.print(" ");
8170 pw.print("oom: max="); pw.print(r.maxAdj);
8171 pw.print(" hidden="); pw.print(r.hiddenAdj);
8172 pw.print(" curRaw="); pw.print(r.curRawAdj);
8173 pw.print(" setRaw="); pw.print(r.setRawAdj);
8174 pw.print(" cur="); pw.print(r.curAdj);
8175 pw.print(" set="); pw.println(r.setAdj);
8176 pw.print(prefix);
8177 pw.print(" ");
8178 pw.print("keeping="); pw.print(r.keeping);
8179 pw.print(" hidden="); pw.print(r.hidden);
8180 pw.print(" empty="); pw.println(r.empty);
8181
8182 if (!r.keeping) {
8183 if (r.lastWakeTime != 0) {
8184 long wtime;
8185 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8186 synchronized (stats) {
8187 wtime = stats.getProcessWakeTime(r.info.uid,
8188 r.pid, curRealtime);
8189 }
8190 long timeUsed = wtime - r.lastWakeTime;
8191 pw.print(prefix);
8192 pw.print(" ");
8193 pw.print("keep awake over ");
8194 TimeUtils.formatDuration(realtimeSince, pw);
8195 pw.print(" used ");
8196 TimeUtils.formatDuration(timeUsed, pw);
8197 pw.print(" (");
8198 pw.print((timeUsed*100)/realtimeSince);
8199 pw.println("%)");
8200 }
8201 if (r.lastCpuTime != 0) {
8202 long timeUsed = r.curCpuTime - r.lastCpuTime;
8203 pw.print(prefix);
8204 pw.print(" ");
8205 pw.print("run cpu over ");
8206 TimeUtils.formatDuration(uptimeSince, pw);
8207 pw.print(" used ");
8208 TimeUtils.formatDuration(timeUsed, pw);
8209 pw.print(" (");
8210 pw.print((timeUsed*100)/uptimeSince);
8211 pw.println("%)");
8212 }
8213 }
8214 }
8215 }
8216 }
8217
Dianne Hackborn472ad872010-04-07 17:31:48 -07008218 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008220 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008221 long uptime = SystemClock.uptimeMillis();
8222 long realtime = SystemClock.elapsedRealtime();
8223
8224 if (isCheckinRequest) {
8225 // short checkin version
8226 pw.println(uptime + "," + realtime);
8227 pw.flush();
8228 } else {
8229 pw.println("Applications Memory Usage (kB):");
8230 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8231 }
8232 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8233 ProcessRecord r = (ProcessRecord)list.get(i);
8234 if (r.thread != null) {
8235 if (!isCheckinRequest) {
8236 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8237 pw.flush();
8238 }
8239 try {
8240 r.thread.asBinder().dump(fd, args);
8241 } catch (RemoteException e) {
8242 if (!isCheckinRequest) {
8243 pw.println("Got RemoteException!");
8244 pw.flush();
8245 }
8246 }
8247 }
8248 }
8249 }
8250
8251 /**
8252 * Searches array of arguments for the specified string
8253 * @param args array of argument strings
8254 * @param value value to search for
8255 * @return true if the value is contained in the array
8256 */
8257 private static boolean scanArgs(String[] args, String value) {
8258 if (args != null) {
8259 for (String arg : args) {
8260 if (value.equals(arg)) {
8261 return true;
8262 }
8263 }
8264 }
8265 return false;
8266 }
8267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008268 private final void killServicesLocked(ProcessRecord app,
8269 boolean allowRestart) {
8270 // Report disconnected services.
8271 if (false) {
8272 // XXX we are letting the client link to the service for
8273 // death notifications.
8274 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008275 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008276 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008277 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008278 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008279 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008280 = r.connections.values().iterator();
8281 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008282 ArrayList<ConnectionRecord> cl = jt.next();
8283 for (int i=0; i<cl.size(); i++) {
8284 ConnectionRecord c = cl.get(i);
8285 if (c.binding.client != app) {
8286 try {
8287 //c.conn.connected(r.className, null);
8288 } catch (Exception e) {
8289 // todo: this should be asynchronous!
8290 Slog.w(TAG, "Exception thrown disconnected servce "
8291 + r.shortName
8292 + " from app " + app.processName, e);
8293 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008294 }
8295 }
8296 }
8297 }
8298 }
8299 }
8300 }
8301
8302 // Clean up any connections this application has to other services.
8303 if (app.connections.size() > 0) {
8304 Iterator<ConnectionRecord> it = app.connections.iterator();
8305 while (it.hasNext()) {
8306 ConnectionRecord r = it.next();
8307 removeConnectionLocked(r, app, null);
8308 }
8309 }
8310 app.connections.clear();
8311
8312 if (app.services.size() != 0) {
8313 // Any services running in the application need to be placed
8314 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008315 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008316 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008317 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008318 synchronized (sr.stats.getBatteryStats()) {
8319 sr.stats.stopLaunchedLocked();
8320 }
8321 sr.app = null;
8322 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008323 if (mStoppingServices.remove(sr)) {
8324 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8325 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008326
8327 boolean hasClients = sr.bindings.size() > 0;
8328 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008329 Iterator<IntentBindRecord> bindings
8330 = sr.bindings.values().iterator();
8331 while (bindings.hasNext()) {
8332 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008333 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008334 + ": shouldUnbind=" + b.hasBound);
8335 b.binder = null;
8336 b.requested = b.received = b.hasBound = false;
8337 }
8338 }
8339
8340 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008341 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008342 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008343 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008344 sr.crashCount, sr.shortName, app.pid);
8345 bringDownServiceLocked(sr, true);
8346 } else if (!allowRestart) {
8347 bringDownServiceLocked(sr, true);
8348 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008349 boolean canceled = scheduleServiceRestartLocked(sr, true);
8350
8351 // Should the service remain running? Note that in the
8352 // extreme case of so many attempts to deliver a command
8353 // that it failed, that we also will stop it here.
8354 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8355 if (sr.pendingStarts.size() == 0) {
8356 sr.startRequested = false;
8357 if (!hasClients) {
8358 // Whoops, no reason to restart!
8359 bringDownServiceLocked(sr, true);
8360 }
8361 }
8362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008363 }
8364 }
8365
8366 if (!allowRestart) {
8367 app.services.clear();
8368 }
8369 }
8370
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008371 // Make sure we have no more records on the stopping list.
8372 int i = mStoppingServices.size();
8373 while (i > 0) {
8374 i--;
8375 ServiceRecord sr = mStoppingServices.get(i);
8376 if (sr.app == app) {
8377 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008378 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008379 }
8380 }
8381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008382 app.executingServices.clear();
8383 }
8384
8385 private final void removeDyingProviderLocked(ProcessRecord proc,
8386 ContentProviderRecord cpr) {
8387 synchronized (cpr) {
8388 cpr.launchingApp = null;
8389 cpr.notifyAll();
8390 }
8391
8392 mProvidersByClass.remove(cpr.info.name);
8393 String names[] = cpr.info.authority.split(";");
8394 for (int j = 0; j < names.length; j++) {
8395 mProvidersByName.remove(names[j]);
8396 }
8397
8398 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8399 while (cit.hasNext()) {
8400 ProcessRecord capp = cit.next();
8401 if (!capp.persistent && capp.thread != null
8402 && capp.pid != 0
8403 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008404 Slog.i(TAG, "Kill " + capp.processName
8405 + " (pid " + capp.pid + "): provider " + cpr.info.name
8406 + " in dying process " + proc.processName);
8407 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8408 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008409 Process.killProcess(capp.pid);
8410 }
8411 }
8412
8413 mLaunchingProviders.remove(cpr);
8414 }
8415
8416 /**
8417 * Main code for cleaning up a process when it has gone away. This is
8418 * called both as a result of the process dying, or directly when stopping
8419 * a process when running in single process mode.
8420 */
8421 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8422 boolean restarting, int index) {
8423 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008424 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 }
8426
Dianne Hackborn36124872009-10-08 16:22:03 -07008427 mProcessesToGc.remove(app);
8428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008429 // Dismiss any open dialogs.
8430 if (app.crashDialog != null) {
8431 app.crashDialog.dismiss();
8432 app.crashDialog = null;
8433 }
8434 if (app.anrDialog != null) {
8435 app.anrDialog.dismiss();
8436 app.anrDialog = null;
8437 }
8438 if (app.waitDialog != null) {
8439 app.waitDialog.dismiss();
8440 app.waitDialog = null;
8441 }
8442
8443 app.crashing = false;
8444 app.notResponding = false;
8445
8446 app.resetPackageList();
8447 app.thread = null;
8448 app.forcingToForeground = null;
8449 app.foregroundServices = false;
8450
8451 killServicesLocked(app, true);
8452
8453 boolean restart = false;
8454
8455 int NL = mLaunchingProviders.size();
8456
8457 // Remove published content providers.
8458 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008459 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008460 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008461 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008462 cpr.provider = null;
8463 cpr.app = null;
8464
8465 // See if someone is waiting for this provider... in which
8466 // case we don't remove it, but just let it restart.
8467 int i = 0;
8468 if (!app.bad) {
8469 for (; i<NL; i++) {
8470 if (mLaunchingProviders.get(i) == cpr) {
8471 restart = true;
8472 break;
8473 }
8474 }
8475 } else {
8476 i = NL;
8477 }
8478
8479 if (i >= NL) {
8480 removeDyingProviderLocked(app, cpr);
8481 NL = mLaunchingProviders.size();
8482 }
8483 }
8484 app.pubProviders.clear();
8485 }
8486
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008487 // Take care of any launching providers waiting for this process.
8488 if (checkAppInLaunchingProvidersLocked(app, false)) {
8489 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008490 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008492 // Unregister from connected content providers.
8493 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008494 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008495 while (it.hasNext()) {
8496 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8497 cpr.clients.remove(app);
8498 }
8499 app.conProviders.clear();
8500 }
8501
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008502 // At this point there may be remaining entries in mLaunchingProviders
8503 // where we were the only one waiting, so they are no longer of use.
8504 // Look for these and clean up if found.
8505 // XXX Commented out for now. Trying to figure out a way to reproduce
8506 // the actual situation to identify what is actually going on.
8507 if (false) {
8508 for (int i=0; i<NL; i++) {
8509 ContentProviderRecord cpr = (ContentProviderRecord)
8510 mLaunchingProviders.get(i);
8511 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8512 synchronized (cpr) {
8513 cpr.launchingApp = null;
8514 cpr.notifyAll();
8515 }
8516 }
8517 }
8518 }
8519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 skipCurrentReceiverLocked(app);
8521
8522 // Unregister any receivers.
8523 if (app.receivers.size() > 0) {
8524 Iterator<ReceiverList> it = app.receivers.iterator();
8525 while (it.hasNext()) {
8526 removeReceiverLocked(it.next());
8527 }
8528 app.receivers.clear();
8529 }
8530
Christopher Tate181fafa2009-05-14 11:12:14 -07008531 // If the app is undergoing backup, tell the backup manager about it
8532 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008533 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008534 try {
8535 IBackupManager bm = IBackupManager.Stub.asInterface(
8536 ServiceManager.getService(Context.BACKUP_SERVICE));
8537 bm.agentDisconnected(app.info.packageName);
8538 } catch (RemoteException e) {
8539 // can't happen; backup manager is local
8540 }
8541 }
8542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008543 // If the caller is restarting this app, then leave it in its
8544 // current lists and let the caller take care of it.
8545 if (restarting) {
8546 return;
8547 }
8548
8549 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008550 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008551 "Removing non-persistent process during cleanup: " + app);
8552 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008553 if (mHeavyWeightProcess == app) {
8554 mHeavyWeightProcess = null;
8555 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008557 } else if (!app.removed) {
8558 // This app is persistent, so we need to keep its record around.
8559 // If it is not already on the pending app list, add it there
8560 // and start a new process for it.
8561 app.thread = null;
8562 app.forcingToForeground = null;
8563 app.foregroundServices = false;
8564 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8565 mPersistentStartingProcesses.add(app);
8566 restart = true;
8567 }
8568 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008569 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8570 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008571 mProcessesOnHold.remove(app);
8572
The Android Open Source Project4df24232009-03-05 14:34:35 -08008573 if (app == mHomeProcess) {
8574 mHomeProcess = null;
8575 }
8576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008577 if (restart) {
8578 // We have components that still need to be running in the
8579 // process, so re-launch it.
8580 mProcessNames.put(app.processName, app.info.uid, app);
8581 startProcessLocked(app, "restart", app.processName);
8582 } else if (app.pid > 0 && app.pid != MY_PID) {
8583 // Goodbye!
8584 synchronized (mPidsSelfLocked) {
8585 mPidsSelfLocked.remove(app.pid);
8586 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8587 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008588 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008589 }
8590 }
8591
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008592 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8593 // Look through the content providers we are waiting to have launched,
8594 // and if any run in this process then either schedule a restart of
8595 // the process or kill the client waiting for it if this process has
8596 // gone bad.
8597 int NL = mLaunchingProviders.size();
8598 boolean restart = false;
8599 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008600 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008601 if (cpr.launchingApp == app) {
8602 if (!alwaysBad && !app.bad) {
8603 restart = true;
8604 } else {
8605 removeDyingProviderLocked(app, cpr);
8606 NL = mLaunchingProviders.size();
8607 }
8608 }
8609 }
8610 return restart;
8611 }
8612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008613 // =========================================================
8614 // SERVICES
8615 // =========================================================
8616
8617 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8618 ActivityManager.RunningServiceInfo info =
8619 new ActivityManager.RunningServiceInfo();
8620 info.service = r.name;
8621 if (r.app != null) {
8622 info.pid = r.app.pid;
8623 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008624 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008625 info.process = r.processName;
8626 info.foreground = r.isForeground;
8627 info.activeSince = r.createTime;
8628 info.started = r.startRequested;
8629 info.clientCount = r.connections.size();
8630 info.crashCount = r.crashCount;
8631 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008632 if (r.isForeground) {
8633 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8634 }
8635 if (r.startRequested) {
8636 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8637 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008638 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008639 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8640 }
8641 if (r.app != null && r.app.persistent) {
8642 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8643 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008644
8645 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8646 for (int i=0; i<connl.size(); i++) {
8647 ConnectionRecord conn = connl.get(i);
8648 if (conn.clientLabel != 0) {
8649 info.clientPackage = conn.binding.client.info.packageName;
8650 info.clientLabel = conn.clientLabel;
8651 return info;
8652 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008653 }
8654 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008655 return info;
8656 }
8657
8658 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8659 int flags) {
8660 synchronized (this) {
8661 ArrayList<ActivityManager.RunningServiceInfo> res
8662 = new ArrayList<ActivityManager.RunningServiceInfo>();
8663
8664 if (mServices.size() > 0) {
8665 Iterator<ServiceRecord> it = mServices.values().iterator();
8666 while (it.hasNext() && res.size() < maxNum) {
8667 res.add(makeRunningServiceInfoLocked(it.next()));
8668 }
8669 }
8670
8671 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8672 ServiceRecord r = mRestartingServices.get(i);
8673 ActivityManager.RunningServiceInfo info =
8674 makeRunningServiceInfoLocked(r);
8675 info.restarting = r.nextRestartTime;
8676 res.add(info);
8677 }
8678
8679 return res;
8680 }
8681 }
8682
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008683 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8684 synchronized (this) {
8685 ServiceRecord r = mServices.get(name);
8686 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008687 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8688 for (int i=0; i<conn.size(); i++) {
8689 if (conn.get(i).clientIntent != null) {
8690 return conn.get(i).clientIntent;
8691 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008692 }
8693 }
8694 }
8695 }
8696 return null;
8697 }
8698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008699 private final ServiceRecord findServiceLocked(ComponentName name,
8700 IBinder token) {
8701 ServiceRecord r = mServices.get(name);
8702 return r == token ? r : null;
8703 }
8704
8705 private final class ServiceLookupResult {
8706 final ServiceRecord record;
8707 final String permission;
8708
8709 ServiceLookupResult(ServiceRecord _record, String _permission) {
8710 record = _record;
8711 permission = _permission;
8712 }
8713 };
8714
8715 private ServiceLookupResult findServiceLocked(Intent service,
8716 String resolvedType) {
8717 ServiceRecord r = null;
8718 if (service.getComponent() != null) {
8719 r = mServices.get(service.getComponent());
8720 }
8721 if (r == null) {
8722 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8723 r = mServicesByIntent.get(filter);
8724 }
8725
8726 if (r == null) {
8727 try {
8728 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008729 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008730 service, resolvedType, 0);
8731 ServiceInfo sInfo =
8732 rInfo != null ? rInfo.serviceInfo : null;
8733 if (sInfo == null) {
8734 return null;
8735 }
8736
8737 ComponentName name = new ComponentName(
8738 sInfo.applicationInfo.packageName, sInfo.name);
8739 r = mServices.get(name);
8740 } catch (RemoteException ex) {
8741 // pm is in same process, this will never happen.
8742 }
8743 }
8744 if (r != null) {
8745 int callingPid = Binder.getCallingPid();
8746 int callingUid = Binder.getCallingUid();
8747 if (checkComponentPermission(r.permission,
8748 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8749 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008750 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008751 + " from pid=" + callingPid
8752 + ", uid=" + callingUid
8753 + " requires " + r.permission);
8754 return new ServiceLookupResult(null, r.permission);
8755 }
8756 return new ServiceLookupResult(r, null);
8757 }
8758 return null;
8759 }
8760
8761 private class ServiceRestarter implements Runnable {
8762 private ServiceRecord mService;
8763
8764 void setService(ServiceRecord service) {
8765 mService = service;
8766 }
8767
8768 public void run() {
8769 synchronized(ActivityManagerService.this) {
8770 performServiceRestartLocked(mService);
8771 }
8772 }
8773 }
8774
8775 private ServiceLookupResult retrieveServiceLocked(Intent service,
8776 String resolvedType, int callingPid, int callingUid) {
8777 ServiceRecord r = null;
8778 if (service.getComponent() != null) {
8779 r = mServices.get(service.getComponent());
8780 }
8781 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8782 r = mServicesByIntent.get(filter);
8783 if (r == null) {
8784 try {
8785 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008786 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008787 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 ServiceInfo sInfo =
8789 rInfo != null ? rInfo.serviceInfo : null;
8790 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008791 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008792 ": not found");
8793 return null;
8794 }
8795
8796 ComponentName name = new ComponentName(
8797 sInfo.applicationInfo.packageName, sInfo.name);
8798 r = mServices.get(name);
8799 if (r == null) {
8800 filter = new Intent.FilterComparison(service.cloneFilter());
8801 ServiceRestarter res = new ServiceRestarter();
8802 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8803 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8804 synchronized (stats) {
8805 ss = stats.getServiceStatsLocked(
8806 sInfo.applicationInfo.uid, sInfo.packageName,
8807 sInfo.name);
8808 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008809 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008810 res.setService(r);
8811 mServices.put(name, r);
8812 mServicesByIntent.put(filter, r);
8813
8814 // Make sure this component isn't in the pending list.
8815 int N = mPendingServices.size();
8816 for (int i=0; i<N; i++) {
8817 ServiceRecord pr = mPendingServices.get(i);
8818 if (pr.name.equals(name)) {
8819 mPendingServices.remove(i);
8820 i--;
8821 N--;
8822 }
8823 }
8824 }
8825 } catch (RemoteException ex) {
8826 // pm is in same process, this will never happen.
8827 }
8828 }
8829 if (r != null) {
8830 if (checkComponentPermission(r.permission,
8831 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8832 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008833 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008834 + " from pid=" + Binder.getCallingPid()
8835 + ", uid=" + Binder.getCallingUid()
8836 + " requires " + r.permission);
8837 return new ServiceLookupResult(null, r.permission);
8838 }
8839 return new ServiceLookupResult(r, null);
8840 }
8841 return null;
8842 }
8843
Dianne Hackborn287952c2010-09-22 22:34:31 -07008844 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8845 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8846 + why + " of " + r + " in app " + r.app);
8847 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8848 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008849 long now = SystemClock.uptimeMillis();
8850 if (r.executeNesting == 0 && r.app != null) {
8851 if (r.app.executingServices.size() == 0) {
8852 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8853 msg.obj = r.app;
8854 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8855 }
8856 r.app.executingServices.add(r);
8857 }
8858 r.executeNesting++;
8859 r.executingStart = now;
8860 }
8861
8862 private final void sendServiceArgsLocked(ServiceRecord r,
8863 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008864 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008865 if (N == 0) {
8866 return;
8867 }
8868
Dianne Hackborn39792d22010-08-19 18:01:52 -07008869 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008870 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008871 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008872 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8873 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008874 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008875 // If somehow we got a dummy start at the front, then
8876 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008877 continue;
8878 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008879 si.deliveredTime = SystemClock.uptimeMillis();
8880 r.deliveredStarts.add(si);
8881 si.deliveryCount++;
8882 if (si.targetPermissionUid >= 0) {
8883 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008884 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008885 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008886 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008887 if (!oomAdjusted) {
8888 oomAdjusted = true;
8889 updateOomAdjLocked(r.app);
8890 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008891 int flags = 0;
8892 if (si.deliveryCount > 0) {
8893 flags |= Service.START_FLAG_RETRY;
8894 }
8895 if (si.doneExecutingCount > 0) {
8896 flags |= Service.START_FLAG_REDELIVERY;
8897 }
8898 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008899 } catch (RemoteException e) {
8900 // Remote process gone... we'll let the normal cleanup take
8901 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008902 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008903 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008904 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008905 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008906 break;
8907 }
8908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008909 }
8910
8911 private final boolean requestServiceBindingLocked(ServiceRecord r,
8912 IntentBindRecord i, boolean rebind) {
8913 if (r.app == null || r.app.thread == null) {
8914 // If service is not currently running, can't yet bind.
8915 return false;
8916 }
8917 if ((!i.requested || rebind) && i.apps.size() > 0) {
8918 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008919 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008920 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8921 if (!rebind) {
8922 i.requested = true;
8923 }
8924 i.hasBound = true;
8925 i.doRebind = false;
8926 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008927 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 return false;
8929 }
8930 }
8931 return true;
8932 }
8933
8934 private final void requestServiceBindingsLocked(ServiceRecord r) {
8935 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8936 while (bindings.hasNext()) {
8937 IntentBindRecord i = bindings.next();
8938 if (!requestServiceBindingLocked(r, i, false)) {
8939 break;
8940 }
8941 }
8942 }
8943
8944 private final void realStartServiceLocked(ServiceRecord r,
8945 ProcessRecord app) throws RemoteException {
8946 if (app.thread == null) {
8947 throw new RemoteException();
8948 }
8949
8950 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008951 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008952
8953 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008954 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008955 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008956
8957 boolean created = false;
8958 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008959 mStringBuilder.setLength(0);
8960 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008961 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008963 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008964 synchronized (r.stats.getBatteryStats()) {
8965 r.stats.startLaunchedLocked();
8966 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008967 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008968 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008969 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970 created = true;
8971 } finally {
8972 if (!created) {
8973 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008974 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008975 }
8976 }
8977
8978 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008979
8980 // If the service is in the started state, and there are no
8981 // pending arguments, then fake up one so its onStartCommand() will
8982 // be called.
8983 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8984 r.lastStartId++;
8985 if (r.lastStartId < 1) {
8986 r.lastStartId = 1;
8987 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008988 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008989 }
8990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008991 sendServiceArgsLocked(r, true);
8992 }
8993
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008994 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8995 boolean allowCancel) {
8996 boolean canceled = false;
8997
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008998 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008999 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009000 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009001
9002 // Any delivered but not yet finished starts should be put back
9003 // on the pending list.
9004 final int N = r.deliveredStarts.size();
9005 if (N > 0) {
9006 for (int i=N-1; i>=0; i--) {
9007 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009008 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009009 if (si.intent == null) {
9010 // We'll generate this again if needed.
9011 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9012 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9013 r.pendingStarts.add(0, si);
9014 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9015 dur *= 2;
9016 if (minDuration < dur) minDuration = dur;
9017 if (resetTime < dur) resetTime = dur;
9018 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009019 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009020 + r.name);
9021 canceled = true;
9022 }
9023 }
9024 r.deliveredStarts.clear();
9025 }
9026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009027 r.totalRestartCount++;
9028 if (r.restartDelay == 0) {
9029 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009030 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009031 } else {
9032 // If it has been a "reasonably long time" since the service
9033 // was started, then reset our restart duration back to
9034 // the beginning, so we don't infinitely increase the duration
9035 // on a service that just occasionally gets killed (which is
9036 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009037 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009038 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009039 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009040 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009041 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009042 if (r.restartDelay < minDuration) {
9043 r.restartDelay = minDuration;
9044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009045 }
9046 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009047
9048 r.nextRestartTime = now + r.restartDelay;
9049
9050 // Make sure that we don't end up restarting a bunch of services
9051 // all at the same time.
9052 boolean repeat;
9053 do {
9054 repeat = false;
9055 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9056 ServiceRecord r2 = mRestartingServices.get(i);
9057 if (r2 != r && r.nextRestartTime
9058 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9059 && r.nextRestartTime
9060 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9061 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9062 r.restartDelay = r.nextRestartTime - now;
9063 repeat = true;
9064 break;
9065 }
9066 }
9067 } while (repeat);
9068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009069 if (!mRestartingServices.contains(r)) {
9070 mRestartingServices.add(r);
9071 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009072
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009073 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009075 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009076 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009078 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009079 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009080 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 r.shortName, r.restartDelay);
9082
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009083 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009084 }
9085
9086 final void performServiceRestartLocked(ServiceRecord r) {
9087 if (!mRestartingServices.contains(r)) {
9088 return;
9089 }
9090 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9091 }
9092
9093 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9094 if (r.restartDelay == 0) {
9095 return false;
9096 }
9097 r.resetRestartCounter();
9098 mRestartingServices.remove(r);
9099 mHandler.removeCallbacks(r.restarter);
9100 return true;
9101 }
9102
9103 private final boolean bringUpServiceLocked(ServiceRecord r,
9104 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009105 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009106 //r.dump(" ");
9107
Dianne Hackborn36124872009-10-08 16:22:03 -07009108 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009109 sendServiceArgsLocked(r, false);
9110 return true;
9111 }
9112
9113 if (!whileRestarting && r.restartDelay > 0) {
9114 // If waiting for a restart, then do nothing.
9115 return true;
9116 }
9117
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009118 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009119
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009120 // We are now bringing the service up, so no longer in the
9121 // restarting state.
9122 mRestartingServices.remove(r);
9123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009124 final String appName = r.processName;
9125 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9126 if (app != null && app.thread != null) {
9127 try {
9128 realStartServiceLocked(r, app);
9129 return true;
9130 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009131 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009132 }
9133
9134 // If a dead object exception was thrown -- fall through to
9135 // restart the application.
9136 }
9137
Dianne Hackborn36124872009-10-08 16:22:03 -07009138 // Not running -- get it started, and enqueue this service record
9139 // to be executed when the app comes up.
9140 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9141 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009142 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009143 + r.appInfo.packageName + "/"
9144 + r.appInfo.uid + " for service "
9145 + r.intent.getIntent() + ": process is bad");
9146 bringDownServiceLocked(r, true);
9147 return false;
9148 }
9149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009150 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009151 mPendingServices.add(r);
9152 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009154 return true;
9155 }
9156
9157 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009158 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009159 //r.dump(" ");
9160
9161 // Does it still need to run?
9162 if (!force && r.startRequested) {
9163 return;
9164 }
9165 if (r.connections.size() > 0) {
9166 if (!force) {
9167 // XXX should probably keep a count of the number of auto-create
9168 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009169 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009170 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009171 ArrayList<ConnectionRecord> cr = it.next();
9172 for (int i=0; i<cr.size(); i++) {
9173 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9174 return;
9175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009176 }
9177 }
9178 }
9179
9180 // Report to all of the connections that the service is no longer
9181 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009182 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009184 ArrayList<ConnectionRecord> c = it.next();
9185 for (int i=0; i<c.size(); i++) {
9186 try {
9187 c.get(i).conn.connected(r.name, null);
9188 } catch (Exception e) {
9189 Slog.w(TAG, "Failure disconnecting service " + r.name +
9190 " to connection " + c.get(i).conn.asBinder() +
9191 " (in " + c.get(i).binding.client.processName + ")", e);
9192 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009193 }
9194 }
9195 }
9196
9197 // Tell the service that it has been unbound.
9198 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9199 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9200 while (it.hasNext()) {
9201 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009202 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009203 + ": hasBound=" + ibr.hasBound);
9204 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9205 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009206 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009207 updateOomAdjLocked(r.app);
9208 ibr.hasBound = false;
9209 r.app.thread.scheduleUnbindService(r,
9210 ibr.intent.getIntent());
9211 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009212 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009213 + r.shortName, e);
9214 serviceDoneExecutingLocked(r, true);
9215 }
9216 }
9217 }
9218 }
9219
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009220 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009221 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009222 System.identityHashCode(r), r.shortName,
9223 (r.app != null) ? r.app.pid : -1);
9224
9225 mServices.remove(r.name);
9226 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009227 r.totalRestartCount = 0;
9228 unscheduleServiceRestartLocked(r);
9229
9230 // Also make sure it is not on the pending list.
9231 int N = mPendingServices.size();
9232 for (int i=0; i<N; i++) {
9233 if (mPendingServices.get(i) == r) {
9234 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009235 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009236 i--;
9237 N--;
9238 }
9239 }
9240
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009241 r.cancelNotification();
9242 r.isForeground = false;
9243 r.foregroundId = 0;
9244 r.foregroundNoti = null;
9245
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009246 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009247 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009248 r.pendingStarts.clear();
9249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 if (r.app != null) {
9251 synchronized (r.stats.getBatteryStats()) {
9252 r.stats.stopLaunchedLocked();
9253 }
9254 r.app.services.remove(r);
9255 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009256 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009257 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009258 mStoppingServices.add(r);
9259 updateOomAdjLocked(r.app);
9260 r.app.thread.scheduleStopService(r);
9261 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009262 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009263 + r.shortName, e);
9264 serviceDoneExecutingLocked(r, true);
9265 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009266 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009267 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009268 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009269 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009270 }
9271 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009272 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009273 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009274 }
9275 }
9276
9277 ComponentName startServiceLocked(IApplicationThread caller,
9278 Intent service, String resolvedType,
9279 int callingPid, int callingUid) {
9280 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009281 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009282 + " type=" + resolvedType + " args=" + service.getExtras());
9283
9284 if (caller != null) {
9285 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9286 if (callerApp == null) {
9287 throw new SecurityException(
9288 "Unable to find app for caller " + caller
9289 + " (pid=" + Binder.getCallingPid()
9290 + ") when starting service " + service);
9291 }
9292 }
9293
9294 ServiceLookupResult res =
9295 retrieveServiceLocked(service, resolvedType,
9296 callingPid, callingUid);
9297 if (res == null) {
9298 return null;
9299 }
9300 if (res.record == null) {
9301 return new ComponentName("!", res.permission != null
9302 ? res.permission : "private to package");
9303 }
9304 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009305 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9306 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009307 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009308 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009309 }
9310 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009311 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 r.lastStartId++;
9313 if (r.lastStartId < 1) {
9314 r.lastStartId = 1;
9315 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009316 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9317 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009318 r.lastActivity = SystemClock.uptimeMillis();
9319 synchronized (r.stats.getBatteryStats()) {
9320 r.stats.startRunningLocked();
9321 }
9322 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9323 return new ComponentName("!", "Service process is bad");
9324 }
9325 return r.name;
9326 }
9327 }
9328
9329 public ComponentName startService(IApplicationThread caller, Intent service,
9330 String resolvedType) {
9331 // Refuse possible leaked file descriptors
9332 if (service != null && service.hasFileDescriptors() == true) {
9333 throw new IllegalArgumentException("File descriptors passed in Intent");
9334 }
9335
9336 synchronized(this) {
9337 final int callingPid = Binder.getCallingPid();
9338 final int callingUid = Binder.getCallingUid();
9339 final long origId = Binder.clearCallingIdentity();
9340 ComponentName res = startServiceLocked(caller, service,
9341 resolvedType, callingPid, callingUid);
9342 Binder.restoreCallingIdentity(origId);
9343 return res;
9344 }
9345 }
9346
9347 ComponentName startServiceInPackage(int uid,
9348 Intent service, String resolvedType) {
9349 synchronized(this) {
9350 final long origId = Binder.clearCallingIdentity();
9351 ComponentName res = startServiceLocked(null, service,
9352 resolvedType, -1, uid);
9353 Binder.restoreCallingIdentity(origId);
9354 return res;
9355 }
9356 }
9357
9358 public int stopService(IApplicationThread caller, Intent service,
9359 String resolvedType) {
9360 // Refuse possible leaked file descriptors
9361 if (service != null && service.hasFileDescriptors() == true) {
9362 throw new IllegalArgumentException("File descriptors passed in Intent");
9363 }
9364
9365 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009366 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009367 + " type=" + resolvedType);
9368
9369 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9370 if (caller != null && callerApp == null) {
9371 throw new SecurityException(
9372 "Unable to find app for caller " + caller
9373 + " (pid=" + Binder.getCallingPid()
9374 + ") when stopping service " + service);
9375 }
9376
9377 // If this service is active, make sure it is stopped.
9378 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9379 if (r != null) {
9380 if (r.record != null) {
9381 synchronized (r.record.stats.getBatteryStats()) {
9382 r.record.stats.stopRunningLocked();
9383 }
9384 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009385 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009386 final long origId = Binder.clearCallingIdentity();
9387 bringDownServiceLocked(r.record, false);
9388 Binder.restoreCallingIdentity(origId);
9389 return 1;
9390 }
9391 return -1;
9392 }
9393 }
9394
9395 return 0;
9396 }
9397
9398 public IBinder peekService(Intent service, String resolvedType) {
9399 // Refuse possible leaked file descriptors
9400 if (service != null && service.hasFileDescriptors() == true) {
9401 throw new IllegalArgumentException("File descriptors passed in Intent");
9402 }
9403
9404 IBinder ret = null;
9405
9406 synchronized(this) {
9407 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9408
9409 if (r != null) {
9410 // r.record is null if findServiceLocked() failed the caller permission check
9411 if (r.record == null) {
9412 throw new SecurityException(
9413 "Permission Denial: Accessing service " + r.record.name
9414 + " from pid=" + Binder.getCallingPid()
9415 + ", uid=" + Binder.getCallingUid()
9416 + " requires " + r.permission);
9417 }
9418 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9419 if (ib != null) {
9420 ret = ib.binder;
9421 }
9422 }
9423 }
9424
9425 return ret;
9426 }
9427
9428 public boolean stopServiceToken(ComponentName className, IBinder token,
9429 int startId) {
9430 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009431 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009432 + " " + token + " startId=" + startId);
9433 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009434 if (r != null) {
9435 if (startId >= 0) {
9436 // Asked to only stop if done with all work. Note that
9437 // to avoid leaks, we will take this as dropping all
9438 // start items up to and including this one.
9439 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9440 if (si != null) {
9441 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009442 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9443 cur.removeUriPermissionsLocked();
9444 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009445 break;
9446 }
9447 }
9448 }
9449
9450 if (r.lastStartId != startId) {
9451 return false;
9452 }
9453
9454 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009455 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009456 + " is last, but have " + r.deliveredStarts.size()
9457 + " remaining args");
9458 }
9459 }
9460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009461 synchronized (r.stats.getBatteryStats()) {
9462 r.stats.stopRunningLocked();
9463 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009464 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009465 }
9466 final long origId = Binder.clearCallingIdentity();
9467 bringDownServiceLocked(r, false);
9468 Binder.restoreCallingIdentity(origId);
9469 return true;
9470 }
9471 }
9472 return false;
9473 }
9474
9475 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009476 int id, Notification notification, boolean removeNotification) {
9477 final long origId = Binder.clearCallingIdentity();
9478 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 synchronized(this) {
9480 ServiceRecord r = findServiceLocked(className, token);
9481 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009482 if (id != 0) {
9483 if (notification == null) {
9484 throw new IllegalArgumentException("null notification");
9485 }
9486 if (r.foregroundId != id) {
9487 r.cancelNotification();
9488 r.foregroundId = id;
9489 }
9490 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9491 r.foregroundNoti = notification;
9492 r.isForeground = true;
9493 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009494 if (r.app != null) {
9495 updateServiceForegroundLocked(r.app, true);
9496 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009497 } else {
9498 if (r.isForeground) {
9499 r.isForeground = false;
9500 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009501 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009502 updateServiceForegroundLocked(r.app, true);
9503 }
9504 }
9505 if (removeNotification) {
9506 r.cancelNotification();
9507 r.foregroundId = 0;
9508 r.foregroundNoti = null;
9509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009510 }
9511 }
9512 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009513 } finally {
9514 Binder.restoreCallingIdentity(origId);
9515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009516 }
9517
9518 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9519 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009520 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009521 if (sr.isForeground) {
9522 anyForeground = true;
9523 break;
9524 }
9525 }
9526 if (anyForeground != proc.foregroundServices) {
9527 proc.foregroundServices = anyForeground;
9528 if (oomAdj) {
9529 updateOomAdjLocked();
9530 }
9531 }
9532 }
9533
9534 public int bindService(IApplicationThread caller, IBinder token,
9535 Intent service, String resolvedType,
9536 IServiceConnection connection, int flags) {
9537 // Refuse possible leaked file descriptors
9538 if (service != null && service.hasFileDescriptors() == true) {
9539 throw new IllegalArgumentException("File descriptors passed in Intent");
9540 }
9541
9542 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009543 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009544 + " type=" + resolvedType + " conn=" + connection.asBinder()
9545 + " flags=0x" + Integer.toHexString(flags));
9546 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9547 if (callerApp == null) {
9548 throw new SecurityException(
9549 "Unable to find app for caller " + caller
9550 + " (pid=" + Binder.getCallingPid()
9551 + ") when binding service " + service);
9552 }
9553
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009554 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009555 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009556 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009557 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009558 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009559 return 0;
9560 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009561 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009562 }
9563
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009564 int clientLabel = 0;
9565 PendingIntent clientIntent = null;
9566
9567 if (callerApp.info.uid == Process.SYSTEM_UID) {
9568 // Hacky kind of thing -- allow system stuff to tell us
9569 // what they are, so we can report this elsewhere for
9570 // others to know why certain services are running.
9571 try {
9572 clientIntent = (PendingIntent)service.getParcelableExtra(
9573 Intent.EXTRA_CLIENT_INTENT);
9574 } catch (RuntimeException e) {
9575 }
9576 if (clientIntent != null) {
9577 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9578 if (clientLabel != 0) {
9579 // There are no useful extras in the intent, trash them.
9580 // System code calling with this stuff just needs to know
9581 // this will happen.
9582 service = service.cloneFilter();
9583 }
9584 }
9585 }
9586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009587 ServiceLookupResult res =
9588 retrieveServiceLocked(service, resolvedType,
9589 Binder.getCallingPid(), Binder.getCallingUid());
9590 if (res == null) {
9591 return 0;
9592 }
9593 if (res.record == null) {
9594 return -1;
9595 }
9596 ServiceRecord s = res.record;
9597
9598 final long origId = Binder.clearCallingIdentity();
9599
9600 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009601 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009602 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009603 }
9604
9605 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9606 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009607 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009608
9609 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009610 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9611 if (clist == null) {
9612 clist = new ArrayList<ConnectionRecord>();
9613 s.connections.put(binder, clist);
9614 }
9615 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009616 b.connections.add(c);
9617 if (activity != null) {
9618 if (activity.connections == null) {
9619 activity.connections = new HashSet<ConnectionRecord>();
9620 }
9621 activity.connections.add(c);
9622 }
9623 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009624 clist = mServiceConnections.get(binder);
9625 if (clist == null) {
9626 clist = new ArrayList<ConnectionRecord>();
9627 mServiceConnections.put(binder, clist);
9628 }
9629 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009630
9631 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9632 s.lastActivity = SystemClock.uptimeMillis();
9633 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9634 return 0;
9635 }
9636 }
9637
9638 if (s.app != null) {
9639 // This could have made the service more important.
9640 updateOomAdjLocked(s.app);
9641 }
9642
Joe Onorato8a9b2202010-02-26 18:56:32 -08009643 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009644 + ": received=" + b.intent.received
9645 + " apps=" + b.intent.apps.size()
9646 + " doRebind=" + b.intent.doRebind);
9647
9648 if (s.app != null && b.intent.received) {
9649 // Service is already running, so we can immediately
9650 // publish the connection.
9651 try {
9652 c.conn.connected(s.name, b.intent.binder);
9653 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009654 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009655 + " to connection " + c.conn.asBinder()
9656 + " (in " + c.binding.client.processName + ")", e);
9657 }
9658
9659 // If this is the first app connected back to this binding,
9660 // and the service had previously asked to be told when
9661 // rebound, then do so.
9662 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9663 requestServiceBindingLocked(s, b.intent, true);
9664 }
9665 } else if (!b.intent.requested) {
9666 requestServiceBindingLocked(s, b.intent, false);
9667 }
9668
9669 Binder.restoreCallingIdentity(origId);
9670 }
9671
9672 return 1;
9673 }
9674
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009675 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009676 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009677 IBinder binder = c.conn.asBinder();
9678 AppBindRecord b = c.binding;
9679 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009680 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9681 if (clist != null) {
9682 clist.remove(c);
9683 if (clist.size() == 0) {
9684 s.connections.remove(binder);
9685 }
9686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009687 b.connections.remove(c);
9688 if (c.activity != null && c.activity != skipAct) {
9689 if (c.activity.connections != null) {
9690 c.activity.connections.remove(c);
9691 }
9692 }
9693 if (b.client != skipApp) {
9694 b.client.connections.remove(c);
9695 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009696 clist = mServiceConnections.get(binder);
9697 if (clist != null) {
9698 clist.remove(c);
9699 if (clist.size() == 0) {
9700 mServiceConnections.remove(binder);
9701 }
9702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009703
9704 if (b.connections.size() == 0) {
9705 b.intent.apps.remove(b.client);
9706 }
9707
Joe Onorato8a9b2202010-02-26 18:56:32 -08009708 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009709 + ": shouldUnbind=" + b.intent.hasBound);
9710 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9711 && b.intent.hasBound) {
9712 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009713 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009714 updateOomAdjLocked(s.app);
9715 b.intent.hasBound = false;
9716 // Assume the client doesn't want to know about a rebind;
9717 // we will deal with that later if it asks for one.
9718 b.intent.doRebind = false;
9719 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9720 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009721 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009722 serviceDoneExecutingLocked(s, true);
9723 }
9724 }
9725
9726 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9727 bringDownServiceLocked(s, false);
9728 }
9729 }
9730
9731 public boolean unbindService(IServiceConnection connection) {
9732 synchronized (this) {
9733 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009734 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009735 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9736 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009737 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009738 + connection.asBinder());
9739 return false;
9740 }
9741
9742 final long origId = Binder.clearCallingIdentity();
9743
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009744 while (clist.size() > 0) {
9745 ConnectionRecord r = clist.get(0);
9746 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009747
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009748 if (r.binding.service.app != null) {
9749 // This could have made the service less important.
9750 updateOomAdjLocked(r.binding.service.app);
9751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009752 }
9753
9754 Binder.restoreCallingIdentity(origId);
9755 }
9756
9757 return true;
9758 }
9759
9760 public void publishService(IBinder token, Intent intent, IBinder service) {
9761 // Refuse possible leaked file descriptors
9762 if (intent != null && intent.hasFileDescriptors() == true) {
9763 throw new IllegalArgumentException("File descriptors passed in Intent");
9764 }
9765
9766 synchronized(this) {
9767 if (!(token instanceof ServiceRecord)) {
9768 throw new IllegalArgumentException("Invalid service token");
9769 }
9770 ServiceRecord r = (ServiceRecord)token;
9771
9772 final long origId = Binder.clearCallingIdentity();
9773
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009774 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009775 + " " + intent + ": " + service);
9776 if (r != null) {
9777 Intent.FilterComparison filter
9778 = new Intent.FilterComparison(intent);
9779 IntentBindRecord b = r.bindings.get(filter);
9780 if (b != null && !b.received) {
9781 b.binder = service;
9782 b.requested = true;
9783 b.received = true;
9784 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009785 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009786 = r.connections.values().iterator();
9787 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009788 ArrayList<ConnectionRecord> clist = it.next();
9789 for (int i=0; i<clist.size(); i++) {
9790 ConnectionRecord c = clist.get(i);
9791 if (!filter.equals(c.binding.intent.intent)) {
9792 if (DEBUG_SERVICE) Slog.v(
9793 TAG, "Not publishing to: " + c);
9794 if (DEBUG_SERVICE) Slog.v(
9795 TAG, "Bound intent: " + c.binding.intent.intent);
9796 if (DEBUG_SERVICE) Slog.v(
9797 TAG, "Published intent: " + intent);
9798 continue;
9799 }
9800 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9801 try {
9802 c.conn.connected(r.name, service);
9803 } catch (Exception e) {
9804 Slog.w(TAG, "Failure sending service " + r.name +
9805 " to connection " + c.conn.asBinder() +
9806 " (in " + c.binding.client.processName + ")", e);
9807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009808 }
9809 }
9810 }
9811 }
9812
9813 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9814
9815 Binder.restoreCallingIdentity(origId);
9816 }
9817 }
9818 }
9819
9820 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9821 // Refuse possible leaked file descriptors
9822 if (intent != null && intent.hasFileDescriptors() == true) {
9823 throw new IllegalArgumentException("File descriptors passed in Intent");
9824 }
9825
9826 synchronized(this) {
9827 if (!(token instanceof ServiceRecord)) {
9828 throw new IllegalArgumentException("Invalid service token");
9829 }
9830 ServiceRecord r = (ServiceRecord)token;
9831
9832 final long origId = Binder.clearCallingIdentity();
9833
9834 if (r != null) {
9835 Intent.FilterComparison filter
9836 = new Intent.FilterComparison(intent);
9837 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009838 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839 + " at " + b + ": apps="
9840 + (b != null ? b.apps.size() : 0));
9841 if (b != null) {
9842 if (b.apps.size() > 0) {
9843 // Applications have already bound since the last
9844 // unbind, so just rebind right here.
9845 requestServiceBindingLocked(r, b, true);
9846 } else {
9847 // Note to tell the service the next time there is
9848 // a new client.
9849 b.doRebind = true;
9850 }
9851 }
9852
9853 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9854
9855 Binder.restoreCallingIdentity(origId);
9856 }
9857 }
9858 }
9859
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009860 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009861 synchronized(this) {
9862 if (!(token instanceof ServiceRecord)) {
9863 throw new IllegalArgumentException("Invalid service token");
9864 }
9865 ServiceRecord r = (ServiceRecord)token;
9866 boolean inStopping = mStoppingServices.contains(token);
9867 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009869 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009870 + " with incorrect token: given " + token
9871 + ", expected " + r);
9872 return;
9873 }
9874
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009875 if (type == 1) {
9876 // This is a call from a service start... take care of
9877 // book-keeping.
9878 r.callStart = true;
9879 switch (res) {
9880 case Service.START_STICKY_COMPATIBILITY:
9881 case Service.START_STICKY: {
9882 // We are done with the associated start arguments.
9883 r.findDeliveredStart(startId, true);
9884 // Don't stop if killed.
9885 r.stopIfKilled = false;
9886 break;
9887 }
9888 case Service.START_NOT_STICKY: {
9889 // We are done with the associated start arguments.
9890 r.findDeliveredStart(startId, true);
9891 if (r.lastStartId == startId) {
9892 // There is no more work, and this service
9893 // doesn't want to hang around if killed.
9894 r.stopIfKilled = true;
9895 }
9896 break;
9897 }
9898 case Service.START_REDELIVER_INTENT: {
9899 // We'll keep this item until they explicitly
9900 // call stop for it, but keep track of the fact
9901 // that it was delivered.
9902 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9903 if (si != null) {
9904 si.deliveryCount = 0;
9905 si.doneExecutingCount++;
9906 // Don't stop if killed.
9907 r.stopIfKilled = true;
9908 }
9909 break;
9910 }
9911 default:
9912 throw new IllegalArgumentException(
9913 "Unknown service start result: " + res);
9914 }
9915 if (res == Service.START_STICKY_COMPATIBILITY) {
9916 r.callStart = false;
9917 }
9918 }
9919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009920 final long origId = Binder.clearCallingIdentity();
9921 serviceDoneExecutingLocked(r, inStopping);
9922 Binder.restoreCallingIdentity(origId);
9923 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009924 Slog.w(TAG, "Done executing unknown service from pid "
9925 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009926 }
9927 }
9928 }
9929
9930 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009931 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9932 + ": nesting=" + r.executeNesting
9933 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009934 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009935 r.executeNesting--;
9936 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009937 if (DEBUG_SERVICE) Slog.v(TAG,
9938 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009939 r.app.executingServices.remove(r);
9940 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009941 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9942 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9944 }
9945 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009946 if (DEBUG_SERVICE) Slog.v(TAG,
9947 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009948 mStoppingServices.remove(r);
9949 }
9950 updateOomAdjLocked(r.app);
9951 }
9952 }
9953
9954 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009955 String anrMessage = null;
9956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009957 synchronized(this) {
9958 if (proc.executingServices.size() == 0 || proc.thread == null) {
9959 return;
9960 }
9961 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9962 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9963 ServiceRecord timeout = null;
9964 long nextTime = 0;
9965 while (it.hasNext()) {
9966 ServiceRecord sr = it.next();
9967 if (sr.executingStart < maxTime) {
9968 timeout = sr;
9969 break;
9970 }
9971 if (sr.executingStart > nextTime) {
9972 nextTime = sr.executingStart;
9973 }
9974 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009975 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009976 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009977 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009978 } else {
9979 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9980 msg.obj = proc;
9981 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9982 }
9983 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009984
9985 if (anrMessage != null) {
9986 appNotResponding(proc, null, null, anrMessage);
9987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009988 }
9989
9990 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009991 // BACKUP AND RESTORE
9992 // =========================================================
9993
9994 // Cause the target app to be launched if necessary and its backup agent
9995 // instantiated. The backup agent will invoke backupAgentCreated() on the
9996 // activity manager to announce its creation.
9997 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009998 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009999 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10000
10001 synchronized(this) {
10002 // !!! TODO: currently no check here that we're already bound
10003 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10004 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10005 synchronized (stats) {
10006 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10007 }
10008
10009 BackupRecord r = new BackupRecord(ss, app, backupMode);
10010 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10011 // startProcessLocked() returns existing proc's record if it's already running
10012 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010013 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010014 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010015 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010016 return false;
10017 }
10018
10019 r.app = proc;
10020 mBackupTarget = r;
10021 mBackupAppName = app.packageName;
10022
Christopher Tate6fa95972009-06-05 18:43:55 -070010023 // Try not to kill the process during backup
10024 updateOomAdjLocked(proc);
10025
Christopher Tate181fafa2009-05-14 11:12:14 -070010026 // If the process is already attached, schedule the creation of the backup agent now.
10027 // If it is not yet live, this will be done when it attaches to the framework.
10028 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010029 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010030 try {
10031 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10032 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010033 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010034 }
10035 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010036 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010037 }
10038 // Invariants: at this point, the target app process exists and the application
10039 // is either already running or in the process of coming up. mBackupTarget and
10040 // mBackupAppName describe the app, so that when it binds back to the AM we
10041 // know that it's scheduled for a backup-agent operation.
10042 }
10043
10044 return true;
10045 }
10046
10047 // A backup agent has just come up
10048 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010049 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010050 + " = " + agent);
10051
10052 synchronized(this) {
10053 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010054 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010055 return;
10056 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010057 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010058
Dianne Hackborn06740692010-09-22 22:46:21 -070010059 long oldIdent = Binder.clearCallingIdentity();
10060 try {
10061 IBackupManager bm = IBackupManager.Stub.asInterface(
10062 ServiceManager.getService(Context.BACKUP_SERVICE));
10063 bm.agentConnected(agentPackageName, agent);
10064 } catch (RemoteException e) {
10065 // can't happen; the backup manager service is local
10066 } catch (Exception e) {
10067 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10068 e.printStackTrace();
10069 } finally {
10070 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010071 }
10072 }
10073
10074 // done with this agent
10075 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010076 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010077 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010078 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010079 return;
10080 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010081
10082 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010083 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010084 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010085 return;
10086 }
10087
Christopher Tate181fafa2009-05-14 11:12:14 -070010088 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010089 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010090 return;
10091 }
10092
Christopher Tate6fa95972009-06-05 18:43:55 -070010093 ProcessRecord proc = mBackupTarget.app;
10094 mBackupTarget = null;
10095 mBackupAppName = null;
10096
10097 // Not backing this app up any more; reset its OOM adjustment
10098 updateOomAdjLocked(proc);
10099
Christopher Tatec7b31e32009-06-10 15:49:30 -070010100 // If the app crashed during backup, 'thread' will be null here
10101 if (proc.thread != null) {
10102 try {
10103 proc.thread.scheduleDestroyBackupAgent(appInfo);
10104 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010105 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010106 e.printStackTrace();
10107 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010108 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010109 }
10110 }
10111 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010112 // BROADCASTS
10113 // =========================================================
10114
Josh Bartel7f208742010-02-25 11:01:44 -060010115 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010116 List cur) {
10117 final ContentResolver resolver = mContext.getContentResolver();
10118 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10119 if (list == null) {
10120 return cur;
10121 }
10122 int N = list.size();
10123 for (int i=0; i<N; i++) {
10124 Intent intent = list.get(i);
10125 if (filter.match(resolver, intent, true, TAG) >= 0) {
10126 if (cur == null) {
10127 cur = new ArrayList<Intent>();
10128 }
10129 cur.add(intent);
10130 }
10131 }
10132 return cur;
10133 }
10134
10135 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010136 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010137 + mBroadcastsScheduled);
10138
10139 if (mBroadcastsScheduled) {
10140 return;
10141 }
10142 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10143 mBroadcastsScheduled = true;
10144 }
10145
10146 public Intent registerReceiver(IApplicationThread caller,
10147 IIntentReceiver receiver, IntentFilter filter, String permission) {
10148 synchronized(this) {
10149 ProcessRecord callerApp = null;
10150 if (caller != null) {
10151 callerApp = getRecordForAppLocked(caller);
10152 if (callerApp == null) {
10153 throw new SecurityException(
10154 "Unable to find app for caller " + caller
10155 + " (pid=" + Binder.getCallingPid()
10156 + ") when registering receiver " + receiver);
10157 }
10158 }
10159
10160 List allSticky = null;
10161
10162 // Look for any matching sticky broadcasts...
10163 Iterator actions = filter.actionsIterator();
10164 if (actions != null) {
10165 while (actions.hasNext()) {
10166 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010167 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010168 }
10169 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010170 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010171 }
10172
10173 // The first sticky in the list is returned directly back to
10174 // the client.
10175 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10176
Joe Onorato8a9b2202010-02-26 18:56:32 -080010177 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010178 + ": " + sticky);
10179
10180 if (receiver == null) {
10181 return sticky;
10182 }
10183
10184 ReceiverList rl
10185 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10186 if (rl == null) {
10187 rl = new ReceiverList(this, callerApp,
10188 Binder.getCallingPid(),
10189 Binder.getCallingUid(), receiver);
10190 if (rl.app != null) {
10191 rl.app.receivers.add(rl);
10192 } else {
10193 try {
10194 receiver.asBinder().linkToDeath(rl, 0);
10195 } catch (RemoteException e) {
10196 return sticky;
10197 }
10198 rl.linkedToDeath = true;
10199 }
10200 mRegisteredReceivers.put(receiver.asBinder(), rl);
10201 }
10202 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10203 rl.add(bf);
10204 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010205 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010206 }
10207 mReceiverResolver.addFilter(bf);
10208
10209 // Enqueue broadcasts for all existing stickies that match
10210 // this filter.
10211 if (allSticky != null) {
10212 ArrayList receivers = new ArrayList();
10213 receivers.add(bf);
10214
10215 int N = allSticky.size();
10216 for (int i=0; i<N; i++) {
10217 Intent intent = (Intent)allSticky.get(i);
10218 BroadcastRecord r = new BroadcastRecord(intent, null,
10219 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010220 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010221 if (mParallelBroadcasts.size() == 0) {
10222 scheduleBroadcastsLocked();
10223 }
10224 mParallelBroadcasts.add(r);
10225 }
10226 }
10227
10228 return sticky;
10229 }
10230 }
10231
10232 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010233 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234
10235 boolean doNext = false;
10236
10237 synchronized(this) {
10238 ReceiverList rl
10239 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10240 if (rl != null) {
10241 if (rl.curBroadcast != null) {
10242 BroadcastRecord r = rl.curBroadcast;
10243 doNext = finishReceiverLocked(
10244 receiver.asBinder(), r.resultCode, r.resultData,
10245 r.resultExtras, r.resultAbort, true);
10246 }
10247
10248 if (rl.app != null) {
10249 rl.app.receivers.remove(rl);
10250 }
10251 removeReceiverLocked(rl);
10252 if (rl.linkedToDeath) {
10253 rl.linkedToDeath = false;
10254 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10255 }
10256 }
10257 }
10258
10259 if (!doNext) {
10260 return;
10261 }
10262
10263 final long origId = Binder.clearCallingIdentity();
10264 processNextBroadcast(false);
10265 trimApplications();
10266 Binder.restoreCallingIdentity(origId);
10267 }
10268
10269 void removeReceiverLocked(ReceiverList rl) {
10270 mRegisteredReceivers.remove(rl.receiver.asBinder());
10271 int N = rl.size();
10272 for (int i=0; i<N; i++) {
10273 mReceiverResolver.removeFilter(rl.get(i));
10274 }
10275 }
10276
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010277 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10278 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10279 ProcessRecord r = mLruProcesses.get(i);
10280 if (r.thread != null) {
10281 try {
10282 r.thread.dispatchPackageBroadcast(cmd, packages);
10283 } catch (RemoteException ex) {
10284 }
10285 }
10286 }
10287 }
10288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010289 private final int broadcastIntentLocked(ProcessRecord callerApp,
10290 String callerPackage, Intent intent, String resolvedType,
10291 IIntentReceiver resultTo, int resultCode, String resultData,
10292 Bundle map, String requiredPermission,
10293 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10294 intent = new Intent(intent);
10295
Joe Onorato8a9b2202010-02-26 18:56:32 -080010296 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010297 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10298 + " ordered=" + ordered);
10299 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010300 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 }
10302
10303 // Handle special intents: if this broadcast is from the package
10304 // manager about a package being removed, we need to remove all of
10305 // its activities from the history stack.
10306 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10307 intent.getAction());
10308 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10309 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010310 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010311 || uidRemoved) {
10312 if (checkComponentPermission(
10313 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10314 callingPid, callingUid, -1)
10315 == PackageManager.PERMISSION_GRANTED) {
10316 if (uidRemoved) {
10317 final Bundle intentExtras = intent.getExtras();
10318 final int uid = intentExtras != null
10319 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10320 if (uid >= 0) {
10321 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10322 synchronized (bs) {
10323 bs.removeUidStatsLocked(uid);
10324 }
10325 }
10326 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010327 // If resources are unvailble just force stop all
10328 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010329 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010330 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10331 if (list != null && (list.length > 0)) {
10332 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010333 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010334 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010335 sendPackageBroadcastLocked(
10336 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010337 }
10338 } else {
10339 Uri data = intent.getData();
10340 String ssp;
10341 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10342 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10343 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010344 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010345 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010346 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10347 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10348 new String[] {ssp});
10349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010350 }
10351 }
10352 }
10353 } else {
10354 String msg = "Permission Denial: " + intent.getAction()
10355 + " broadcast from " + callerPackage + " (pid=" + callingPid
10356 + ", uid=" + callingUid + ")"
10357 + " requires "
10358 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010359 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010360 throw new SecurityException(msg);
10361 }
10362 }
10363
10364 /*
10365 * If this is the time zone changed action, queue up a message that will reset the timezone
10366 * of all currently running processes. This message will get queued up before the broadcast
10367 * happens.
10368 */
10369 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10370 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10371 }
10372
Dianne Hackborn854060af2009-07-09 18:14:31 -070010373 /*
10374 * Prevent non-system code (defined here to be non-persistent
10375 * processes) from sending protected broadcasts.
10376 */
10377 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10378 || callingUid == Process.SHELL_UID || callingUid == 0) {
10379 // Always okay.
10380 } else if (callerApp == null || !callerApp.persistent) {
10381 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010382 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010383 intent.getAction())) {
10384 String msg = "Permission Denial: not allowed to send broadcast "
10385 + intent.getAction() + " from pid="
10386 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010387 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010388 throw new SecurityException(msg);
10389 }
10390 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010391 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010392 return BROADCAST_SUCCESS;
10393 }
10394 }
10395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010396 // Add to the sticky list if requested.
10397 if (sticky) {
10398 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10399 callingPid, callingUid)
10400 != PackageManager.PERMISSION_GRANTED) {
10401 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10402 + callingPid + ", uid=" + callingUid
10403 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010404 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010405 throw new SecurityException(msg);
10406 }
10407 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010408 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010409 + " and enforce permission " + requiredPermission);
10410 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10411 }
10412 if (intent.getComponent() != null) {
10413 throw new SecurityException(
10414 "Sticky broadcasts can't target a specific component");
10415 }
10416 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10417 if (list == null) {
10418 list = new ArrayList<Intent>();
10419 mStickyBroadcasts.put(intent.getAction(), list);
10420 }
10421 int N = list.size();
10422 int i;
10423 for (i=0; i<N; i++) {
10424 if (intent.filterEquals(list.get(i))) {
10425 // This sticky already exists, replace it.
10426 list.set(i, new Intent(intent));
10427 break;
10428 }
10429 }
10430 if (i >= N) {
10431 list.add(new Intent(intent));
10432 }
10433 }
10434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435 // Figure out who all will receive this broadcast.
10436 List receivers = null;
10437 List<BroadcastFilter> registeredReceivers = null;
10438 try {
10439 if (intent.getComponent() != null) {
10440 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010441 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010442 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 if (ai != null) {
10444 receivers = new ArrayList();
10445 ResolveInfo ri = new ResolveInfo();
10446 ri.activityInfo = ai;
10447 receivers.add(ri);
10448 }
10449 } else {
10450 // Need to resolve the intent to interested receivers...
10451 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10452 == 0) {
10453 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010454 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010455 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456 }
Mihai Preda074edef2009-05-18 17:13:31 +020010457 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010458 }
10459 } catch (RemoteException ex) {
10460 // pm is in same process, this will never happen.
10461 }
10462
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010463 final boolean replacePending =
10464 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10465
Joe Onorato8a9b2202010-02-26 18:56:32 -080010466 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010467 + " replacePending=" + replacePending);
10468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010469 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10470 if (!ordered && NR > 0) {
10471 // If we are not serializing this broadcast, then send the
10472 // registered receivers separately so they don't wait for the
10473 // components to be launched.
10474 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10475 callerPackage, callingPid, callingUid, requiredPermission,
10476 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010477 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010478 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 TAG, "Enqueueing parallel broadcast " + r
10480 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010481 boolean replaced = false;
10482 if (replacePending) {
10483 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10484 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010485 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010486 "***** DROPPING PARALLEL: " + intent);
10487 mParallelBroadcasts.set(i, r);
10488 replaced = true;
10489 break;
10490 }
10491 }
10492 }
10493 if (!replaced) {
10494 mParallelBroadcasts.add(r);
10495 scheduleBroadcastsLocked();
10496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010497 registeredReceivers = null;
10498 NR = 0;
10499 }
10500
10501 // Merge into one list.
10502 int ir = 0;
10503 if (receivers != null) {
10504 // A special case for PACKAGE_ADDED: do not allow the package
10505 // being added to see this broadcast. This prevents them from
10506 // using this as a back door to get run as soon as they are
10507 // installed. Maybe in the future we want to have a special install
10508 // broadcast or such for apps, but we'd like to deliberately make
10509 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010510 String skipPackages[] = null;
10511 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10512 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10513 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10514 Uri data = intent.getData();
10515 if (data != null) {
10516 String pkgName = data.getSchemeSpecificPart();
10517 if (pkgName != null) {
10518 skipPackages = new String[] { pkgName };
10519 }
10520 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010521 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010522 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010523 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010524 if (skipPackages != null && (skipPackages.length > 0)) {
10525 for (String skipPackage : skipPackages) {
10526 if (skipPackage != null) {
10527 int NT = receivers.size();
10528 for (int it=0; it<NT; it++) {
10529 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10530 if (curt.activityInfo.packageName.equals(skipPackage)) {
10531 receivers.remove(it);
10532 it--;
10533 NT--;
10534 }
10535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010536 }
10537 }
10538 }
10539
10540 int NT = receivers != null ? receivers.size() : 0;
10541 int it = 0;
10542 ResolveInfo curt = null;
10543 BroadcastFilter curr = null;
10544 while (it < NT && ir < NR) {
10545 if (curt == null) {
10546 curt = (ResolveInfo)receivers.get(it);
10547 }
10548 if (curr == null) {
10549 curr = registeredReceivers.get(ir);
10550 }
10551 if (curr.getPriority() >= curt.priority) {
10552 // Insert this broadcast record into the final list.
10553 receivers.add(it, curr);
10554 ir++;
10555 curr = null;
10556 it++;
10557 NT++;
10558 } else {
10559 // Skip to the next ResolveInfo in the final list.
10560 it++;
10561 curt = null;
10562 }
10563 }
10564 }
10565 while (ir < NR) {
10566 if (receivers == null) {
10567 receivers = new ArrayList();
10568 }
10569 receivers.add(registeredReceivers.get(ir));
10570 ir++;
10571 }
10572
10573 if ((receivers != null && receivers.size() > 0)
10574 || resultTo != null) {
10575 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10576 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010577 receivers, resultTo, resultCode, resultData, map, ordered,
10578 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010579 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010580 TAG, "Enqueueing ordered broadcast " + r
10581 + ": prev had " + mOrderedBroadcasts.size());
10582 if (DEBUG_BROADCAST) {
10583 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010584 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010586 boolean replaced = false;
10587 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010588 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010589 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010590 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010591 "***** DROPPING ORDERED: " + intent);
10592 mOrderedBroadcasts.set(i, r);
10593 replaced = true;
10594 break;
10595 }
10596 }
10597 }
10598 if (!replaced) {
10599 mOrderedBroadcasts.add(r);
10600 scheduleBroadcastsLocked();
10601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010602 }
10603
10604 return BROADCAST_SUCCESS;
10605 }
10606
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010607 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010608 // Refuse possible leaked file descriptors
10609 if (intent != null && intent.hasFileDescriptors() == true) {
10610 throw new IllegalArgumentException("File descriptors passed in Intent");
10611 }
10612
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010613 int flags = intent.getFlags();
10614
10615 if (!mProcessesReady) {
10616 // if the caller really truly claims to know what they're doing, go
10617 // ahead and allow the broadcast without launching any receivers
10618 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10619 intent = new Intent(intent);
10620 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10621 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10622 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10623 + " before boot completion");
10624 throw new IllegalStateException("Cannot broadcast before boot completed");
10625 }
10626 }
10627
10628 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10629 throw new IllegalArgumentException(
10630 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10631 }
10632
10633 return intent;
10634 }
10635
10636 public final int broadcastIntent(IApplicationThread caller,
10637 Intent intent, String resolvedType, IIntentReceiver resultTo,
10638 int resultCode, String resultData, Bundle map,
10639 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010640 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010641 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010643 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10644 final int callingPid = Binder.getCallingPid();
10645 final int callingUid = Binder.getCallingUid();
10646 final long origId = Binder.clearCallingIdentity();
10647 int res = broadcastIntentLocked(callerApp,
10648 callerApp != null ? callerApp.info.packageName : null,
10649 intent, resolvedType, resultTo,
10650 resultCode, resultData, map, requiredPermission, serialized,
10651 sticky, callingPid, callingUid);
10652 Binder.restoreCallingIdentity(origId);
10653 return res;
10654 }
10655 }
10656
10657 int broadcastIntentInPackage(String packageName, int uid,
10658 Intent intent, String resolvedType, IIntentReceiver resultTo,
10659 int resultCode, String resultData, Bundle map,
10660 String requiredPermission, boolean serialized, boolean sticky) {
10661 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010662 intent = verifyBroadcastLocked(intent);
10663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010664 final long origId = Binder.clearCallingIdentity();
10665 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10666 resultTo, resultCode, resultData, map, requiredPermission,
10667 serialized, sticky, -1, uid);
10668 Binder.restoreCallingIdentity(origId);
10669 return res;
10670 }
10671 }
10672
10673 public final void unbroadcastIntent(IApplicationThread caller,
10674 Intent intent) {
10675 // Refuse possible leaked file descriptors
10676 if (intent != null && intent.hasFileDescriptors() == true) {
10677 throw new IllegalArgumentException("File descriptors passed in Intent");
10678 }
10679
10680 synchronized(this) {
10681 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10682 != PackageManager.PERMISSION_GRANTED) {
10683 String msg = "Permission Denial: unbroadcastIntent() from pid="
10684 + Binder.getCallingPid()
10685 + ", uid=" + Binder.getCallingUid()
10686 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010687 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010688 throw new SecurityException(msg);
10689 }
10690 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10691 if (list != null) {
10692 int N = list.size();
10693 int i;
10694 for (i=0; i<N; i++) {
10695 if (intent.filterEquals(list.get(i))) {
10696 list.remove(i);
10697 break;
10698 }
10699 }
10700 }
10701 }
10702 }
10703
10704 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10705 String resultData, Bundle resultExtras, boolean resultAbort,
10706 boolean explicit) {
10707 if (mOrderedBroadcasts.size() == 0) {
10708 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010709 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010710 }
10711 return false;
10712 }
10713 BroadcastRecord r = mOrderedBroadcasts.get(0);
10714 if (r.receiver == null) {
10715 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010716 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010717 }
10718 return false;
10719 }
10720 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010721 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010722 return false;
10723 }
10724 int state = r.state;
10725 r.state = r.IDLE;
10726 if (state == r.IDLE) {
10727 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010728 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010729 }
10730 }
10731 r.receiver = null;
10732 r.intent.setComponent(null);
10733 if (r.curApp != null) {
10734 r.curApp.curReceiver = null;
10735 }
10736 if (r.curFilter != null) {
10737 r.curFilter.receiverList.curBroadcast = null;
10738 }
10739 r.curFilter = null;
10740 r.curApp = null;
10741 r.curComponent = null;
10742 r.curReceiver = null;
10743 mPendingBroadcast = null;
10744
10745 r.resultCode = resultCode;
10746 r.resultData = resultData;
10747 r.resultExtras = resultExtras;
10748 r.resultAbort = resultAbort;
10749
10750 // We will process the next receiver right now if this is finishing
10751 // an app receiver (which is always asynchronous) or after we have
10752 // come back from calling a receiver.
10753 return state == BroadcastRecord.APP_RECEIVE
10754 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10755 }
10756
10757 public void finishReceiver(IBinder who, int resultCode, String resultData,
10758 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010759 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010760
10761 // Refuse possible leaked file descriptors
10762 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10763 throw new IllegalArgumentException("File descriptors passed in Bundle");
10764 }
10765
10766 boolean doNext;
10767
10768 final long origId = Binder.clearCallingIdentity();
10769
10770 synchronized(this) {
10771 doNext = finishReceiverLocked(
10772 who, resultCode, resultData, resultExtras, resultAbort, true);
10773 }
10774
10775 if (doNext) {
10776 processNextBroadcast(false);
10777 }
10778 trimApplications();
10779
10780 Binder.restoreCallingIdentity(origId);
10781 }
10782
Jeff Brown4d94a762010-09-23 11:33:28 -070010783 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010784 if (r.nextReceiver > 0) {
10785 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10786 if (curReceiver instanceof BroadcastFilter) {
10787 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010788 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789 System.identityHashCode(r),
10790 r.intent.getAction(),
10791 r.nextReceiver - 1,
10792 System.identityHashCode(bf));
10793 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010794 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010795 System.identityHashCode(r),
10796 r.intent.getAction(),
10797 r.nextReceiver - 1,
10798 ((ResolveInfo)curReceiver).toString());
10799 }
10800 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010801 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010802 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010803 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010804 System.identityHashCode(r),
10805 r.intent.getAction(),
10806 r.nextReceiver,
10807 "NONE");
10808 }
10809 }
10810
Jeff Brown4d94a762010-09-23 11:33:28 -070010811 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10812 if (! mPendingBroadcastTimeoutMessage) {
10813 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10814 mHandler.sendMessageAtTime(msg, timeoutTime);
10815 mPendingBroadcastTimeoutMessage = true;
10816 }
10817 }
10818
10819 private final void cancelBroadcastTimeoutLocked() {
10820 if (mPendingBroadcastTimeoutMessage) {
10821 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10822 mPendingBroadcastTimeoutMessage = false;
10823 }
10824 }
10825
10826 private final void broadcastTimeoutLocked(boolean fromMsg) {
10827 if (fromMsg) {
10828 mPendingBroadcastTimeoutMessage = false;
10829 }
10830
10831 if (mOrderedBroadcasts.size() == 0) {
10832 return;
10833 }
10834
10835 long now = SystemClock.uptimeMillis();
10836 BroadcastRecord r = mOrderedBroadcasts.get(0);
10837 if (fromMsg) {
10838 if (mDidDexOpt) {
10839 // Delay timeouts until dexopt finishes.
10840 mDidDexOpt = false;
10841 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10842 setBroadcastTimeoutLocked(timeoutTime);
10843 return;
10844 }
10845 if (! mProcessesReady) {
10846 // Only process broadcast timeouts if the system is ready. That way
10847 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10848 // to do heavy lifting for system up.
10849 return;
10850 }
10851
10852 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10853 if (timeoutTime > now) {
10854 // We can observe premature timeouts because we do not cancel and reset the
10855 // broadcast timeout message after each receiver finishes. Instead, we set up
10856 // an initial timeout then kick it down the road a little further as needed
10857 // when it expires.
10858 if (DEBUG_BROADCAST) Slog.v(TAG,
10859 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10860 + timeoutTime);
10861 setBroadcastTimeoutLocked(timeoutTime);
10862 return;
10863 }
10864 }
10865
10866 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10867 + ", started " + (now - r.receiverTime) + "ms ago");
10868 r.receiverTime = now;
10869 r.anrCount++;
10870
10871 // Current receiver has passed its expiration date.
10872 if (r.nextReceiver <= 0) {
10873 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10874 return;
10875 }
10876
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010877 ProcessRecord app = null;
10878 String anrMessage = null;
10879
Jeff Brown4d94a762010-09-23 11:33:28 -070010880 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10881 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10882 logBroadcastReceiverDiscardLocked(r);
10883 if (curReceiver instanceof BroadcastFilter) {
10884 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10885 if (bf.receiverList.pid != 0
10886 && bf.receiverList.pid != MY_PID) {
10887 synchronized (this.mPidsSelfLocked) {
10888 app = this.mPidsSelfLocked.get(
10889 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010890 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010892 } else {
10893 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010895
Jeff Brown4d94a762010-09-23 11:33:28 -070010896 if (app != null) {
10897 anrMessage = "Broadcast of " + r.intent.toString();
10898 }
10899
10900 if (mPendingBroadcast == r) {
10901 mPendingBroadcast = null;
10902 }
10903
10904 // Move on to the next receiver.
10905 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10906 r.resultExtras, r.resultAbort, true);
10907 scheduleBroadcastsLocked();
10908
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010909 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010910 // Post the ANR to the handler since we do not want to process ANRs while
10911 // potentially holding our lock.
10912 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010914 }
10915
10916 private final void processCurBroadcastLocked(BroadcastRecord r,
10917 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010918 if (DEBUG_BROADCAST) Slog.v(TAG,
10919 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010920 if (app.thread == null) {
10921 throw new RemoteException();
10922 }
10923 r.receiver = app.thread.asBinder();
10924 r.curApp = app;
10925 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010926 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927
10928 // Tell the application to launch this receiver.
10929 r.intent.setComponent(r.curComponent);
10930
10931 boolean started = false;
10932 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010933 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010934 "Delivering to component " + r.curComponent
10935 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010936 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010937 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10938 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010939 if (DEBUG_BROADCAST) Slog.v(TAG,
10940 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010941 started = true;
10942 } finally {
10943 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010944 if (DEBUG_BROADCAST) Slog.v(TAG,
10945 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010946 r.receiver = null;
10947 r.curApp = null;
10948 app.curReceiver = null;
10949 }
10950 }
10951
10952 }
10953
Jeff Brown4d94a762010-09-23 11:33:28 -070010954 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010955 Intent intent, int resultCode, String data, Bundle extras,
10956 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010957 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010958 if (app != null && app.thread != null) {
10959 // If we have an app thread, do the call through that so it is
10960 // correctly ordered with other one-way calls.
10961 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010962 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010964 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010965 }
10966 }
10967
Jeff Brown4d94a762010-09-23 11:33:28 -070010968 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 BroadcastFilter filter, boolean ordered) {
10970 boolean skip = false;
10971 if (filter.requiredPermission != null) {
10972 int perm = checkComponentPermission(filter.requiredPermission,
10973 r.callingPid, r.callingUid, -1);
10974 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010975 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010976 + r.intent.toString()
10977 + " from " + r.callerPackage + " (pid="
10978 + r.callingPid + ", uid=" + r.callingUid + ")"
10979 + " requires " + filter.requiredPermission
10980 + " due to registered receiver " + filter);
10981 skip = true;
10982 }
10983 }
10984 if (r.requiredPermission != null) {
10985 int perm = checkComponentPermission(r.requiredPermission,
10986 filter.receiverList.pid, filter.receiverList.uid, -1);
10987 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010988 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 + r.intent.toString()
10990 + " to " + filter.receiverList.app
10991 + " (pid=" + filter.receiverList.pid
10992 + ", uid=" + filter.receiverList.uid + ")"
10993 + " requires " + r.requiredPermission
10994 + " due to sender " + r.callerPackage
10995 + " (uid " + r.callingUid + ")");
10996 skip = true;
10997 }
10998 }
10999
11000 if (!skip) {
11001 // If this is not being sent as an ordered broadcast, then we
11002 // don't want to touch the fields that keep track of the current
11003 // state of ordered broadcasts.
11004 if (ordered) {
11005 r.receiver = filter.receiverList.receiver.asBinder();
11006 r.curFilter = filter;
11007 filter.receiverList.curBroadcast = r;
11008 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011009 if (filter.receiverList.app != null) {
11010 // Bump hosting application to no longer be in background
11011 // scheduling class. Note that we can't do that if there
11012 // isn't an app... but we can only be in that case for
11013 // things that directly call the IActivityManager API, which
11014 // are already core system stuff so don't matter for this.
11015 r.curApp = filter.receiverList.app;
11016 filter.receiverList.app.curReceiver = r;
11017 updateOomAdjLocked();
11018 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011019 }
11020 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011021 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011022 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011023 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011024 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011025 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011026 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011027 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011028 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029 if (ordered) {
11030 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11031 }
11032 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011033 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011034 if (ordered) {
11035 r.receiver = null;
11036 r.curFilter = null;
11037 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011038 if (filter.receiverList.app != null) {
11039 filter.receiverList.app.curReceiver = null;
11040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011041 }
11042 }
11043 }
11044 }
11045
Dianne Hackborn12527f92009-11-11 17:39:50 -080011046 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11047 if (r.callingUid < 0) {
11048 // This was from a registerReceiver() call; ignore it.
11049 return;
11050 }
11051 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11052 MAX_BROADCAST_HISTORY-1);
11053 r.finishTime = SystemClock.uptimeMillis();
11054 mBroadcastHistory[0] = r;
11055 }
11056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011057 private final void processNextBroadcast(boolean fromMsg) {
11058 synchronized(this) {
11059 BroadcastRecord r;
11060
Joe Onorato8a9b2202010-02-26 18:56:32 -080011061 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011062 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011063 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064
11065 updateCpuStats();
11066
11067 if (fromMsg) {
11068 mBroadcastsScheduled = false;
11069 }
11070
11071 // First, deliver any non-serialized broadcasts right away.
11072 while (mParallelBroadcasts.size() > 0) {
11073 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011074 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011075 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011076 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011077 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011078 for (int i=0; i<N; i++) {
11079 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011080 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011081 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011082 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011083 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011084 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011085 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011086 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011087 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011088 }
11089
11090 // Now take care of the next serialized one...
11091
11092 // If we are waiting for a process to come up to handle the next
11093 // broadcast, then do nothing at this point. Just in case, we
11094 // check that the process we're waiting for still exists.
11095 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011096 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011097 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011098 + mPendingBroadcast.curApp);
11099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011100
11101 boolean isDead;
11102 synchronized (mPidsSelfLocked) {
11103 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11104 }
11105 if (!isDead) {
11106 // It's still alive, so keep waiting
11107 return;
11108 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011109 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011111 mPendingBroadcast.state = BroadcastRecord.IDLE;
11112 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011113 mPendingBroadcast = null;
11114 }
11115 }
11116
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011117 boolean looped = false;
11118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011119 do {
11120 if (mOrderedBroadcasts.size() == 0) {
11121 // No more broadcasts pending, so all done!
11122 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011123 if (looped) {
11124 // If we had finished the last ordered broadcast, then
11125 // make sure all processes have correct oom and sched
11126 // adjustments.
11127 updateOomAdjLocked();
11128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011129 return;
11130 }
11131 r = mOrderedBroadcasts.get(0);
11132 boolean forceReceive = false;
11133
11134 // Ensure that even if something goes awry with the timeout
11135 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011136 // and continue to make progress.
11137 //
11138 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011139 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011140 // one time heavy lifting after system upgrades and can take
11141 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011142 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011143 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011144 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 if ((numReceivers > 0) &&
11146 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011147 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011148 + " now=" + now
11149 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011150 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011151 + " intent=" + r.intent
11152 + " numReceivers=" + numReceivers
11153 + " nextReceiver=" + r.nextReceiver
11154 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011155 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 forceReceive = true;
11157 r.state = BroadcastRecord.IDLE;
11158 }
11159 }
11160
11161 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011162 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011163 "processNextBroadcast() called when not idle (state="
11164 + r.state + ")");
11165 return;
11166 }
11167
11168 if (r.receivers == null || r.nextReceiver >= numReceivers
11169 || r.resultAbort || forceReceive) {
11170 // No more receivers for this broadcast! Send the final
11171 // result if requested...
11172 if (r.resultTo != null) {
11173 try {
11174 if (DEBUG_BROADCAST) {
11175 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011176 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011177 + " seq=" + seq + " app=" + r.callerApp);
11178 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011179 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011180 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011181 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011182 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011183 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011184 }
11185 }
11186
Joe Onorato8a9b2202010-02-26 18:56:32 -080011187 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011188 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011189
Joe Onorato8a9b2202010-02-26 18:56:32 -080011190 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011191 + r);
11192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011193 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011194 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011195 mOrderedBroadcasts.remove(0);
11196 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011197 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 continue;
11199 }
11200 } while (r == null);
11201
11202 // Get the next receiver...
11203 int recIdx = r.nextReceiver++;
11204
11205 // Keep track of when this receiver started, and make sure there
11206 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011207 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011208 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011209 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210
Joe Onorato8a9b2202010-02-26 18:56:32 -080011211 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011212 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011213 }
11214 if (! mPendingBroadcastTimeoutMessage) {
11215 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011216 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011217 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11218 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011219 }
11220
11221 Object nextReceiver = r.receivers.get(recIdx);
11222 if (nextReceiver instanceof BroadcastFilter) {
11223 // Simple case: this is a registered receiver who gets
11224 // a direct call.
11225 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011226 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011227 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011228 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011229 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011230 if (r.receiver == null || !r.ordered) {
11231 // The receiver has already finished, so schedule to
11232 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011233 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11234 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 r.state = BroadcastRecord.IDLE;
11236 scheduleBroadcastsLocked();
11237 }
11238 return;
11239 }
11240
11241 // Hard case: need to instantiate the receiver, possibly
11242 // starting its application process to host it.
11243
11244 ResolveInfo info =
11245 (ResolveInfo)nextReceiver;
11246
11247 boolean skip = false;
11248 int perm = checkComponentPermission(info.activityInfo.permission,
11249 r.callingPid, r.callingUid,
11250 info.activityInfo.exported
11251 ? -1 : info.activityInfo.applicationInfo.uid);
11252 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011253 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011254 + r.intent.toString()
11255 + " from " + r.callerPackage + " (pid=" + r.callingPid
11256 + ", uid=" + r.callingUid + ")"
11257 + " requires " + info.activityInfo.permission
11258 + " due to receiver " + info.activityInfo.packageName
11259 + "/" + info.activityInfo.name);
11260 skip = true;
11261 }
11262 if (r.callingUid != Process.SYSTEM_UID &&
11263 r.requiredPermission != null) {
11264 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011265 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 checkPermission(r.requiredPermission,
11267 info.activityInfo.applicationInfo.packageName);
11268 } catch (RemoteException e) {
11269 perm = PackageManager.PERMISSION_DENIED;
11270 }
11271 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011272 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011273 + r.intent + " to "
11274 + info.activityInfo.applicationInfo.packageName
11275 + " requires " + r.requiredPermission
11276 + " due to sender " + r.callerPackage
11277 + " (uid " + r.callingUid + ")");
11278 skip = true;
11279 }
11280 }
11281 if (r.curApp != null && r.curApp.crashing) {
11282 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011283 if (DEBUG_BROADCAST) Slog.v(TAG,
11284 "Skipping deliver ordered " + r + " to " + r.curApp
11285 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011286 skip = true;
11287 }
11288
11289 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011290 if (DEBUG_BROADCAST) Slog.v(TAG,
11291 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011292 r.receiver = null;
11293 r.curFilter = null;
11294 r.state = BroadcastRecord.IDLE;
11295 scheduleBroadcastsLocked();
11296 return;
11297 }
11298
11299 r.state = BroadcastRecord.APP_RECEIVE;
11300 String targetProcess = info.activityInfo.processName;
11301 r.curComponent = new ComponentName(
11302 info.activityInfo.applicationInfo.packageName,
11303 info.activityInfo.name);
11304 r.curReceiver = info.activityInfo;
11305
11306 // Is this receiver's application already running?
11307 ProcessRecord app = getProcessRecordLocked(targetProcess,
11308 info.activityInfo.applicationInfo.uid);
11309 if (app != null && app.thread != null) {
11310 try {
11311 processCurBroadcastLocked(r, app);
11312 return;
11313 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011314 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011315 + r.curComponent, e);
11316 }
11317
11318 // If a dead object exception was thrown -- fall through to
11319 // restart the application.
11320 }
11321
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011322 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011323 if (DEBUG_BROADCAST) Slog.v(TAG,
11324 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011325 if ((r.curApp=startProcessLocked(targetProcess,
11326 info.activityInfo.applicationInfo, true,
11327 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011328 "broadcast", r.curComponent,
11329 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11330 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011331 // Ah, this recipient is unavailable. Finish it if necessary,
11332 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011333 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334 + info.activityInfo.applicationInfo.packageName + "/"
11335 + info.activityInfo.applicationInfo.uid + " for broadcast "
11336 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011337 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011338 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11339 r.resultExtras, r.resultAbort, true);
11340 scheduleBroadcastsLocked();
11341 r.state = BroadcastRecord.IDLE;
11342 return;
11343 }
11344
11345 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011346 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 }
11348 }
11349
11350 // =========================================================
11351 // INSTRUMENTATION
11352 // =========================================================
11353
11354 public boolean startInstrumentation(ComponentName className,
11355 String profileFile, int flags, Bundle arguments,
11356 IInstrumentationWatcher watcher) {
11357 // Refuse possible leaked file descriptors
11358 if (arguments != null && arguments.hasFileDescriptors()) {
11359 throw new IllegalArgumentException("File descriptors passed in Bundle");
11360 }
11361
11362 synchronized(this) {
11363 InstrumentationInfo ii = null;
11364 ApplicationInfo ai = null;
11365 try {
11366 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011367 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011368 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011369 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 } catch (PackageManager.NameNotFoundException e) {
11371 }
11372 if (ii == null) {
11373 reportStartInstrumentationFailure(watcher, className,
11374 "Unable to find instrumentation info for: " + className);
11375 return false;
11376 }
11377 if (ai == null) {
11378 reportStartInstrumentationFailure(watcher, className,
11379 "Unable to find instrumentation target package: " + ii.targetPackage);
11380 return false;
11381 }
11382
11383 int match = mContext.getPackageManager().checkSignatures(
11384 ii.targetPackage, ii.packageName);
11385 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11386 String msg = "Permission Denial: starting instrumentation "
11387 + className + " from pid="
11388 + Binder.getCallingPid()
11389 + ", uid=" + Binder.getCallingPid()
11390 + " not allowed because package " + ii.packageName
11391 + " does not have a signature matching the target "
11392 + ii.targetPackage;
11393 reportStartInstrumentationFailure(watcher, className, msg);
11394 throw new SecurityException(msg);
11395 }
11396
11397 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011398 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011399 ProcessRecord app = addAppLocked(ai);
11400 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011401 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011402 app.instrumentationProfileFile = profileFile;
11403 app.instrumentationArguments = arguments;
11404 app.instrumentationWatcher = watcher;
11405 app.instrumentationResultClass = className;
11406 Binder.restoreCallingIdentity(origId);
11407 }
11408
11409 return true;
11410 }
11411
11412 /**
11413 * Report errors that occur while attempting to start Instrumentation. Always writes the
11414 * error to the logs, but if somebody is watching, send the report there too. This enables
11415 * the "am" command to report errors with more information.
11416 *
11417 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11418 * @param cn The component name of the instrumentation.
11419 * @param report The error report.
11420 */
11421 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11422 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011423 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011424 try {
11425 if (watcher != null) {
11426 Bundle results = new Bundle();
11427 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11428 results.putString("Error", report);
11429 watcher.instrumentationStatus(cn, -1, results);
11430 }
11431 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011432 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011433 }
11434 }
11435
11436 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11437 if (app.instrumentationWatcher != null) {
11438 try {
11439 // NOTE: IInstrumentationWatcher *must* be oneway here
11440 app.instrumentationWatcher.instrumentationFinished(
11441 app.instrumentationClass,
11442 resultCode,
11443 results);
11444 } catch (RemoteException e) {
11445 }
11446 }
11447 app.instrumentationWatcher = null;
11448 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011449 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011450 app.instrumentationProfileFile = null;
11451 app.instrumentationArguments = null;
11452
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011453 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011454 }
11455
11456 public void finishInstrumentation(IApplicationThread target,
11457 int resultCode, Bundle results) {
11458 // Refuse possible leaked file descriptors
11459 if (results != null && results.hasFileDescriptors()) {
11460 throw new IllegalArgumentException("File descriptors passed in Intent");
11461 }
11462
11463 synchronized(this) {
11464 ProcessRecord app = getRecordForAppLocked(target);
11465 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011466 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467 return;
11468 }
11469 final long origId = Binder.clearCallingIdentity();
11470 finishInstrumentationLocked(app, resultCode, results);
11471 Binder.restoreCallingIdentity(origId);
11472 }
11473 }
11474
11475 // =========================================================
11476 // CONFIGURATION
11477 // =========================================================
11478
11479 public ConfigurationInfo getDeviceConfigurationInfo() {
11480 ConfigurationInfo config = new ConfigurationInfo();
11481 synchronized (this) {
11482 config.reqTouchScreen = mConfiguration.touchscreen;
11483 config.reqKeyboardType = mConfiguration.keyboard;
11484 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011485 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11486 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011487 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11488 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011489 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11490 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011491 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11492 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011493 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011494 }
11495 return config;
11496 }
11497
11498 public Configuration getConfiguration() {
11499 Configuration ci;
11500 synchronized(this) {
11501 ci = new Configuration(mConfiguration);
11502 }
11503 return ci;
11504 }
11505
11506 public void updateConfiguration(Configuration values) {
11507 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11508 "updateConfiguration()");
11509
11510 synchronized(this) {
11511 if (values == null && mWindowManager != null) {
11512 // sentinel: fetch the current configuration from the window manager
11513 values = mWindowManager.computeNewConfiguration();
11514 }
11515
11516 final long origId = Binder.clearCallingIdentity();
11517 updateConfigurationLocked(values, null);
11518 Binder.restoreCallingIdentity(origId);
11519 }
11520 }
11521
11522 /**
11523 * Do either or both things: (1) change the current configuration, and (2)
11524 * make sure the given activity is running with the (now) current
11525 * configuration. Returns true if the activity has been left running, or
11526 * false if <var>starting</var> is being destroyed to match the new
11527 * configuration.
11528 */
11529 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011530 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011531 int changes = 0;
11532
11533 boolean kept = true;
11534
11535 if (values != null) {
11536 Configuration newConfig = new Configuration(mConfiguration);
11537 changes = newConfig.updateFrom(values);
11538 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011539 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011540 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541 }
11542
Doug Zongker2bec3d42009-12-04 12:52:44 -080011543 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011544
11545 if (values.locale != null) {
11546 saveLocaleLocked(values.locale,
11547 !values.locale.equals(mConfiguration.locale),
11548 values.userSetLocale);
11549 }
11550
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011551 mConfigurationSeq++;
11552 if (mConfigurationSeq <= 0) {
11553 mConfigurationSeq = 1;
11554 }
11555 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011556 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011557 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011558
11559 AttributeCache ac = AttributeCache.instance();
11560 if (ac != null) {
11561 ac.updateConfiguration(mConfiguration);
11562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011564 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11565 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11566 msg.obj = new Configuration(mConfiguration);
11567 mHandler.sendMessage(msg);
11568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011569
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011570 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11571 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572 try {
11573 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011574 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011575 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576 app.thread.scheduleConfigurationChanged(mConfiguration);
11577 }
11578 } catch (Exception e) {
11579 }
11580 }
11581 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011582 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11583 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011584 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11585 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011586 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11587 broadcastIntentLocked(null, null,
11588 new Intent(Intent.ACTION_LOCALE_CHANGED),
11589 null, null, 0, null, null,
11590 null, false, false, MY_PID, Process.SYSTEM_UID);
11591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011592 }
11593 }
11594
11595 if (changes != 0 && starting == null) {
11596 // If the configuration changed, and the caller is not already
11597 // in the process of starting an activity, then find the top
11598 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011599 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011600 }
11601
11602 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011603 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604 if (kept) {
11605 // If this didn't result in the starting activity being
11606 // destroyed, then we need to make sure at this point that all
11607 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011608 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011609 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011610 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011611 }
11612 }
11613
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011614 if (values != null && mWindowManager != null) {
11615 mWindowManager.setNewConfiguration(mConfiguration);
11616 }
11617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011618 return kept;
11619 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620
11621 /**
11622 * Save the locale. You must be inside a synchronized (this) block.
11623 */
11624 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11625 if(isDiff) {
11626 SystemProperties.set("user.language", l.getLanguage());
11627 SystemProperties.set("user.region", l.getCountry());
11628 }
11629
11630 if(isPersist) {
11631 SystemProperties.set("persist.sys.language", l.getLanguage());
11632 SystemProperties.set("persist.sys.country", l.getCountry());
11633 SystemProperties.set("persist.sys.localevar", l.getVariant());
11634 }
11635 }
11636
11637 // =========================================================
11638 // LIFETIME MANAGEMENT
11639 // =========================================================
11640
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011641 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11642 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011644 // This adjustment has already been computed. If we are calling
11645 // from the top, we may have already computed our adjustment with
11646 // an earlier hidden adjustment that isn't really for us... if
11647 // so, use the new hidden adjustment.
11648 if (!recursed && app.hidden) {
11649 app.curAdj = hiddenAdj;
11650 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011651 return app.curAdj;
11652 }
11653
11654 if (app.thread == null) {
11655 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011656 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011657 return (app.curAdj=EMPTY_APP_ADJ);
11658 }
11659
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011660 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11661 // The max adjustment doesn't allow this app to be anything
11662 // below foreground, so it is not worth doing work for it.
11663 app.adjType = "fixed";
11664 app.adjSeq = mAdjSeq;
11665 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011666 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011667 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11668 return (app.curAdj=app.maxAdj);
11669 }
11670
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011671 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011672 app.adjSource = null;
11673 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011674 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011675 app.empty = false;
11676 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011677
The Android Open Source Project4df24232009-03-05 14:34:35 -080011678 // Determine the importance of the process, starting with most
11679 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011680 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011681 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011682 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011683 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011684 // The last app on the list is the foreground app.
11685 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011686 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011687 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011688 } else if (app.instrumentationClass != null) {
11689 // Don't want to kill running instrumentation.
11690 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011691 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011692 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011693 } else if (app.curReceiver != null ||
11694 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11695 // An app that is currently receiving a broadcast also
11696 // counts as being in the foreground.
11697 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011698 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011699 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011700 } else if (app.executingServices.size() > 0) {
11701 // An app that is currently executing a service callback also
11702 // counts as being in the foreground.
11703 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011704 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011705 app.adjType = "exec-service";
11706 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011707 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011708 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011709 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011710 app.adjType = "foreground-service";
11711 } else if (app.forcingToForeground != null) {
11712 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011713 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011714 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011715 app.adjType = "force-foreground";
11716 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011717 } else if (app == mHeavyWeightProcess) {
11718 // We don't want to kill the current heavy-weight process.
11719 adj = HEAVY_WEIGHT_APP_ADJ;
11720 schedGroup = Process.THREAD_GROUP_DEFAULT;
11721 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011722 } else if (app == mHomeProcess) {
11723 // This process is hosting what we currently consider to be the
11724 // home app, so we don't want to let it go into the background.
11725 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011726 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011727 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011728 } else if ((N=app.activities.size()) != 0) {
11729 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011730 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011732 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011733 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011734 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011735 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011736 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011737 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011738 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011739 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011740 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011741 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011742 break;
11743 }
11744 }
11745 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011746 // A very not-needed process. If this is lower in the lru list,
11747 // we will push it in to the empty bucket.
11748 app.hidden = true;
11749 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011750 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011751 adj = hiddenAdj;
11752 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011753 }
11754
Joe Onorato8a9b2202010-02-26 18:56:32 -080011755 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011756
The Android Open Source Project4df24232009-03-05 14:34:35 -080011757 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011758 // there are applications dependent on our services or providers, but
11759 // this gives us a baseline and makes sure we don't get into an
11760 // infinite recursion.
11761 app.adjSeq = mAdjSeq;
11762 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763
Christopher Tate6fa95972009-06-05 18:43:55 -070011764 if (mBackupTarget != null && app == mBackupTarget.app) {
11765 // If possible we want to avoid killing apps while they're being backed up
11766 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011767 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011768 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011769 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011770 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011771 }
11772 }
11773
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011774 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11775 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011776 final long now = SystemClock.uptimeMillis();
11777 // This process is more important if the top activity is
11778 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011779 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011780 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011781 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011782 if (s.startRequested) {
11783 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11784 // This service has seen some activity within
11785 // recent memory, so we will keep its process ahead
11786 // of the background processes.
11787 if (adj > SECONDARY_SERVER_ADJ) {
11788 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011789 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011790 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011791 }
11792 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011793 // If we have let the service slide into the background
11794 // state, still have some text describing what it is doing
11795 // even though the service no longer has an impact.
11796 if (adj > SECONDARY_SERVER_ADJ) {
11797 app.adjType = "started-bg-services";
11798 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011799 // Don't kill this process because it is doing work; it
11800 // has said it is doing work.
11801 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011802 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011803 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11804 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011805 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011806 = s.connections.values().iterator();
11807 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011808 ArrayList<ConnectionRecord> clist = kt.next();
11809 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11810 // XXX should compute this based on the max of
11811 // all connected clients.
11812 ConnectionRecord cr = clist.get(i);
11813 if (cr.binding.client == app) {
11814 // Binding to ourself is not interesting.
11815 continue;
11816 }
11817 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11818 ProcessRecord client = cr.binding.client;
11819 int myHiddenAdj = hiddenAdj;
11820 if (myHiddenAdj > client.hiddenAdj) {
11821 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11822 myHiddenAdj = client.hiddenAdj;
11823 } else {
11824 myHiddenAdj = VISIBLE_APP_ADJ;
11825 }
11826 }
11827 int clientAdj = computeOomAdjLocked(
11828 client, myHiddenAdj, TOP_APP, true);
11829 if (adj > clientAdj) {
11830 adj = clientAdj >= VISIBLE_APP_ADJ
11831 ? clientAdj : VISIBLE_APP_ADJ;
11832 if (!client.hidden) {
11833 app.hidden = false;
11834 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011835 if (client.keeping) {
11836 app.keeping = true;
11837 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011838 app.adjType = "service";
11839 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11840 .REASON_SERVICE_IN_USE;
11841 app.adjSource = cr.binding.client;
11842 app.adjTarget = s.name;
11843 }
11844 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11845 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11846 schedGroup = Process.THREAD_GROUP_DEFAULT;
11847 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011848 }
11849 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011850 ActivityRecord a = cr.activity;
11851 //if (a != null) {
11852 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11853 //}
11854 if (a != null && adj > FOREGROUND_APP_ADJ &&
11855 (a.state == ActivityState.RESUMED
11856 || a.state == ActivityState.PAUSING)) {
11857 adj = FOREGROUND_APP_ADJ;
11858 schedGroup = Process.THREAD_GROUP_DEFAULT;
11859 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011860 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011861 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11862 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011863 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011864 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011865 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011866 }
11867 }
11868 }
11869 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011870
Dianne Hackborn287952c2010-09-22 22:34:31 -070011871 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011872 // would like to avoid killing it unless it would prevent the current
11873 // application from running. By default we put the process in
11874 // with the rest of the background processes; as we scan through
11875 // its services we may bump it up from there.
11876 if (adj > hiddenAdj) {
11877 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011878 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011879 app.adjType = "bg-services";
11880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011881 }
11882
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011883 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11884 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011885 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011886 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11887 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011888 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011889 if (cpr.clients.size() != 0) {
11890 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11891 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11892 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011893 if (client == app) {
11894 // Being our own client is not interesting.
11895 continue;
11896 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011897 int myHiddenAdj = hiddenAdj;
11898 if (myHiddenAdj > client.hiddenAdj) {
11899 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11900 myHiddenAdj = client.hiddenAdj;
11901 } else {
11902 myHiddenAdj = FOREGROUND_APP_ADJ;
11903 }
11904 }
11905 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011906 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011907 if (adj > clientAdj) {
11908 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011909 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011910 if (!client.hidden) {
11911 app.hidden = false;
11912 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011913 if (client.keeping) {
11914 app.keeping = true;
11915 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011916 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011917 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11918 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011919 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011920 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011921 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011922 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11923 schedGroup = Process.THREAD_GROUP_DEFAULT;
11924 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011925 }
11926 }
11927 // If the provider has external (non-framework) process
11928 // dependencies, ensure that its adjustment is at least
11929 // FOREGROUND_APP_ADJ.
11930 if (cpr.externals != 0) {
11931 if (adj > FOREGROUND_APP_ADJ) {
11932 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011933 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011934 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011935 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011936 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011937 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011938 }
11939 }
11940 }
11941 }
11942
11943 app.curRawAdj = adj;
11944
Joe Onorato8a9b2202010-02-26 18:56:32 -080011945 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011946 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11947 if (adj > app.maxAdj) {
11948 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011949 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011950 schedGroup = Process.THREAD_GROUP_DEFAULT;
11951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011953 if (adj < HIDDEN_APP_MIN_ADJ) {
11954 app.keeping = true;
11955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011956
11957 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011958 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011960 return adj;
11961 }
11962
11963 /**
11964 * Ask a given process to GC right now.
11965 */
11966 final void performAppGcLocked(ProcessRecord app) {
11967 try {
11968 app.lastRequestedGc = SystemClock.uptimeMillis();
11969 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011970 if (app.reportLowMemory) {
11971 app.reportLowMemory = false;
11972 app.thread.scheduleLowMemory();
11973 } else {
11974 app.thread.processInBackground();
11975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011976 }
11977 } catch (Exception e) {
11978 // whatever.
11979 }
11980 }
11981
11982 /**
11983 * Returns true if things are idle enough to perform GCs.
11984 */
Josh Bartel7f208742010-02-25 11:01:44 -060011985 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011986 return mParallelBroadcasts.size() == 0
11987 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011988 && (mSleeping || (mMainStack.mResumedActivity != null &&
11989 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011990 }
11991
11992 /**
11993 * Perform GCs on all processes that are waiting for it, but only
11994 * if things are idle.
11995 */
11996 final void performAppGcsLocked() {
11997 final int N = mProcessesToGc.size();
11998 if (N <= 0) {
11999 return;
12000 }
Josh Bartel7f208742010-02-25 11:01:44 -060012001 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012002 while (mProcessesToGc.size() > 0) {
12003 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012004 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012005 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12006 <= SystemClock.uptimeMillis()) {
12007 // To avoid spamming the system, we will GC processes one
12008 // at a time, waiting a few seconds between each.
12009 performAppGcLocked(proc);
12010 scheduleAppGcsLocked();
12011 return;
12012 } else {
12013 // It hasn't been long enough since we last GCed this
12014 // process... put it in the list to wait for its time.
12015 addProcessToGcListLocked(proc);
12016 break;
12017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012018 }
12019 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012020
12021 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012022 }
12023 }
12024
12025 /**
12026 * If all looks good, perform GCs on all processes waiting for them.
12027 */
12028 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012029 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012030 performAppGcsLocked();
12031 return;
12032 }
12033 // Still not idle, wait some more.
12034 scheduleAppGcsLocked();
12035 }
12036
12037 /**
12038 * Schedule the execution of all pending app GCs.
12039 */
12040 final void scheduleAppGcsLocked() {
12041 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012042
12043 if (mProcessesToGc.size() > 0) {
12044 // Schedule a GC for the time to the next process.
12045 ProcessRecord proc = mProcessesToGc.get(0);
12046 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12047
12048 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12049 long now = SystemClock.uptimeMillis();
12050 if (when < (now+GC_TIMEOUT)) {
12051 when = now + GC_TIMEOUT;
12052 }
12053 mHandler.sendMessageAtTime(msg, when);
12054 }
12055 }
12056
12057 /**
12058 * Add a process to the array of processes waiting to be GCed. Keeps the
12059 * list in sorted order by the last GC time. The process can't already be
12060 * on the list.
12061 */
12062 final void addProcessToGcListLocked(ProcessRecord proc) {
12063 boolean added = false;
12064 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12065 if (mProcessesToGc.get(i).lastRequestedGc <
12066 proc.lastRequestedGc) {
12067 added = true;
12068 mProcessesToGc.add(i+1, proc);
12069 break;
12070 }
12071 }
12072 if (!added) {
12073 mProcessesToGc.add(0, proc);
12074 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012075 }
12076
12077 /**
12078 * Set up to ask a process to GC itself. This will either do it
12079 * immediately, or put it on the list of processes to gc the next
12080 * time things are idle.
12081 */
12082 final void scheduleAppGcLocked(ProcessRecord app) {
12083 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012084 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012085 return;
12086 }
12087 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012088 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089 scheduleAppGcsLocked();
12090 }
12091 }
12092
Dianne Hackborn287952c2010-09-22 22:34:31 -070012093 final void checkExcessivePowerUsageLocked(boolean doKills) {
12094 updateCpuStatsNow();
12095
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012096 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012097 boolean doWakeKills = doKills;
12098 boolean doCpuKills = doKills;
12099 if (mLastPowerCheckRealtime == 0) {
12100 doWakeKills = false;
12101 }
12102 if (mLastPowerCheckUptime == 0) {
12103 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012104 }
12105 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012106 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012107 }
12108 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012109 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12110 final long curUptime = SystemClock.uptimeMillis();
12111 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12112 mLastPowerCheckRealtime = curRealtime;
12113 mLastPowerCheckUptime = curUptime;
12114 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12115 doWakeKills = false;
12116 }
12117 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12118 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012119 }
12120 int i = mLruProcesses.size();
12121 while (i > 0) {
12122 i--;
12123 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012124 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012125 long wtime;
12126 synchronized (stats) {
12127 wtime = stats.getProcessWakeTime(app.info.uid,
12128 app.pid, curRealtime);
12129 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012130 long wtimeUsed = wtime - app.lastWakeTime;
12131 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12132 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012133 StringBuilder sb = new StringBuilder(128);
12134 sb.append("Wake for ");
12135 app.toShortString(sb);
12136 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012137 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012138 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012139 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012140 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012141 sb.append((wtimeUsed*100)/realtimeSince);
12142 sb.append("%)");
12143 Slog.i(TAG, sb.toString());
12144 sb.setLength(0);
12145 sb.append("CPU for ");
12146 app.toShortString(sb);
12147 sb.append(": over ");
12148 TimeUtils.formatDuration(uptimeSince, sb);
12149 sb.append(" used ");
12150 TimeUtils.formatDuration(cputimeUsed, sb);
12151 sb.append(" (");
12152 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012153 sb.append("%)");
12154 Slog.i(TAG, sb.toString());
12155 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012156 // If a process has held a wake lock for more
12157 // than 50% of the time during this period,
12158 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012159 if (doWakeKills && realtimeSince > 0
12160 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12161 synchronized (stats) {
12162 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12163 realtimeSince, wtimeUsed);
12164 }
12165 Slog.w(TAG, "Excessive wake lock in " + app.processName
12166 + " (pid " + app.pid + "): held " + wtimeUsed
12167 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012168 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12169 app.processName, app.setAdj, "excessive wake lock");
12170 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012171 } else if (doCpuKills && uptimeSince > 0
12172 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12173 synchronized (stats) {
12174 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12175 uptimeSince, cputimeUsed);
12176 }
12177 Slog.w(TAG, "Excessive CPU in " + app.processName
12178 + " (pid " + app.pid + "): used " + cputimeUsed
12179 + " during " + uptimeSince);
12180 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12181 app.processName, app.setAdj, "excessive cpu");
12182 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012183 } else {
12184 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012185 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012186 }
12187 }
12188 }
12189 }
12190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012191 private final boolean updateOomAdjLocked(
12192 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12193 app.hiddenAdj = hiddenAdj;
12194
12195 if (app.thread == null) {
12196 return true;
12197 }
12198
Dianne Hackborn287952c2010-09-22 22:34:31 -070012199 final boolean wasKeeping = app.keeping;
12200
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012201 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012202
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012203 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012204 if (app.curRawAdj != app.setRawAdj) {
12205 if (app.curRawAdj > FOREGROUND_APP_ADJ
12206 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12207 // If this app is transitioning from foreground to
12208 // non-foreground, have it do a gc.
12209 scheduleAppGcLocked(app);
12210 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12211 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12212 // Likewise do a gc when an app is moving in to the
12213 // background (such as a service stopping).
12214 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012215 }
12216
12217 if (wasKeeping && !app.keeping) {
12218 // This app is no longer something we want to keep. Note
12219 // its current wake lock time to later know to kill it if
12220 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012221 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12222 synchronized (stats) {
12223 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12224 app.pid, SystemClock.elapsedRealtime());
12225 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012226 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012227 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012229 app.setRawAdj = app.curRawAdj;
12230 }
12231 if (adj != app.setAdj) {
12232 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012233 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012234 TAG, "Set app " + app.processName +
12235 " oom adj to " + adj);
12236 app.setAdj = adj;
12237 } else {
12238 return false;
12239 }
12240 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012241 if (app.setSchedGroup != app.curSchedGroup) {
12242 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012243 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012244 "Setting process group of " + app.processName
12245 + " to " + app.curSchedGroup);
12246 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012247 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012248 try {
12249 Process.setProcessGroup(app.pid, app.curSchedGroup);
12250 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012251 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012252 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012253 e.printStackTrace();
12254 } finally {
12255 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012256 }
12257 }
12258 if (false) {
12259 if (app.thread != null) {
12260 try {
12261 app.thread.setSchedulingGroup(app.curSchedGroup);
12262 } catch (RemoteException e) {
12263 }
12264 }
12265 }
12266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012267 }
12268
12269 return true;
12270 }
12271
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012272 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012273 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012274 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012275 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012276 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012277 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012278 }
12279 }
12280 return resumedActivity;
12281 }
12282
12283 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012284 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012285 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12286 int curAdj = app.curAdj;
12287 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12288 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12289
12290 mAdjSeq++;
12291
12292 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12293 if (res) {
12294 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12295 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12296 if (nowHidden != wasHidden) {
12297 // Changed to/from hidden state, so apps after it in the LRU
12298 // list may also be changed.
12299 updateOomAdjLocked();
12300 }
12301 }
12302 return res;
12303 }
12304
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012305 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012306 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012307 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012308 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12309
12310 if (false) {
12311 RuntimeException e = new RuntimeException();
12312 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012313 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012314 }
12315
12316 mAdjSeq++;
12317
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012318 // Let's determine how many processes we have running vs.
12319 // how many slots we have for background processes; we may want
12320 // to put multiple processes in a slot of there are enough of
12321 // them.
12322 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12323 int factor = (mLruProcesses.size()-4)/numSlots;
12324 if (factor < 1) factor = 1;
12325 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012326 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012328 // First try updating the OOM adjustment for each of the
12329 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012330 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012331 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12332 while (i > 0) {
12333 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012334 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012335 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012336 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012337 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012338 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012339 step++;
12340 if (step >= factor) {
12341 step = 0;
12342 curHiddenAdj++;
12343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012344 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012345 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012346 if (!app.killedBackground) {
12347 numHidden++;
12348 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012349 Slog.i(TAG, "No longer want " + app.processName
12350 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012351 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12352 app.processName, app.setAdj, "too many background");
12353 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012354 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012355 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012356 }
12357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012358 } else {
12359 didOomAdj = false;
12360 }
12361 }
12362
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012363 // If we return false, we will fall back on killing processes to
12364 // have a fixed limit. Do this if a limit has been requested; else
12365 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012366 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12367 }
12368
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012369 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012370 synchronized (this) {
12371 int i;
12372
12373 // First remove any unused application processes whose package
12374 // has been removed.
12375 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12376 final ProcessRecord app = mRemovedProcesses.get(i);
12377 if (app.activities.size() == 0
12378 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012379 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012380 TAG, "Exiting empty application process "
12381 + app.processName + " ("
12382 + (app.thread != null ? app.thread.asBinder() : null)
12383 + ")\n");
12384 if (app.pid > 0 && app.pid != MY_PID) {
12385 Process.killProcess(app.pid);
12386 } else {
12387 try {
12388 app.thread.scheduleExit();
12389 } catch (Exception e) {
12390 // Ignore exceptions.
12391 }
12392 }
12393 cleanUpApplicationRecordLocked(app, false, -1);
12394 mRemovedProcesses.remove(i);
12395
12396 if (app.persistent) {
12397 if (app.persistent) {
12398 addAppLocked(app.info);
12399 }
12400 }
12401 }
12402 }
12403
12404 // Now try updating the OOM adjustment for each of the
12405 // application processes based on their current state.
12406 // If the setOomAdj() API is not supported, then go with our
12407 // back-up plan...
12408 if (!updateOomAdjLocked()) {
12409
12410 // Count how many processes are running services.
12411 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012412 for (i=mLruProcesses.size()-1; i>=0; i--) {
12413 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012414
12415 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012416 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012417 // Don't count processes holding services against our
12418 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012419 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012420 TAG, "Not trimming app " + app + " with services: "
12421 + app.services);
12422 numServiceProcs++;
12423 }
12424 }
12425
12426 int curMaxProcs = mProcessLimit;
12427 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12428 if (mAlwaysFinishActivities) {
12429 curMaxProcs = 1;
12430 }
12431 curMaxProcs += numServiceProcs;
12432
12433 // Quit as many processes as we can to get down to the desired
12434 // process count. First remove any processes that no longer
12435 // have activites running in them.
12436 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012437 i<mLruProcesses.size()
12438 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012439 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012440 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012441 // Quit an application only if it is not currently
12442 // running any activities.
12443 if (!app.persistent && app.activities.size() == 0
12444 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012445 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012446 TAG, "Exiting empty application process "
12447 + app.processName + " ("
12448 + (app.thread != null ? app.thread.asBinder() : null)
12449 + ")\n");
12450 if (app.pid > 0 && app.pid != MY_PID) {
12451 Process.killProcess(app.pid);
12452 } else {
12453 try {
12454 app.thread.scheduleExit();
12455 } catch (Exception e) {
12456 // Ignore exceptions.
12457 }
12458 }
12459 // todo: For now we assume the application is not buggy
12460 // or evil, and will quit as a result of our request.
12461 // Eventually we need to drive this off of the death
12462 // notification, and kill the process if it takes too long.
12463 cleanUpApplicationRecordLocked(app, false, i);
12464 i--;
12465 }
12466 }
12467
12468 // If we still have too many processes, now from the least
12469 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012470 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012471 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012472 " of " + curMaxProcs + " processes");
12473 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012474 i<mLruProcesses.size()
12475 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012476 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012477 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012478 // Quit the application only if we have a state saved for
12479 // all of its activities.
12480 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012481 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012482 int NUMA = app.activities.size();
12483 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012484 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012485 TAG, "Looking to quit " + app.processName);
12486 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012487 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012488 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012489 TAG, " " + r.intent.getComponent().flattenToShortString()
12490 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12491 canQuit = (r.haveState || !r.stateNotNeeded)
12492 && !r.visible && r.stopped;
12493 }
12494 if (canQuit) {
12495 // Finish all of the activities, and then the app itself.
12496 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012497 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012498 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012499 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012500 }
12501 r.resultTo = null;
12502 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012503 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012504 + app.processName + " ("
12505 + (app.thread != null ? app.thread.asBinder() : null)
12506 + ")\n");
12507 if (app.pid > 0 && app.pid != MY_PID) {
12508 Process.killProcess(app.pid);
12509 } else {
12510 try {
12511 app.thread.scheduleExit();
12512 } catch (Exception e) {
12513 // Ignore exceptions.
12514 }
12515 }
12516 // todo: For now we assume the application is not buggy
12517 // or evil, and will quit as a result of our request.
12518 // Eventually we need to drive this off of the death
12519 // notification, and kill the process if it takes too long.
12520 cleanUpApplicationRecordLocked(app, false, i);
12521 i--;
12522 //dump();
12523 }
12524 }
12525
12526 }
12527
12528 int curMaxActivities = MAX_ACTIVITIES;
12529 if (mAlwaysFinishActivities) {
12530 curMaxActivities = 1;
12531 }
12532
12533 // Finally, if there are too many activities now running, try to
12534 // finish as many as we can to get back down to the limit.
12535 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012536 i<mMainStack.mLRUActivities.size()
12537 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012538 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012539 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012540 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012541
12542 // We can finish this one if we have its icicle saved and
12543 // it is not persistent.
12544 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012545 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012546 final int origSize = mMainStack.mLRUActivities.size();
12547 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012548
12549 // This will remove it from the LRU list, so keep
12550 // our index at the same value. Note that this check to
12551 // see if the size changes is just paranoia -- if
12552 // something unexpected happens, we don't want to end up
12553 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012554 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012555 i--;
12556 }
12557 }
12558 }
12559 }
12560 }
12561
12562 /** This method sends the specified signal to each of the persistent apps */
12563 public void signalPersistentProcesses(int sig) throws RemoteException {
12564 if (sig != Process.SIGNAL_USR1) {
12565 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12566 }
12567
12568 synchronized (this) {
12569 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12570 != PackageManager.PERMISSION_GRANTED) {
12571 throw new SecurityException("Requires permission "
12572 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12573 }
12574
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012575 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12576 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012577 if (r.thread != null && r.persistent) {
12578 Process.sendSignal(r.pid, sig);
12579 }
12580 }
12581 }
12582 }
12583
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012584 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012585 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012586
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012587 try {
12588 synchronized (this) {
12589 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12590 // its own permission.
12591 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12592 != PackageManager.PERMISSION_GRANTED) {
12593 throw new SecurityException("Requires permission "
12594 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012595 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012596
12597 if (start && fd == null) {
12598 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012599 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012600
12601 ProcessRecord proc = null;
12602 try {
12603 int pid = Integer.parseInt(process);
12604 synchronized (mPidsSelfLocked) {
12605 proc = mPidsSelfLocked.get(pid);
12606 }
12607 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012608 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012609
12610 if (proc == null) {
12611 HashMap<String, SparseArray<ProcessRecord>> all
12612 = mProcessNames.getMap();
12613 SparseArray<ProcessRecord> procs = all.get(process);
12614 if (procs != null && procs.size() > 0) {
12615 proc = procs.valueAt(0);
12616 }
12617 }
12618
12619 if (proc == null || proc.thread == null) {
12620 throw new IllegalArgumentException("Unknown process: " + process);
12621 }
12622
12623 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12624 if (isSecure) {
12625 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12626 throw new SecurityException("Process not debuggable: " + proc);
12627 }
12628 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012629
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012630 proc.thread.profilerControl(start, path, fd);
12631 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012632 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012633 }
12634 } catch (RemoteException e) {
12635 throw new IllegalStateException("Process disappeared");
12636 } finally {
12637 if (fd != null) {
12638 try {
12639 fd.close();
12640 } catch (IOException e) {
12641 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012642 }
12643 }
12644 }
Andy McFadden824c5102010-07-09 16:26:57 -070012645
12646 public boolean dumpHeap(String process, boolean managed,
12647 String path, ParcelFileDescriptor fd) throws RemoteException {
12648
12649 try {
12650 synchronized (this) {
12651 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12652 // its own permission (same as profileControl).
12653 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12654 != PackageManager.PERMISSION_GRANTED) {
12655 throw new SecurityException("Requires permission "
12656 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12657 }
12658
12659 if (fd == null) {
12660 throw new IllegalArgumentException("null fd");
12661 }
12662
12663 ProcessRecord proc = null;
12664 try {
12665 int pid = Integer.parseInt(process);
12666 synchronized (mPidsSelfLocked) {
12667 proc = mPidsSelfLocked.get(pid);
12668 }
12669 } catch (NumberFormatException e) {
12670 }
12671
12672 if (proc == null) {
12673 HashMap<String, SparseArray<ProcessRecord>> all
12674 = mProcessNames.getMap();
12675 SparseArray<ProcessRecord> procs = all.get(process);
12676 if (procs != null && procs.size() > 0) {
12677 proc = procs.valueAt(0);
12678 }
12679 }
12680
12681 if (proc == null || proc.thread == null) {
12682 throw new IllegalArgumentException("Unknown process: " + process);
12683 }
12684
12685 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12686 if (isSecure) {
12687 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12688 throw new SecurityException("Process not debuggable: " + proc);
12689 }
12690 }
12691
12692 proc.thread.dumpHeap(managed, path, fd);
12693 fd = null;
12694 return true;
12695 }
12696 } catch (RemoteException e) {
12697 throw new IllegalStateException("Process disappeared");
12698 } finally {
12699 if (fd != null) {
12700 try {
12701 fd.close();
12702 } catch (IOException e) {
12703 }
12704 }
12705 }
12706 }
12707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012708 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12709 public void monitor() {
12710 synchronized (this) { }
12711 }
12712}