blob: 4ec71c180e87b33a37290fe3da5a6d9b09626088 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070027import com.android.server.am.ActivityStack.ActivityState;
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080028import com.android.server.wm.WindowManagerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
Jeff Sharkeya4620792011-05-20 15:29:23 -070045import android.app.IProcessObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.app.IServiceConnection;
47import android.app.IThumbnailReceiver;
Dianne Hackbornf26fd992011-04-08 18:14:09 -070048import android.app.IThumbnailRetriever;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070050import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070051import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070053import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080054import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020055import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080056import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.content.ComponentName;
58import android.content.ContentResolver;
59import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020060import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.content.Intent;
62import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070063import android.content.IIntentReceiver;
64import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070065import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.content.pm.ActivityInfo;
67import android.content.pm.ApplicationInfo;
68import android.content.pm.ConfigurationInfo;
69import android.content.pm.IPackageDataObserver;
70import android.content.pm.IPackageManager;
71import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080072import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070074import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.content.pm.ProviderInfo;
76import android.content.pm.ResolveInfo;
77import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070078import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackborne2515ee2011-04-27 18:52:56 -040079import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.content.res.Configuration;
81import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070082import android.net.Proxy;
83import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.net.Uri;
85import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080087import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070088import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080089import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080091import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.os.FileUtils;
93import android.os.Handler;
94import android.os.IBinder;
95import android.os.IPermissionController;
96import android.os.Looper;
97import android.os.Message;
98import android.os.Parcel;
99import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700101import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.RemoteException;
103import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700104import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.os.SystemClock;
106import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800109import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800110import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import android.util.PrintWriterPrinter;
112import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700113import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import android.view.Gravity;
115import android.view.LayoutInflater;
116import android.view.View;
117import android.view.WindowManager;
118import android.view.WindowManagerPolicy;
119
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700120import java.io.BufferedInputStream;
121import java.io.BufferedOutputStream;
122import java.io.DataInputStream;
123import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124import java.io.File;
125import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700126import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700128import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200129import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800130import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131import java.io.PrintWriter;
132import java.lang.IllegalStateException;
133import java.lang.ref.WeakReference;
134import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700135import java.util.Collections;
136import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137import java.util.HashMap;
138import java.util.HashSet;
139import java.util.Iterator;
140import java.util.List;
141import java.util.Locale;
142import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700143import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700144import java.util.concurrent.atomic.AtomicBoolean;
145import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700147public final class ActivityManagerService extends ActivityManagerNative
148 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 static final String TAG = "ActivityManager";
150 static final boolean DEBUG = false;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400151 static final boolean localLOGV = DEBUG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 static final boolean DEBUG_SWITCH = localLOGV || false;
153 static final boolean DEBUG_TASKS = localLOGV || false;
154 static final boolean DEBUG_PAUSE = localLOGV || false;
155 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
156 static final boolean DEBUG_TRANSITION = localLOGV || false;
157 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700158 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700160 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static final boolean DEBUG_VISBILITY = localLOGV || false;
162 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700163 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800164 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700166 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate4a627c72011-04-01 14:43:32 -0700167 static final boolean DEBUG_BACKUP = localLOGV || true;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700168 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700169 static final boolean DEBUG_POWER = localLOGV || false;
170 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 static final boolean VALIDATE_TOKENS = false;
172 static final boolean SHOW_ACTIVITY_START_TIME = true;
173
174 // Control over CPU and battery monitoring.
175 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
176 static final boolean MONITOR_CPU_USAGE = true;
177 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
178 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
179 static final boolean MONITOR_THREAD_CPU_USAGE = false;
180
Dianne Hackborn1655be42009-05-08 14:29:01 -0700181 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700182 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 private static final String SYSTEM_SECURE = "ro.secure";
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800185 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186
187 // This is the maximum number of application processes we would like
188 // to have running. Due to the asynchronous nature of things, we can
189 // temporarily go beyond this limit.
190 static final int MAX_PROCESSES = 2;
191
192 // Set to false to leave processes running indefinitely, relying on
193 // the kernel killing them as resources are required.
194 static final boolean ENFORCE_PROCESS_LIMIT = false;
195
196 // This is the maximum number of activities that we would like to have
197 // running at a given time.
198 static final int MAX_ACTIVITIES = 20;
199
200 // Maximum number of recent tasks that we can remember.
201 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700202
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700203 // Amount of time after a call to stopAppSwitches() during which we will
204 // prevent further untrusted switches from happening.
205 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206
207 // How long we wait for a launched process to attach to the activity manager
208 // before we decide it's never going to come up for real.
209 static final int PROC_START_TIMEOUT = 10*1000;
210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 // How long to wait after going idle before forcing apps to GC.
212 static final int GC_TIMEOUT = 5*1000;
213
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700214 // The minimum amount of time between successive GC requests for a process.
215 static final int GC_MIN_INTERVAL = 60*1000;
216
Dianne Hackborn287952c2010-09-22 22:34:31 -0700217 // The rate at which we check for apps using excessive power -- 15 mins.
218 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
219
220 // The minimum sample duration we will allow before deciding we have
221 // enough data on wake locks to start killing things.
222 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
223
224 // The minimum sample duration we will allow before deciding we have
225 // enough data on CPU usage to start killing things.
226 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 // How long we allow a receiver to run before giving up on it.
229 static final int BROADCAST_TIMEOUT = 10*1000;
230
231 // How long we wait for a service to finish executing.
232 static final int SERVICE_TIMEOUT = 20*1000;
233
234 // How long a service needs to be running until restarting its process
235 // is no longer considered to be a relaunch of the service.
236 static final int SERVICE_RESTART_DURATION = 5*1000;
237
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700238 // How long a service needs to be running until it will start back at
239 // SERVICE_RESTART_DURATION after being killed.
240 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
241
242 // Multiplying factor to increase restart duration time by, for each time
243 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
244 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
245
246 // The minimum amount of time between restarting services that we allow.
247 // That is, when multiple services are restarting, we won't allow each
248 // to restart less than this amount of time from the last one.
249 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 // Maximum amount of time for there to be no activity on a service before
252 // we consider it non-essential and allow its process to go on the
253 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700254 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255
256 // How long we wait until we timeout on key dispatching.
257 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
258
259 // The minimum time we allow between crashes, for us to consider this
260 // application to be bad and stop and its services and reject broadcasts.
261 static final int MIN_CRASH_INTERVAL = 60*1000;
262
263 // How long we wait until we timeout on key dispatching during instrumentation.
264 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
265
266 // OOM adjustments for processes in various states:
267
268 // This is a process without anything currently running in it. Definitely
269 // the first to go! Value set in system/rootdir/init.rc on startup.
270 // This value is initalized in the constructor, careful when refering to
271 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800272 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273
274 // This is a process only hosting activities that are not visible,
275 // so it can be killed without any disruption. Value set in
276 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800277 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 static int HIDDEN_APP_MIN_ADJ;
279
The Android Open Source Project4df24232009-03-05 14:34:35 -0800280 // This is a process holding the home application -- we want to try
281 // avoiding killing it, even if it would normally be in the background,
282 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800283 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800284
Christopher Tate6fa95972009-06-05 18:43:55 -0700285 // This is a process currently hosting a backup operation. Killing it
286 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 // This is a process holding a secondary server -- killing it will not
290 // have much of an impact as far as the user is concerned. Value set in
291 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800292 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700294 // This is a process with a heavy-weight application. It is in the
295 // background, but we want to try to avoid killing it. Value set in
296 // system/rootdir/init.rc on startup.
297 static final int HEAVY_WEIGHT_APP_ADJ;
298
299 // This is a process only hosting components that are perceptible to the
300 // user, and we really want to avoid killing them, but they are not
301 // immediately visible. An example is background music playback. Value set in
302 // system/rootdir/init.rc on startup.
303 static final int PERCEPTIBLE_APP_ADJ;
304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 // This is a process only hosting activities that are visible to the
306 // user, so we'd prefer they don't disappear. Value set in
307 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800308 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309
310 // This is the process running the current foreground app. We'd really
311 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800312 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313
314 // This is a process running a core server, such as telephony. Definitely
315 // don't want to kill it, but doing so is not completely fatal.
316 static final int CORE_SERVER_ADJ = -12;
317
318 // The system process runs at the default adjustment.
319 static final int SYSTEM_ADJ = -16;
320
321 // Memory pages are 4K.
322 static final int PAGE_SIZE = 4*1024;
323
324 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800325 static final int EMPTY_APP_MEM;
326 static final int HIDDEN_APP_MEM;
327 static final int HOME_APP_MEM;
328 static final int BACKUP_APP_MEM;
329 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700330 static final int HEAVY_WEIGHT_APP_MEM;
331 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800332 static final int VISIBLE_APP_MEM;
333 static final int FOREGROUND_APP_MEM;
334
335 // The minimum number of hidden apps we want to be able to keep around,
336 // without empty apps being able to push them out of memory.
337 static final int MIN_HIDDEN_APPS = 2;
338
Dianne Hackborn8633e682010-04-22 16:03:41 -0700339 // The maximum number of hidden processes we will keep around before
340 // killing them; this is just a control to not let us go too crazy with
341 // keeping around processes on devices with large amounts of RAM.
342 static final int MAX_HIDDEN_APPS = 15;
343
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800344 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700345 // been idle for less than 15 seconds.
346 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800347
348 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700349 // been idle for less than 120 seconds.
350 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800351
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700352 static int getIntProp(String name, boolean allowZero) {
353 String str = SystemProperties.get(name);
354 if (str == null) {
355 throw new IllegalArgumentException("Property not defined: " + name);
356 }
357 int val = Integer.valueOf(str);
358 if (val == 0 && !allowZero) {
359 throw new IllegalArgumentException("Property must not be zero: " + name);
360 }
361 return val;
362 }
363
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800364 static {
365 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700366 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
367 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
368 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
369 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
370 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
371 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
372 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
373 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
374 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
375 // These days we use the last empty slot for hidden apps as well.
376 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
377 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
378 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
379 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
380 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
381 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
382 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
383 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
384 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
385 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387
Dan Egnor42471dd2010-01-07 17:25:22 -0800388 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389
390 static final String[] EMPTY_STRING_ARRAY = new String[0];
391
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700392 public ActivityStack mMainStack;
393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700395 * Description of a request to start a new activity, which has been held
396 * due to app switches being disabled.
397 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700398 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700399 ActivityRecord r;
400 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700401 Uri[] grantedUriPermissions;
402 int grantedMode;
403 boolean onlyIfNeeded;
404 }
405
406 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
407 = new ArrayList<PendingActivityLaunch>();
408
409 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 * List of all active broadcasts that are to be executed immediately
411 * (without waiting for another broadcast to finish). Currently this only
412 * contains broadcasts to registered receivers, to avoid spinning up
413 * a bunch of processes to execute IntentReceiver components.
414 */
415 final ArrayList<BroadcastRecord> mParallelBroadcasts
416 = new ArrayList<BroadcastRecord>();
417
418 /**
419 * List of all active broadcasts that are to be executed one at a time.
420 * The object at the top of the list is the currently activity broadcasts;
421 * those after it are waiting for the top to finish..
422 */
423 final ArrayList<BroadcastRecord> mOrderedBroadcasts
424 = new ArrayList<BroadcastRecord>();
425
426 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800427 * Historical data of past broadcasts, for debugging.
428 */
429 static final int MAX_BROADCAST_HISTORY = 100;
430 final BroadcastRecord[] mBroadcastHistory
431 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
432
433 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 * Set when we current have a BROADCAST_INTENT_MSG in flight.
435 */
436 boolean mBroadcastsScheduled = false;
437
438 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 * Activity we have told the window manager to have key focus.
440 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700441 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700442 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 * List of intents that were used to start the most recent tasks.
444 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700445 final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446
447 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 * All of the applications we currently have running organized by name.
449 * The keys are strings of the application package name (as
450 * returned by the package manager), and the keys are ApplicationRecord
451 * objects.
452 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700453 final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454
455 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700456 * The currently running heavy-weight process, if any.
457 */
458 ProcessRecord mHeavyWeightProcess = null;
459
460 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 * The last time that various processes have crashed.
462 */
463 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
464
465 /**
466 * Set of applications that we consider to be bad, and will reject
467 * incoming broadcasts from (which the user has no control over).
468 * Processes are added to this set when they have crashed twice within
469 * a minimum amount of time; they are removed from it when they are
470 * later restarted (hopefully due to some user action). The value is the
471 * time it was added to the list.
472 */
473 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
474
475 /**
476 * All of the processes we currently have running organized by pid.
477 * The keys are the pid running the application.
478 *
479 * <p>NOTE: This object is protected by its own lock, NOT the global
480 * activity manager lock!
481 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700482 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483
484 /**
485 * All of the processes that have been forced to be foreground. The key
486 * is the pid of the caller who requested it (we hold a death
487 * link on it).
488 */
489 abstract class ForegroundToken implements IBinder.DeathRecipient {
490 int pid;
491 IBinder token;
492 }
493 final SparseArray<ForegroundToken> mForegroundProcesses
494 = new SparseArray<ForegroundToken>();
495
496 /**
497 * List of records for processes that someone had tried to start before the
498 * system was ready. We don't start them at that point, but ensure they
499 * are started by the time booting is complete.
500 */
501 final ArrayList<ProcessRecord> mProcessesOnHold
502 = new ArrayList<ProcessRecord>();
503
504 /**
505 * List of records for processes that we have started and are waiting
506 * for them to call back. This is really only needed when running in
507 * single processes mode, in which case we do not have a unique pid for
508 * each process.
509 */
510 final ArrayList<ProcessRecord> mStartingProcesses
511 = new ArrayList<ProcessRecord>();
512
513 /**
514 * List of persistent applications that are in the process
515 * of being started.
516 */
517 final ArrayList<ProcessRecord> mPersistentStartingProcesses
518 = new ArrayList<ProcessRecord>();
519
520 /**
521 * Processes that are being forcibly torn down.
522 */
523 final ArrayList<ProcessRecord> mRemovedProcesses
524 = new ArrayList<ProcessRecord>();
525
526 /**
527 * List of running applications, sorted by recent usage.
528 * The first entry in the list is the least recently used.
529 * It contains ApplicationRecord objects. This list does NOT include
530 * any persistent application records (since we never want to exit them).
531 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800532 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 = new ArrayList<ProcessRecord>();
534
535 /**
536 * List of processes that should gc as soon as things are idle.
537 */
538 final ArrayList<ProcessRecord> mProcessesToGc
539 = new ArrayList<ProcessRecord>();
540
541 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800542 * This is the process holding what we currently consider to be
543 * the "home" activity.
544 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700545 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800546
547 /**
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400548 * Packages that the user has asked to have run in screen size
549 * compatibility mode instead of filling the screen.
550 */
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -0700551 final CompatModePackages mCompatModePackages;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400552
553 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 * Set of PendingResultRecord objects that are currently active.
555 */
556 final HashSet mPendingResultRecords = new HashSet();
557
558 /**
559 * Set of IntentSenderRecord objects that are currently active.
560 */
561 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
562 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
563
564 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800565 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700566 * already logged DropBox entries for. Guarded by itself. If
567 * something (rogue user app) forces this over
568 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
569 */
570 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
571 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
572
573 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700574 * Strict Mode background batched logging state.
575 *
576 * The string buffer is guarded by itself, and its lock is also
577 * used to determine if another batched write is already
578 * in-flight.
579 */
580 private final StringBuilder mStrictModeBuffer = new StringBuilder();
581
582 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700583 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
584 */
585 private boolean mPendingBroadcastTimeoutMessage;
586
587 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800588 * Intent broadcast that we have tried to start, but are
589 * waiting for its application's process to be created. We only
590 * need one (instead of a list) because we always process broadcasts
591 * one at a time, so no others can be started while waiting for this
592 * one.
593 */
594 BroadcastRecord mPendingBroadcast = null;
595
596 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700597 * The receiver index that is pending, to restart the broadcast if needed.
598 */
599 int mPendingBroadcastRecvIndex;
600
601 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 * Keeps track of all IIntentReceivers that have been registered for
603 * broadcasts. Hash keys are the receiver IBinder, hash value is
604 * a ReceiverList.
605 */
606 final HashMap mRegisteredReceivers = new HashMap();
607
608 /**
609 * Resolver for broadcast intents to registered receivers.
610 * Holds BroadcastFilter (subclass of IntentFilter).
611 */
612 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
613 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
614 @Override
615 protected boolean allowFilterResult(
616 BroadcastFilter filter, List<BroadcastFilter> dest) {
617 IBinder target = filter.receiverList.receiver.asBinder();
618 for (int i=dest.size()-1; i>=0; i--) {
619 if (dest.get(i).receiverList.receiver.asBinder() == target) {
620 return false;
621 }
622 }
623 return true;
624 }
625 };
626
627 /**
628 * State of all active sticky broadcasts. Keys are the action of the
629 * sticky Intent, values are an ArrayList of all broadcasted intents with
630 * that action (which should usually be one).
631 */
632 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
633 new HashMap<String, ArrayList<Intent>>();
634
635 /**
636 * All currently running services.
637 */
638 final HashMap<ComponentName, ServiceRecord> mServices =
639 new HashMap<ComponentName, ServiceRecord>();
640
641 /**
642 * All currently running services indexed by the Intent used to start them.
643 */
644 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
645 new HashMap<Intent.FilterComparison, ServiceRecord>();
646
647 /**
648 * All currently bound service connections. Keys are the IBinder of
649 * the client's IServiceConnection.
650 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700651 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
652 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653
654 /**
655 * List of services that we have been asked to start,
656 * but haven't yet been able to. It is used to hold start requests
657 * while waiting for their corresponding application thread to get
658 * going.
659 */
660 final ArrayList<ServiceRecord> mPendingServices
661 = new ArrayList<ServiceRecord>();
662
663 /**
664 * List of services that are scheduled to restart following a crash.
665 */
666 final ArrayList<ServiceRecord> mRestartingServices
667 = new ArrayList<ServiceRecord>();
668
669 /**
670 * List of services that are in the process of being stopped.
671 */
672 final ArrayList<ServiceRecord> mStoppingServices
673 = new ArrayList<ServiceRecord>();
674
675 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700676 * Backup/restore process management
677 */
678 String mBackupAppName = null;
679 BackupRecord mBackupTarget = null;
680
681 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 * List of PendingThumbnailsRecord objects of clients who are still
683 * waiting to receive all of the thumbnails for a task.
684 */
685 final ArrayList mPendingThumbnails = new ArrayList();
686
687 /**
688 * List of HistoryRecord objects that have been finished and must
689 * still report back to a pending thumbnail receiver.
690 */
691 final ArrayList mCancelledThumbnails = new ArrayList();
692
693 /**
694 * All of the currently running global content providers. Keys are a
695 * string containing the provider name and values are a
696 * ContentProviderRecord object containing the data about it. Note
697 * that a single provider may be published under multiple names, so
698 * there may be multiple entries here for a single one in mProvidersByClass.
699 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700700 final HashMap<String, ContentProviderRecord> mProvidersByName
701 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702
703 /**
704 * All of the currently running global content providers. Keys are a
705 * string containing the provider's implementation class and values are a
706 * ContentProviderRecord object containing the data about it.
707 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700708 final HashMap<String, ContentProviderRecord> mProvidersByClass
709 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710
711 /**
712 * List of content providers who have clients waiting for them. The
713 * application is currently being launched and the provider will be
714 * removed from this list once it is published.
715 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700716 final ArrayList<ContentProviderRecord> mLaunchingProviders
717 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718
719 /**
720 * Global set of specific Uri permissions that have been granted.
721 */
722 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
723 = new SparseArray<HashMap<Uri, UriPermission>>();
724
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800725 CoreSettingsObserver mCoreSettingsObserver;
726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 /**
728 * Thread-local storage used to carry caller permissions over through
729 * indirect content-provider access.
730 * @see #ActivityManagerService.openContentUri()
731 */
732 private class Identity {
733 public int pid;
734 public int uid;
735
736 Identity(int _pid, int _uid) {
737 pid = _pid;
738 uid = _uid;
739 }
740 }
741 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
742
743 /**
744 * All information we have collected about the runtime performance of
745 * any user id that can impact battery performance.
746 */
747 final BatteryStatsService mBatteryStatsService;
748
749 /**
750 * information about component usage
751 */
752 final UsageStatsService mUsageStatsService;
753
754 /**
755 * Current configuration information. HistoryRecord objects are given
756 * a reference to this object to indicate which configuration they are
757 * currently running in, so this object must be kept immutable.
758 */
759 Configuration mConfiguration = new Configuration();
760
761 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800762 * Current sequencing integer of the configuration, for skipping old
763 * configurations.
764 */
765 int mConfigurationSeq = 0;
766
767 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700768 * Hardware-reported OpenGLES version.
769 */
770 final int GL_ES_VERSION;
771
772 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 * List of initialization arguments to pass to all processes when binding applications to them.
774 * For example, references to the commonly used services.
775 */
776 HashMap<String, IBinder> mAppBindArgs;
777
778 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700779 * Temporary to avoid allocations. Protected by main lock.
780 */
781 final StringBuilder mStringBuilder = new StringBuilder(256);
782
783 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 * Used to control how we initialize the service.
785 */
786 boolean mStartRunning = false;
787 ComponentName mTopComponent;
788 String mTopAction;
789 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700790 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 boolean mSystemReady = false;
792 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700793 boolean mWaitingUpdate = false;
794 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700795 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700796 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797
798 Context mContext;
799
800 int mFactoryTest;
801
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700802 boolean mCheckedForSetup;
803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700805 * The time at which we will allow normal application switches again,
806 * after a call to {@link #stopAppSwitches()}.
807 */
808 long mAppSwitchesAllowedTime;
809
810 /**
811 * This is set to true after the first switch after mAppSwitchesAllowedTime
812 * is set; any switches after that will clear the time.
813 */
814 boolean mDidAppSwitch;
815
816 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700817 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700818 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700819 long mLastPowerCheckRealtime;
820
821 /**
822 * Last time (in uptime) at which we checked for power usage.
823 */
824 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700825
826 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 * Set while we are wanting to sleep, to prevent any
828 * activities from being started/resumed.
829 */
830 boolean mSleeping = false;
831
832 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700833 * Set if we are shutting down the system, similar to sleeping.
834 */
835 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836
837 /**
838 * Task identifier that activities are currently being started
839 * in. Incremented each time a new task is created.
840 * todo: Replace this with a TokenSpace class that generates non-repeating
841 * integers that won't wrap.
842 */
843 int mCurTask = 1;
844
845 /**
846 * Current sequence id for oom_adj computation traversal.
847 */
848 int mAdjSeq = 0;
849
850 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700851 * Current sequence id for process LRU updating.
852 */
853 int mLruSeq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854
855 /**
856 * System monitoring: number of processes that died since the last
857 * N procs were started.
858 */
859 int[] mProcDeaths = new int[20];
860
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700861 /**
862 * This is set if we had to do a delayed dexopt of an app before launching
863 * it, to increasing the ANR timeouts in that case.
864 */
865 boolean mDidDexOpt;
866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 String mDebugApp = null;
868 boolean mWaitForDebugger = false;
869 boolean mDebugTransient = false;
870 String mOrigDebugApp = null;
871 boolean mOrigWaitForDebugger = false;
872 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700873 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700875 final RemoteCallbackList<IActivityWatcher> mWatchers
876 = new RemoteCallbackList<IActivityWatcher>();
Jeff Sharkeya4620792011-05-20 15:29:23 -0700877
878 final RemoteCallbackList<IProcessObserver> mProcessObservers
879 = new RemoteCallbackList<IProcessObserver>();
880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 /**
882 * Callback of last caller to {@link #requestPss}.
883 */
884 Runnable mRequestPssCallback;
885
886 /**
887 * Remaining processes for which we are waiting results from the last
888 * call to {@link #requestPss}.
889 */
890 final ArrayList<ProcessRecord> mRequestPssList
891 = new ArrayList<ProcessRecord>();
892
893 /**
894 * Runtime statistics collection thread. This object's lock is used to
895 * protect all related state.
896 */
897 final Thread mProcessStatsThread;
898
899 /**
900 * Used to collect process stats when showing not responding dialog.
901 * Protected by mProcessStatsThread.
902 */
903 final ProcessStats mProcessStats = new ProcessStats(
904 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700905 final AtomicLong mLastCpuTime = new AtomicLong(0);
906 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 long mLastWriteTime = 0;
909
910 /**
911 * Set to true after the system has finished booting.
912 */
913 boolean mBooted = false;
914
915 int mProcessLimit = 0;
916
917 WindowManagerService mWindowManager;
918
919 static ActivityManagerService mSelf;
920 static ActivityThread mSystemThread;
921
922 private final class AppDeathRecipient implements IBinder.DeathRecipient {
923 final ProcessRecord mApp;
924 final int mPid;
925 final IApplicationThread mAppThread;
926
927 AppDeathRecipient(ProcessRecord app, int pid,
928 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800929 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 TAG, "New death recipient " + this
931 + " for thread " + thread.asBinder());
932 mApp = app;
933 mPid = pid;
934 mAppThread = thread;
935 }
936
937 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800938 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 TAG, "Death received in " + this
940 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 synchronized(ActivityManagerService.this) {
942 appDiedLocked(mApp, mPid, mAppThread);
943 }
944 }
945 }
946
947 static final int SHOW_ERROR_MSG = 1;
948 static final int SHOW_NOT_RESPONDING_MSG = 2;
949 static final int SHOW_FACTORY_ERROR_MSG = 3;
950 static final int UPDATE_CONFIGURATION_MSG = 4;
951 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
952 static final int WAIT_FOR_DEBUGGER_MSG = 6;
953 static final int BROADCAST_INTENT_MSG = 7;
954 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 static final int SERVICE_TIMEOUT_MSG = 12;
956 static final int UPDATE_TIME_ZONE = 13;
957 static final int SHOW_UID_ERROR_MSG = 14;
958 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700960 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700961 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800962 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700963 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
964 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700965 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700966 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700967 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700968 static final int UPDATE_HTTP_PROXY = 29;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700969 static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
Dianne Hackborn36f80f32011-05-31 18:26:45 -0700970 static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
971 static final int DISPATCH_PROCESS_DIED = 32;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972
973 AlertDialog mUidAlert;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700974 CompatModeDialog mCompatModeDialog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975
976 final Handler mHandler = new Handler() {
977 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800978 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 //}
980
981 public void handleMessage(Message msg) {
982 switch (msg.what) {
983 case SHOW_ERROR_MSG: {
984 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800985 synchronized (ActivityManagerService.this) {
986 ProcessRecord proc = (ProcessRecord)data.get("app");
987 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800988 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 return;
990 }
991 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700992 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800993 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 d.show();
995 proc.crashDialog = d;
996 } else {
997 // The device is asleep, so just pretend that the user
998 // saw a crash dialog and hit "force quit".
999 res.set(0);
1000 }
1001 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001002
1003 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 } break;
1005 case SHOW_NOT_RESPONDING_MSG: {
1006 synchronized (ActivityManagerService.this) {
1007 HashMap data = (HashMap) msg.obj;
1008 ProcessRecord proc = (ProcessRecord)data.get("app");
1009 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001010 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 return;
1012 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001013
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001014 Intent intent = new Intent("android.intent.action.ANR");
1015 if (!mProcessesReady) {
1016 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1017 }
1018 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001019 null, null, 0, null, null, null,
1020 false, false, MY_PID, Process.SYSTEM_UID);
1021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001023 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 d.show();
1025 proc.anrDialog = d;
1026 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001027
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001028 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001030 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1031 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1032 synchronized (ActivityManagerService.this) {
1033 ProcessRecord proc = (ProcessRecord) data.get("app");
1034 if (proc == null) {
1035 Slog.e(TAG, "App not found when showing strict mode dialog.");
1036 break;
1037 }
1038 if (proc.crashDialog != null) {
1039 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1040 return;
1041 }
1042 AppErrorResult res = (AppErrorResult) data.get("result");
1043 if (!mSleeping && !mShuttingDown) {
1044 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1045 d.show();
1046 proc.crashDialog = d;
1047 } else {
1048 // The device is asleep, so just pretend that the user
1049 // saw a crash dialog and hit "force quit".
1050 res.set(0);
1051 }
1052 }
1053 ensureBootCompleted();
1054 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 case SHOW_FACTORY_ERROR_MSG: {
1056 Dialog d = new FactoryErrorDialog(
1057 mContext, msg.getData().getCharSequence("msg"));
1058 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001059 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 } break;
1061 case UPDATE_CONFIGURATION_MSG: {
1062 final ContentResolver resolver = mContext.getContentResolver();
1063 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1064 } break;
1065 case GC_BACKGROUND_PROCESSES_MSG: {
1066 synchronized (ActivityManagerService.this) {
1067 performAppGcsIfAppropriateLocked();
1068 }
1069 } break;
1070 case WAIT_FOR_DEBUGGER_MSG: {
1071 synchronized (ActivityManagerService.this) {
1072 ProcessRecord app = (ProcessRecord)msg.obj;
1073 if (msg.arg1 != 0) {
1074 if (!app.waitedForDebugger) {
1075 Dialog d = new AppWaitingForDebuggerDialog(
1076 ActivityManagerService.this,
1077 mContext, app);
1078 app.waitDialog = d;
1079 app.waitedForDebugger = true;
1080 d.show();
1081 }
1082 } else {
1083 if (app.waitDialog != null) {
1084 app.waitDialog.dismiss();
1085 app.waitDialog = null;
1086 }
1087 }
1088 }
1089 } break;
1090 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001091 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 TAG, "Received BROADCAST_INTENT_MSG");
1093 processNextBroadcast(true);
1094 } break;
1095 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001096 synchronized (ActivityManagerService.this) {
1097 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001101 if (mDidDexOpt) {
1102 mDidDexOpt = false;
1103 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1104 nmsg.obj = msg.obj;
1105 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1106 return;
1107 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 serviceTimeout((ProcessRecord)msg.obj);
1109 } break;
1110 case UPDATE_TIME_ZONE: {
1111 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001112 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1113 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 if (r.thread != null) {
1115 try {
1116 r.thread.updateTimeZone();
1117 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001118 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 }
1120 }
1121 }
1122 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001123 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001124 case CLEAR_DNS_CACHE: {
1125 synchronized (ActivityManagerService.this) {
1126 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1127 ProcessRecord r = mLruProcesses.get(i);
1128 if (r.thread != null) {
1129 try {
1130 r.thread.clearDnsCache();
1131 } catch (RemoteException ex) {
1132 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1133 }
1134 }
1135 }
1136 }
1137 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001138 case UPDATE_HTTP_PROXY: {
1139 ProxyProperties proxy = (ProxyProperties)msg.obj;
1140 String host = "";
1141 String port = "";
1142 String exclList = "";
1143 if (proxy != null) {
1144 host = proxy.getHost();
1145 port = Integer.toString(proxy.getPort());
1146 exclList = proxy.getExclusionList();
1147 }
1148 synchronized (ActivityManagerService.this) {
1149 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1150 ProcessRecord r = mLruProcesses.get(i);
1151 if (r.thread != null) {
1152 try {
1153 r.thread.setHttpProxy(host, port, exclList);
1154 } catch (RemoteException ex) {
1155 Slog.w(TAG, "Failed to update http proxy for: " +
1156 r.info.processName);
1157 }
1158 }
1159 }
1160 }
1161 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 case SHOW_UID_ERROR_MSG: {
1163 // XXX This is a temporary dialog, no need to localize.
1164 AlertDialog d = new BaseErrorDialog(mContext);
1165 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1166 d.setCancelable(false);
1167 d.setTitle("System UIDs Inconsistent");
1168 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 +02001169 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1171 mUidAlert = d;
1172 d.show();
1173 } break;
1174 case IM_FEELING_LUCKY_MSG: {
1175 if (mUidAlert != null) {
1176 mUidAlert.dismiss();
1177 mUidAlert = null;
1178 }
1179 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001181 if (mDidDexOpt) {
1182 mDidDexOpt = false;
1183 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1184 nmsg.obj = msg.obj;
1185 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1186 return;
1187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001188 ProcessRecord app = (ProcessRecord)msg.obj;
1189 synchronized (ActivityManagerService.this) {
1190 processStartTimedOutLocked(app);
1191 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001192 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001193 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1194 synchronized (ActivityManagerService.this) {
1195 doPendingActivityLaunchesLocked(true);
1196 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001197 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001198 case KILL_APPLICATION_MSG: {
1199 synchronized (ActivityManagerService.this) {
1200 int uid = msg.arg1;
1201 boolean restart = (msg.arg2 == 1);
1202 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001203 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001204 }
1205 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001206 case FINALIZE_PENDING_INTENT_MSG: {
1207 ((PendingIntentRecord)msg.obj).completeFinalize();
1208 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001209 case POST_HEAVY_NOTIFICATION_MSG: {
1210 INotificationManager inm = NotificationManager.getService();
1211 if (inm == null) {
1212 return;
1213 }
1214
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001215 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001216 ProcessRecord process = root.app;
1217 if (process == null) {
1218 return;
1219 }
1220
1221 try {
1222 Context context = mContext.createPackageContext(process.info.packageName, 0);
1223 String text = mContext.getString(R.string.heavy_weight_notification,
1224 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1225 Notification notification = new Notification();
1226 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1227 notification.when = 0;
1228 notification.flags = Notification.FLAG_ONGOING_EVENT;
1229 notification.tickerText = text;
1230 notification.defaults = 0; // please be quiet
1231 notification.sound = null;
1232 notification.vibrate = null;
1233 notification.setLatestEventInfo(context, text,
1234 mContext.getText(R.string.heavy_weight_notification_detail),
1235 PendingIntent.getActivity(mContext, 0, root.intent,
1236 PendingIntent.FLAG_CANCEL_CURRENT));
1237
1238 try {
1239 int[] outId = new int[1];
1240 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1241 notification, outId);
1242 } catch (RuntimeException e) {
1243 Slog.w(ActivityManagerService.TAG,
1244 "Error showing notification for heavy-weight app", e);
1245 } catch (RemoteException e) {
1246 }
1247 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001248 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001249 }
1250 } break;
1251 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1252 INotificationManager inm = NotificationManager.getService();
1253 if (inm == null) {
1254 return;
1255 }
1256 try {
1257 inm.cancelNotification("android",
1258 R.string.heavy_weight_notification);
1259 } catch (RuntimeException e) {
1260 Slog.w(ActivityManagerService.TAG,
1261 "Error canceling notification for service", e);
1262 } catch (RemoteException e) {
1263 }
1264 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001265 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1266 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001267 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001268 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001269 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1270 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001271 }
1272 } break;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001273 case SHOW_COMPAT_MODE_DIALOG_MSG: {
1274 synchronized (ActivityManagerService.this) {
1275 ActivityRecord ar = (ActivityRecord)msg.obj;
1276 if (mCompatModeDialog != null) {
1277 if (mCompatModeDialog.mAppInfo.packageName.equals(
1278 ar.info.applicationInfo.packageName)) {
1279 return;
1280 }
1281 mCompatModeDialog.dismiss();
1282 mCompatModeDialog = null;
1283 }
Dianne Hackborn29478262011-06-07 15:44:22 -07001284 if (ar != null && false) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001285 if (mCompatModePackages.getPackageAskCompatModeLocked(
1286 ar.packageName)) {
1287 int mode = mCompatModePackages.computeCompatModeLocked(
1288 ar.info.applicationInfo);
1289 if (mode == ActivityManager.COMPAT_MODE_DISABLED
1290 || mode == ActivityManager.COMPAT_MODE_ENABLED) {
1291 mCompatModeDialog = new CompatModeDialog(
1292 ActivityManagerService.this, mContext,
1293 ar.info.applicationInfo);
1294 mCompatModeDialog.show();
1295 }
1296 }
1297 }
1298 }
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001299 break;
1300 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001301 case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001302 final int pid = msg.arg1;
1303 final int uid = msg.arg2;
1304 final boolean foregroundActivities = (Boolean) msg.obj;
1305 dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001306 break;
1307 }
1308 case DISPATCH_PROCESS_DIED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001309 final int pid = msg.arg1;
1310 final int uid = msg.arg2;
1311 dispatchProcessDied(pid, uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001312 break;
1313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314 }
1315 }
1316 };
1317
1318 public static void setSystemProcess() {
1319 try {
1320 ActivityManagerService m = mSelf;
1321
1322 ServiceManager.addService("activity", m);
1323 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07001324 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325 if (MONITOR_CPU_USAGE) {
1326 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 ServiceManager.addService("permission", new PermissionController(m));
1329
1330 ApplicationInfo info =
1331 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001332 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001333 mSystemThread.installSystemApplicationInfo(info);
1334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 synchronized (mSelf) {
1336 ProcessRecord app = mSelf.newProcessRecordLocked(
1337 mSystemThread.getApplicationThread(), info,
1338 info.processName);
1339 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001340 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341 app.maxAdj = SYSTEM_ADJ;
1342 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1343 synchronized (mSelf.mPidsSelfLocked) {
1344 mSelf.mPidsSelfLocked.put(app.pid, app);
1345 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001346 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 }
1348 } catch (PackageManager.NameNotFoundException e) {
1349 throw new RuntimeException(
1350 "Unable to find android system package", e);
1351 }
1352 }
1353
1354 public void setWindowManager(WindowManagerService wm) {
1355 mWindowManager = wm;
1356 }
1357
1358 public static final Context main(int factoryTest) {
1359 AThread thr = new AThread();
1360 thr.start();
1361
1362 synchronized (thr) {
1363 while (thr.mService == null) {
1364 try {
1365 thr.wait();
1366 } catch (InterruptedException e) {
1367 }
1368 }
1369 }
1370
1371 ActivityManagerService m = thr.mService;
1372 mSelf = m;
1373 ActivityThread at = ActivityThread.systemMain();
1374 mSystemThread = at;
1375 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001376 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 m.mContext = context;
1378 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001379 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380
1381 m.mBatteryStatsService.publish(context);
1382 m.mUsageStatsService.publish(context);
1383
1384 synchronized (thr) {
1385 thr.mReady = true;
1386 thr.notifyAll();
1387 }
1388
1389 m.startRunning(null, null, null, null);
1390
1391 return context;
1392 }
1393
1394 public static ActivityManagerService self() {
1395 return mSelf;
1396 }
1397
1398 static class AThread extends Thread {
1399 ActivityManagerService mService;
1400 boolean mReady = false;
1401
1402 public AThread() {
1403 super("ActivityManager");
1404 }
1405
1406 public void run() {
1407 Looper.prepare();
1408
1409 android.os.Process.setThreadPriority(
1410 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001411 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412
1413 ActivityManagerService m = new ActivityManagerService();
1414
1415 synchronized (this) {
1416 mService = m;
1417 notifyAll();
1418 }
1419
1420 synchronized (this) {
1421 while (!mReady) {
1422 try {
1423 wait();
1424 } catch (InterruptedException e) {
1425 }
1426 }
1427 }
1428
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001429 // For debug builds, log event loop stalls to dropbox for analysis.
1430 if (StrictMode.conditionallyEnableDebugLogging()) {
1431 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1432 }
1433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 Looper.loop();
1435 }
1436 }
1437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 static class MemBinder extends Binder {
1439 ActivityManagerService mActivityManagerService;
1440 MemBinder(ActivityManagerService activityManagerService) {
1441 mActivityManagerService = activityManagerService;
1442 }
1443
1444 @Override
1445 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001446 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 }
1448 }
1449
Chet Haase9c1e23b2011-03-24 10:51:31 -07001450 static class GraphicsBinder extends Binder {
1451 ActivityManagerService mActivityManagerService;
1452 GraphicsBinder(ActivityManagerService activityManagerService) {
1453 mActivityManagerService = activityManagerService;
1454 }
1455
1456 @Override
1457 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001458 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07001459 }
1460 }
1461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 static class CpuBinder extends Binder {
1463 ActivityManagerService mActivityManagerService;
1464 CpuBinder(ActivityManagerService activityManagerService) {
1465 mActivityManagerService = activityManagerService;
1466 }
1467
1468 @Override
1469 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1470 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001471 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1472 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1473 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 }
1475 }
1476 }
1477
1478 private ActivityManagerService() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001479 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 File dataDir = Environment.getDataDirectory();
1482 File systemDir = new File(dataDir, "system");
1483 systemDir.mkdirs();
1484 mBatteryStatsService = new BatteryStatsService(new File(
1485 systemDir, "batterystats.bin").toString());
1486 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001487 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001488 mOnBattery = DEBUG_POWER ? true
1489 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001490 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001492 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001493 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494
Jack Palevichb90d28c2009-07-22 15:35:24 -07001495 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1496 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1497
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001498 mConfiguration.setToDefaults();
1499 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 mProcessStats.init();
1501
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07001502 mCompatModePackages = new CompatModePackages(this, systemDir);
1503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 // Add ourself to the Watchdog monitors.
1505 Watchdog.getInstance().addMonitor(this);
1506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 mProcessStatsThread = new Thread("ProcessStats") {
1508 public void run() {
1509 while (true) {
1510 try {
1511 try {
1512 synchronized(this) {
1513 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001514 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001516 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 // + ", write delay=" + nextWriteDelay);
1518 if (nextWriteDelay < nextCpuDelay) {
1519 nextCpuDelay = nextWriteDelay;
1520 }
1521 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001522 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 this.wait(nextCpuDelay);
1524 }
1525 }
1526 } catch (InterruptedException e) {
1527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 updateCpuStatsNow();
1529 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001530 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 }
1532 }
1533 }
1534 };
1535 mProcessStatsThread.start();
1536 }
1537
1538 @Override
1539 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1540 throws RemoteException {
1541 try {
1542 return super.onTransact(code, data, reply, flags);
1543 } catch (RuntimeException e) {
1544 // The activity manager only throws security exceptions, so let's
1545 // log all others.
1546 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001547 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 }
1549 throw e;
1550 }
1551 }
1552
1553 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001554 final long now = SystemClock.uptimeMillis();
1555 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1556 return;
1557 }
1558 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1559 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 mProcessStatsThread.notify();
1561 }
1562 }
1563 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 void updateCpuStatsNow() {
1566 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001567 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 final long now = SystemClock.uptimeMillis();
1569 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001572 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1573 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 haveNewCpuStats = true;
1575 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001576 //Slog.i(TAG, mProcessStats.printCurrentState());
1577 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578 // + mProcessStats.getTotalCpuPercent() + "%");
1579
Joe Onorato8a9b2202010-02-26 18:56:32 -08001580 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 if ("true".equals(SystemProperties.get("events.cpu"))) {
1582 int user = mProcessStats.getLastUserTime();
1583 int system = mProcessStats.getLastSystemTime();
1584 int iowait = mProcessStats.getLastIoWaitTime();
1585 int irq = mProcessStats.getLastIrqTime();
1586 int softIrq = mProcessStats.getLastSoftIrqTime();
1587 int idle = mProcessStats.getLastIdleTime();
1588
1589 int total = user + system + iowait + irq + softIrq + idle;
1590 if (total == 0) total = 1;
1591
Doug Zongker2bec3d42009-12-04 12:52:44 -08001592 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 ((user+system+iowait+irq+softIrq) * 100) / total,
1594 (user * 100) / total,
1595 (system * 100) / total,
1596 (iowait * 100) / total,
1597 (irq * 100) / total,
1598 (softIrq * 100) / total);
1599 }
1600 }
1601
Amith Yamasanie43530a2009-08-21 13:11:37 -07001602 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001603 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001604 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605 synchronized(mPidsSelfLocked) {
1606 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001607 if (mOnBattery) {
1608 int perc = bstats.startAddingCpuLocked();
1609 int totalUTime = 0;
1610 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001611 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001613 ProcessStats.Stats st = mProcessStats.getStats(i);
1614 if (!st.working) {
1615 continue;
1616 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001618 int otherUTime = (st.rel_utime*perc)/100;
1619 int otherSTime = (st.rel_stime*perc)/100;
1620 totalUTime += otherUTime;
1621 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 if (pr != null) {
1623 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001624 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1625 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001626 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001627 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001628 } else {
1629 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001630 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001631 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001632 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1633 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001634 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 }
1637 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001638 bstats.finishAddingCpuLocked(perc, totalUTime,
1639 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 }
1641 }
1642 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1645 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001646 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 }
1648 }
1649 }
1650 }
1651
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001652 @Override
1653 public void batteryNeedsCpuUpdate() {
1654 updateCpuStatsNow();
1655 }
1656
1657 @Override
1658 public void batteryPowerChanged(boolean onBattery) {
1659 // When plugging in, update the CPU stats first before changing
1660 // the plug state.
1661 updateCpuStatsNow();
1662 synchronized (this) {
1663 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001664 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001665 }
1666 }
1667 }
1668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669 /**
1670 * Initialize the application bind args. These are passed to each
1671 * process when the bindApplication() IPC is sent to the process. They're
1672 * lazily setup to make sure the services are running when they're asked for.
1673 */
1674 private HashMap<String, IBinder> getCommonServicesLocked() {
1675 if (mAppBindArgs == null) {
1676 mAppBindArgs = new HashMap<String, IBinder>();
1677
1678 // Setup the application init args
1679 mAppBindArgs.put("package", ServiceManager.getService("package"));
1680 mAppBindArgs.put("window", ServiceManager.getService("window"));
1681 mAppBindArgs.put(Context.ALARM_SERVICE,
1682 ServiceManager.getService(Context.ALARM_SERVICE));
1683 }
1684 return mAppBindArgs;
1685 }
1686
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001687 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 if (mFocusedActivity != r) {
1689 mFocusedActivity = r;
1690 mWindowManager.setFocusedApp(r, true);
1691 }
1692 }
1693
Dianne Hackborn906497c2010-05-10 15:57:38 -07001694 private final void updateLruProcessInternalLocked(ProcessRecord app,
1695 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001697 int lrui = mLruProcesses.indexOf(app);
1698 if (lrui >= 0) mLruProcesses.remove(lrui);
1699
1700 int i = mLruProcesses.size()-1;
1701 int skipTop = 0;
1702
Dianne Hackborn906497c2010-05-10 15:57:38 -07001703 app.lruSeq = mLruSeq;
1704
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001705 // compute the new weight for this process.
1706 if (updateActivityTime) {
1707 app.lastActivityTime = SystemClock.uptimeMillis();
1708 }
1709 if (app.activities.size() > 0) {
1710 // If this process has activities, we more strongly want to keep
1711 // it around.
1712 app.lruWeight = app.lastActivityTime;
1713 } else if (app.pubProviders.size() > 0) {
1714 // If this process contains content providers, we want to keep
1715 // it a little more strongly.
1716 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1717 // Also don't let it kick out the first few "real" hidden processes.
1718 skipTop = MIN_HIDDEN_APPS;
1719 } else {
1720 // If this process doesn't have activities, we less strongly
1721 // want to keep it around, and generally want to avoid getting
1722 // in front of any very recently used activities.
1723 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1724 // Also don't let it kick out the first few "real" hidden processes.
1725 skipTop = MIN_HIDDEN_APPS;
1726 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001727
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001728 while (i >= 0) {
1729 ProcessRecord p = mLruProcesses.get(i);
1730 // If this app shouldn't be in front of the first N background
1731 // apps, then skip over that many that are currently hidden.
1732 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1733 skipTop--;
1734 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001735 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001736 mLruProcesses.add(i+1, app);
1737 break;
1738 }
1739 i--;
1740 }
1741 if (i < 0) {
1742 mLruProcesses.add(0, app);
1743 }
1744
Dianne Hackborn906497c2010-05-10 15:57:38 -07001745 // If the app is currently using a content provider or service,
1746 // bump those processes as well.
1747 if (app.connections.size() > 0) {
1748 for (ConnectionRecord cr : app.connections) {
1749 if (cr.binding != null && cr.binding.service != null
1750 && cr.binding.service.app != null
1751 && cr.binding.service.app.lruSeq != mLruSeq) {
1752 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1753 updateActivityTime, i+1);
1754 }
1755 }
1756 }
1757 if (app.conProviders.size() > 0) {
1758 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1759 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1760 updateLruProcessInternalLocked(cpr.app, oomAdj,
1761 updateActivityTime, i+1);
1762 }
1763 }
1764 }
1765
Joe Onorato8a9b2202010-02-26 18:56:32 -08001766 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 if (oomAdj) {
1768 updateOomAdjLocked();
1769 }
1770 }
1771
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001772 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001773 boolean oomAdj, boolean updateActivityTime) {
1774 mLruSeq++;
1775 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1776 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001777
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001778 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 String processName, int uid) {
1780 if (uid == Process.SYSTEM_UID) {
1781 // The system gets to run in any process. If there are multiple
1782 // processes with the same uid, just pick the first (this
1783 // should never happen).
1784 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1785 processName);
1786 return procs != null ? procs.valueAt(0) : null;
1787 }
1788 ProcessRecord proc = mProcessNames.get(processName, uid);
1789 return proc;
1790 }
1791
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001792 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001793 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001794 try {
1795 if (pm.performDexOpt(packageName)) {
1796 mDidDexOpt = true;
1797 }
1798 } catch (RemoteException e) {
1799 }
1800 }
1801
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001802 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 int transit = mWindowManager.getPendingAppTransition();
1804 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1805 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1806 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1807 }
1808
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001809 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001811 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1813 // We don't have to do anything more if:
1814 // (1) There is an existing application record; and
1815 // (2) The caller doesn't think it is dead, OR there is no thread
1816 // object attached to it so we know it couldn't have crashed; and
1817 // (3) There is a pid assigned to it, so it is either starting or
1818 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001819 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 + " app=" + app + " knownToBeDead=" + knownToBeDead
1821 + " thread=" + (app != null ? app.thread : null)
1822 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001823 if (app != null && app.pid > 0) {
1824 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001825 // We already have the app running, or are waiting for it to
1826 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001827 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001828 return app;
1829 } else {
1830 // An application record is attached to a previous process,
1831 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001832 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001833 handleAppDiedLocked(app, true);
1834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 String hostingNameStr = hostingName != null
1838 ? hostingName.flattenToShortString() : null;
1839
1840 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1841 // If we are in the background, then check to see if this process
1842 // is bad. If so, we will just silently fail.
1843 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001844 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1845 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 return null;
1847 }
1848 } else {
1849 // When the user is explicitly starting a process, then clear its
1850 // crash count so that we won't make it bad until they see at
1851 // least one crash dialog again, and make the process good again
1852 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001853 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1854 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855 mProcessCrashTimes.remove(info.processName, info.uid);
1856 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001857 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001858 info.processName);
1859 mBadProcesses.remove(info.processName, info.uid);
1860 if (app != null) {
1861 app.bad = false;
1862 }
1863 }
1864 }
1865
1866 if (app == null) {
1867 app = newProcessRecordLocked(null, info, processName);
1868 mProcessNames.put(processName, info.uid, app);
1869 } else {
1870 // If this is a new package in the process, add the package to the list
1871 app.addPackage(info.packageName);
1872 }
1873
1874 // If the system is not ready yet, then hold off on starting this
1875 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001876 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001877 && !isAllowedWhileBooting(info)
1878 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 if (!mProcessesOnHold.contains(app)) {
1880 mProcessesOnHold.add(app);
1881 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001882 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 return app;
1884 }
1885
1886 startProcessLocked(app, hostingType, hostingNameStr);
1887 return (app.pid != 0) ? app : null;
1888 }
1889
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001890 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1891 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1892 }
1893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 private final void startProcessLocked(ProcessRecord app,
1895 String hostingType, String hostingNameStr) {
1896 if (app.pid > 0 && app.pid != MY_PID) {
1897 synchronized (mPidsSelfLocked) {
1898 mPidsSelfLocked.remove(app.pid);
1899 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1900 }
1901 app.pid = 0;
1902 }
1903
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001904 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1905 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906 mProcessesOnHold.remove(app);
1907
1908 updateCpuStats();
1909
1910 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1911 mProcDeaths[0] = 0;
1912
1913 try {
1914 int uid = app.info.uid;
1915 int[] gids = null;
1916 try {
1917 gids = mContext.getPackageManager().getPackageGids(
1918 app.info.packageName);
1919 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001920 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001921 }
1922 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1923 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1924 && mTopComponent != null
1925 && app.processName.equals(mTopComponent.getPackageName())) {
1926 uid = 0;
1927 }
1928 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1929 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1930 uid = 0;
1931 }
1932 }
1933 int debugFlags = 0;
1934 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1935 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
Elliott Hughesfa36aee2011-06-17 14:39:41 -07001936 // Also turn on CheckJNI for debuggable apps. It's quite
1937 // awkward to turn on otherwise.
1938 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001940 // Run the app in safe mode if its manifest requests so or the
1941 // system is booted in safe mode.
1942 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1943 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001944 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1947 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1948 }
1949 if ("1".equals(SystemProperties.get("debug.assert"))) {
1950 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1951 }
1952 int pid = Process.start("android.app.ActivityThread",
Jeff Brownebed7d62011-05-16 17:08:42 -07001953 app.processName, uid, uid, gids, debugFlags, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001954 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1955 synchronized (bs) {
1956 if (bs.isOnBattery()) {
1957 app.batteryStats.incStartsLocked();
1958 }
1959 }
1960
Doug Zongker2bec3d42009-12-04 12:52:44 -08001961 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001962 app.processName, hostingType,
1963 hostingNameStr != null ? hostingNameStr : "");
1964
1965 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001966 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967 }
1968
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001969 StringBuilder buf = mStringBuilder;
1970 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001971 buf.append("Start proc ");
1972 buf.append(app.processName);
1973 buf.append(" for ");
1974 buf.append(hostingType);
1975 if (hostingNameStr != null) {
1976 buf.append(" ");
1977 buf.append(hostingNameStr);
1978 }
1979 buf.append(": pid=");
1980 buf.append(pid);
1981 buf.append(" uid=");
1982 buf.append(uid);
1983 buf.append(" gids={");
1984 if (gids != null) {
1985 for (int gi=0; gi<gids.length; gi++) {
1986 if (gi != 0) buf.append(", ");
1987 buf.append(gids[gi]);
1988
1989 }
1990 }
1991 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001992 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 if (pid == 0 || pid == MY_PID) {
1994 // Processes are being emulated with threads.
1995 app.pid = MY_PID;
1996 app.removed = false;
1997 mStartingProcesses.add(app);
1998 } else if (pid > 0) {
1999 app.pid = pid;
2000 app.removed = false;
2001 synchronized (mPidsSelfLocked) {
2002 this.mPidsSelfLocked.put(pid, app);
2003 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2004 msg.obj = app;
2005 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2006 }
2007 } else {
2008 app.pid = 0;
2009 RuntimeException e = new RuntimeException(
2010 "Failure starting process " + app.processName
2011 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002012 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 }
2014 } catch (RuntimeException e) {
2015 // XXX do better error recovery.
2016 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002017 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002018 }
2019 }
2020
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002021 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002022 if (resumed) {
2023 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2024 } else {
2025 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2026 }
2027 }
2028
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002029 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002030 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2031 && mTopAction == null) {
2032 // We are running in factory test mode, but unable to find
2033 // the factory test app, so just sit around displaying the
2034 // error message and don't try to start anything.
2035 return false;
2036 }
2037 Intent intent = new Intent(
2038 mTopAction,
2039 mTopData != null ? Uri.parse(mTopData) : null);
2040 intent.setComponent(mTopComponent);
2041 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2042 intent.addCategory(Intent.CATEGORY_HOME);
2043 }
2044 ActivityInfo aInfo =
2045 intent.resolveActivityInfo(mContext.getPackageManager(),
2046 STOCK_PM_FLAGS);
2047 if (aInfo != null) {
2048 intent.setComponent(new ComponentName(
2049 aInfo.applicationInfo.packageName, aInfo.name));
2050 // Don't do this if the home app is currently being
2051 // instrumented.
2052 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2053 aInfo.applicationInfo.uid);
2054 if (app == null || app.instrumentationClass == null) {
2055 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002056 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002057 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002058 }
2059 }
2060
2061
2062 return true;
2063 }
2064
2065 /**
2066 * Starts the "new version setup screen" if appropriate.
2067 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002068 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002069 // Only do this once per boot.
2070 if (mCheckedForSetup) {
2071 return;
2072 }
2073
2074 // We will show this screen if the current one is a different
2075 // version than the last one shown, and we are not running in
2076 // low-level factory test mode.
2077 final ContentResolver resolver = mContext.getContentResolver();
2078 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2079 Settings.Secure.getInt(resolver,
2080 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2081 mCheckedForSetup = true;
2082
2083 // See if we should be showing the platform update setup UI.
2084 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2085 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2086 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2087
2088 // We don't allow third party apps to replace this.
2089 ResolveInfo ri = null;
2090 for (int i=0; ris != null && i<ris.size(); i++) {
2091 if ((ris.get(i).activityInfo.applicationInfo.flags
2092 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2093 ri = ris.get(i);
2094 break;
2095 }
2096 }
2097
2098 if (ri != null) {
2099 String vers = ri.activityInfo.metaData != null
2100 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2101 : null;
2102 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2103 vers = ri.activityInfo.applicationInfo.metaData.getString(
2104 Intent.METADATA_SETUP_VERSION);
2105 }
2106 String lastVers = Settings.Secure.getString(
2107 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2108 if (vers != null && !vers.equals(lastVers)) {
2109 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2110 intent.setComponent(new ComponentName(
2111 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002112 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002113 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002114 }
2115 }
2116 }
2117 }
2118
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002119 CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002120 return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002121 }
2122
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002123 public int getFrontActivityScreenCompatMode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002124 synchronized (this) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002125 return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
2126 }
2127 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002128
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002129 public void setFrontActivityScreenCompatMode(int mode) {
2130 synchronized (this) {
2131 mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
2132 }
2133 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002134
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002135 public int getPackageScreenCompatMode(String packageName) {
2136 synchronized (this) {
2137 return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
2138 }
2139 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002140
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002141 public void setPackageScreenCompatMode(String packageName, int mode) {
2142 synchronized (this) {
2143 mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002144 }
2145 }
2146
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002147 public boolean getPackageAskScreenCompat(String packageName) {
2148 synchronized (this) {
2149 return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
2150 }
2151 }
2152
2153 public void setPackageAskScreenCompat(String packageName, boolean ask) {
2154 synchronized (this) {
2155 mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
2156 }
2157 }
2158
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002159 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002160 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002161
2162 final int identHash = System.identityHashCode(r);
2163 updateUsageStats(r, true);
2164
2165 int i = mWatchers.beginBroadcast();
2166 while (i > 0) {
2167 i--;
2168 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2169 if (w != null) {
2170 try {
2171 w.activityResuming(identHash);
2172 } catch (RemoteException e) {
2173 }
2174 }
2175 }
2176 mWatchers.finishBroadcast();
2177 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178
Jeff Sharkeya4620792011-05-20 15:29:23 -07002179 private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2180 int i = mProcessObservers.beginBroadcast();
2181 while (i > 0) {
2182 i--;
2183 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2184 if (observer != null) {
2185 try {
2186 observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
2187 } catch (RemoteException e) {
2188 }
2189 }
2190 }
2191 mProcessObservers.finishBroadcast();
2192 }
2193
2194 private void dispatchProcessDied(int pid, int uid) {
2195 int i = mProcessObservers.beginBroadcast();
2196 while (i > 0) {
2197 i--;
2198 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2199 if (observer != null) {
2200 try {
2201 observer.onProcessDied(pid, uid);
2202 } catch (RemoteException e) {
2203 }
2204 }
2205 }
2206 mProcessObservers.finishBroadcast();
2207 }
2208
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002209 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002210 final int N = mPendingActivityLaunches.size();
2211 if (N <= 0) {
2212 return;
2213 }
2214 for (int i=0; i<N; i++) {
2215 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002216 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002217 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2218 doResume && i == (N-1));
2219 }
2220 mPendingActivityLaunches.clear();
2221 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002222
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002223 public final int startActivity(IApplicationThread caller,
2224 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2225 int grantedMode, IBinder resultTo,
2226 String resultWho, int requestCode, boolean onlyIfNeeded,
2227 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002228 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002229 grantedUriPermissions, grantedMode, resultTo, resultWho,
2230 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002231 }
2232
2233 public final WaitResult startActivityAndWait(IApplicationThread caller,
2234 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2235 int grantedMode, IBinder resultTo,
2236 String resultWho, int requestCode, boolean onlyIfNeeded,
2237 boolean debug) {
2238 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002239 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002240 grantedUriPermissions, grantedMode, resultTo, resultWho,
2241 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002242 return res;
2243 }
2244
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002245 public final int startActivityWithConfig(IApplicationThread caller,
2246 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2247 int grantedMode, IBinder resultTo,
2248 String resultWho, int requestCode, boolean onlyIfNeeded,
2249 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002250 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002251 grantedUriPermissions, grantedMode, resultTo, resultWho,
2252 requestCode, onlyIfNeeded, debug, null, config);
2253 }
2254
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002255 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002256 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002257 IBinder resultTo, String resultWho, int requestCode,
2258 int flagsMask, int flagsValues) {
2259 // Refuse possible leaked file descriptors
2260 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2261 throw new IllegalArgumentException("File descriptors passed in Intent");
2262 }
2263
2264 IIntentSender sender = intent.getTarget();
2265 if (!(sender instanceof PendingIntentRecord)) {
2266 throw new IllegalArgumentException("Bad PendingIntent object");
2267 }
2268
2269 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002270
2271 synchronized (this) {
2272 // If this is coming from the currently resumed activity, it is
2273 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002274 if (mMainStack.mResumedActivity != null
2275 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002276 Binder.getCallingUid()) {
2277 mAppSwitchesAllowedTime = 0;
2278 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002279 }
2280
2281 return pir.sendInner(0, fillInIntent, resolvedType,
2282 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2283 }
2284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 public boolean startNextMatchingActivity(IBinder callingActivity,
2286 Intent intent) {
2287 // Refuse possible leaked file descriptors
2288 if (intent != null && intent.hasFileDescriptors() == true) {
2289 throw new IllegalArgumentException("File descriptors passed in Intent");
2290 }
2291
2292 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002293 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002294 if (index < 0) {
2295 return false;
2296 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002297 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002298 if (r.app == null || r.app.thread == null) {
2299 // The caller is not running... d'oh!
2300 return false;
2301 }
2302 intent = new Intent(intent);
2303 // The caller is not allowed to change the data.
2304 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2305 // And we are resetting to find the next component...
2306 intent.setComponent(null);
2307
2308 ActivityInfo aInfo = null;
2309 try {
2310 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002311 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002313 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314
2315 // Look for the original activity in the list...
2316 final int N = resolves != null ? resolves.size() : 0;
2317 for (int i=0; i<N; i++) {
2318 ResolveInfo rInfo = resolves.get(i);
2319 if (rInfo.activityInfo.packageName.equals(r.packageName)
2320 && rInfo.activityInfo.name.equals(r.info.name)) {
2321 // We found the current one... the next matching is
2322 // after it.
2323 i++;
2324 if (i<N) {
2325 aInfo = resolves.get(i).activityInfo;
2326 }
2327 break;
2328 }
2329 }
2330 } catch (RemoteException e) {
2331 }
2332
2333 if (aInfo == null) {
2334 // Nobody who is next!
2335 return false;
2336 }
2337
2338 intent.setComponent(new ComponentName(
2339 aInfo.applicationInfo.packageName, aInfo.name));
2340 intent.setFlags(intent.getFlags()&~(
2341 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2342 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2343 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2344 Intent.FLAG_ACTIVITY_NEW_TASK));
2345
2346 // Okay now we need to start the new activity, replacing the
2347 // currently running activity. This is a little tricky because
2348 // we want to start the new one as if the current one is finished,
2349 // but not finish the current one first so that there is no flicker.
2350 // And thus...
2351 final boolean wasFinishing = r.finishing;
2352 r.finishing = true;
2353
2354 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002355 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002356 final String resultWho = r.resultWho;
2357 final int requestCode = r.requestCode;
2358 r.resultTo = null;
2359 if (resultTo != null) {
2360 resultTo.removeResultsLocked(r, resultWho, requestCode);
2361 }
2362
2363 final long origId = Binder.clearCallingIdentity();
2364 // XXX we are not dealing with propagating grantedUriPermissions...
2365 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002366 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002368 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 Binder.restoreCallingIdentity(origId);
2370
2371 r.finishing = wasFinishing;
2372 if (res != START_SUCCESS) {
2373 return false;
2374 }
2375 return true;
2376 }
2377 }
2378
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002379 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 Intent intent, String resolvedType, IBinder resultTo,
2381 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002382
2383 // This is so super not safe, that only the system (or okay root)
2384 // can do it.
2385 final int callingUid = Binder.getCallingUid();
2386 if (callingUid != 0 && callingUid != Process.myUid()) {
2387 throw new SecurityException(
2388 "startActivityInPackage only available to the system");
2389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002391 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2392 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2393 }
2394
2395 public final int startActivities(IApplicationThread caller,
2396 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2397 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2398 }
2399
2400 public final int startActivitiesInPackage(int uid,
2401 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2402
2403 // This is so super not safe, that only the system (or okay root)
2404 // can do it.
2405 final int callingUid = Binder.getCallingUid();
2406 if (callingUid != 0 && callingUid != Process.myUid()) {
2407 throw new SecurityException(
2408 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002409 }
2410
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002411 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 }
2413
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002414 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002415 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002416 // Quick case: check if the top-most recent task is the same.
2417 if (N > 0 && mRecentTasks.get(0) == task) {
2418 return;
2419 }
2420 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002421 for (int i=0; i<N; i++) {
2422 TaskRecord tr = mRecentTasks.get(i);
2423 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2424 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2425 mRecentTasks.remove(i);
2426 i--;
2427 N--;
2428 if (task.intent == null) {
2429 // If the new recent task we are adding is not fully
2430 // specified, then replace it with the existing recent task.
2431 task = tr;
2432 }
2433 }
2434 }
2435 if (N >= MAX_RECENT_TASKS) {
2436 mRecentTasks.remove(N-1);
2437 }
2438 mRecentTasks.add(0, task);
2439 }
2440
2441 public void setRequestedOrientation(IBinder token,
2442 int requestedOrientation) {
2443 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002444 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 if (index < 0) {
2446 return;
2447 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002448 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002449 final long origId = Binder.clearCallingIdentity();
2450 mWindowManager.setAppOrientation(r, requestedOrientation);
2451 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002452 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002453 r.mayFreezeScreenLocked(r.app) ? r : null);
2454 if (config != null) {
2455 r.frozenBeforeDestroy = true;
2456 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002457 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458 }
2459 }
2460 Binder.restoreCallingIdentity(origId);
2461 }
2462 }
2463
2464 public int getRequestedOrientation(IBinder token) {
2465 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002466 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 if (index < 0) {
2468 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2469 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002470 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471 return mWindowManager.getAppOrientation(r);
2472 }
2473 }
2474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002475 /**
2476 * This is the internal entry point for handling Activity.finish().
2477 *
2478 * @param token The Binder token referencing the Activity we want to finish.
2479 * @param resultCode Result code, if any, from this Activity.
2480 * @param resultData Result data (Intent), if any, from this Activity.
2481 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002482 * @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 -08002483 */
2484 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2485 // Refuse possible leaked file descriptors
2486 if (resultData != null && resultData.hasFileDescriptors() == true) {
2487 throw new IllegalArgumentException("File descriptors passed in Intent");
2488 }
2489
2490 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002491 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002493 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002494 if (next != null) {
2495 // ask watcher if this is allowed
2496 boolean resumeOK = true;
2497 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002498 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002499 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002500 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 }
2502
2503 if (!resumeOK) {
2504 return false;
2505 }
2506 }
2507 }
2508 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002509 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 resultData, "app-request");
2511 Binder.restoreCallingIdentity(origId);
2512 return res;
2513 }
2514 }
2515
Dianne Hackborn860755f2010-06-03 18:47:52 -07002516 public final void finishHeavyWeightApp() {
2517 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2518 != PackageManager.PERMISSION_GRANTED) {
2519 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2520 + Binder.getCallingPid()
2521 + ", uid=" + Binder.getCallingUid()
2522 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2523 Slog.w(TAG, msg);
2524 throw new SecurityException(msg);
2525 }
2526
2527 synchronized(this) {
2528 if (mHeavyWeightProcess == null) {
2529 return;
2530 }
2531
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002532 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002533 mHeavyWeightProcess.activities);
2534 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002535 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002536 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002537 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002538 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002539 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002540 null, "finish-heavy");
2541 }
2542 }
2543 }
2544
2545 mHeavyWeightProcess = null;
2546 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2547 }
2548 }
2549
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002550 public void crashApplication(int uid, int initialPid, String packageName,
2551 String message) {
2552 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2553 != PackageManager.PERMISSION_GRANTED) {
2554 String msg = "Permission Denial: crashApplication() from pid="
2555 + Binder.getCallingPid()
2556 + ", uid=" + Binder.getCallingUid()
2557 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2558 Slog.w(TAG, msg);
2559 throw new SecurityException(msg);
2560 }
2561
2562 synchronized(this) {
2563 ProcessRecord proc = null;
2564
2565 // Figure out which process to kill. We don't trust that initialPid
2566 // still has any relation to current pids, so must scan through the
2567 // list.
2568 synchronized (mPidsSelfLocked) {
2569 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2570 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2571 if (p.info.uid != uid) {
2572 continue;
2573 }
2574 if (p.pid == initialPid) {
2575 proc = p;
2576 break;
2577 }
2578 for (String str : p.pkgList) {
2579 if (str.equals(packageName)) {
2580 proc = p;
2581 }
2582 }
2583 }
2584 }
2585
2586 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002587 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002588 + " initialPid=" + initialPid
2589 + " packageName=" + packageName);
2590 return;
2591 }
2592
2593 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002594 if (proc.pid == Process.myPid()) {
2595 Log.w(TAG, "crashApplication: trying to crash self!");
2596 return;
2597 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002598 long ident = Binder.clearCallingIdentity();
2599 try {
2600 proc.thread.scheduleCrash(message);
2601 } catch (RemoteException e) {
2602 }
2603 Binder.restoreCallingIdentity(ident);
2604 }
2605 }
2606 }
2607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608 public final void finishSubActivity(IBinder token, String resultWho,
2609 int requestCode) {
2610 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002611 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002612 if (index < 0) {
2613 return;
2614 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002615 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616
2617 final long origId = Binder.clearCallingIdentity();
2618
2619 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002620 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2621 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 if (r.resultTo == self && r.requestCode == requestCode) {
2623 if ((r.resultWho == null && resultWho == null) ||
2624 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002625 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 Activity.RESULT_CANCELED, null, "request-sub");
2627 }
2628 }
2629 }
2630
2631 Binder.restoreCallingIdentity(origId);
2632 }
2633 }
2634
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002635 public boolean willActivityBeVisible(IBinder token) {
2636 synchronized(this) {
2637 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002638 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2639 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002640 if (r == token) {
2641 return true;
2642 }
2643 if (r.fullscreen && !r.finishing) {
2644 return false;
2645 }
2646 }
2647 return true;
2648 }
2649 }
2650
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002651 public void overridePendingTransition(IBinder token, String packageName,
2652 int enterAnim, int exitAnim) {
2653 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002654 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002655 if (index < 0) {
2656 return;
2657 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002658 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002659
2660 final long origId = Binder.clearCallingIdentity();
2661
2662 if (self.state == ActivityState.RESUMED
2663 || self.state == ActivityState.PAUSING) {
2664 mWindowManager.overridePendingAppTransition(packageName,
2665 enterAnim, exitAnim);
2666 }
2667
2668 Binder.restoreCallingIdentity(origId);
2669 }
2670 }
2671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002673 * Main function for removing an existing process from the activity manager
2674 * as a result of that process going away. Clears out all connections
2675 * to the process.
2676 */
2677 private final void handleAppDiedLocked(ProcessRecord app,
2678 boolean restarting) {
2679 cleanUpApplicationRecordLocked(app, restarting, -1);
2680 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002681 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002682 }
2683
2684 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002685 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2686 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2687 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002688 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002689 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2690 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 }
2692
2693 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002694 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002695
2696 boolean atTop = true;
2697 boolean hasVisibleActivities = false;
2698
2699 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002700 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002701 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 TAG, "Removing app " + app + " from history with " + i + " entries");
2703 while (i > 0) {
2704 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002705 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002706 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002707 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2708 if (r.app == app) {
2709 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002710 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 TAG, "Removing this entry! frozen=" + r.haveState
2712 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002713 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002714 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002715 r.takeFromHistory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002716 mWindowManager.removeAppToken(r);
2717 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002718 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002720 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721
2722 } else {
2723 // We have the current state for this activity, so
2724 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002725 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 TAG, "Keeping entry, setting app to null");
2727 if (r.visible) {
2728 hasVisibleActivities = true;
2729 }
2730 r.app = null;
2731 r.nowVisible = false;
2732 if (!r.haveState) {
2733 r.icicle = null;
2734 }
2735 }
2736
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002737 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 r.state = ActivityState.STOPPED;
2739 }
2740 atTop = false;
2741 }
2742
2743 app.activities.clear();
2744
2745 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002746 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002747 + " running instrumentation " + app.instrumentationClass);
2748 Bundle info = new Bundle();
2749 info.putString("shortMsg", "Process crashed.");
2750 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2751 }
2752
2753 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002754 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 // If there was nothing to resume, and we are not already
2756 // restarting this process, but there is a visible activity that
2757 // is hosted by the process... then make sure all visible
2758 // activities are running, taking care of restarting this
2759 // process.
2760 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002761 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002762 }
2763 }
2764 }
2765 }
2766
2767 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2768 IBinder threadBinder = thread.asBinder();
2769
2770 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002771 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2772 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002773 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2774 return i;
2775 }
2776 }
2777 return -1;
2778 }
2779
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002780 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781 IApplicationThread thread) {
2782 if (thread == null) {
2783 return null;
2784 }
2785
2786 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002787 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002788 }
2789
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002790 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 IApplicationThread thread) {
2792
2793 mProcDeaths[0]++;
2794
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002795 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2796 synchronized (stats) {
2797 stats.noteProcessDiedLocked(app.info.uid, pid);
2798 }
2799
Magnus Edlund7bb25812010-02-24 15:45:06 +01002800 // Clean up already done if the process has been re-started.
2801 if (app.pid == pid && app.thread != null &&
2802 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002803 if (!app.killedBackground) {
2804 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2805 + ") has died.");
2806 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002807 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002808 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809 TAG, "Dying app: " + app + ", pid: " + pid
2810 + ", thread: " + thread.asBinder());
2811 boolean doLowMem = app.instrumentationClass == null;
2812 handleAppDiedLocked(app, false);
2813
2814 if (doLowMem) {
2815 // If there are no longer any background processes running,
2816 // and the app that died was not running instrumentation,
2817 // then tell everyone we are now low on memory.
2818 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002819 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2820 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002821 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2822 haveBg = true;
2823 break;
2824 }
2825 }
2826
2827 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002828 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002829 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002830 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002831 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2832 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002833 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002834 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2835 // The low memory report is overriding any current
2836 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002837 // heavy/important/visible/foreground processes first.
2838 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002839 rec.lastRequestedGc = 0;
2840 } else {
2841 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002842 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002843 rec.reportLowMemory = true;
2844 rec.lastLowMemory = now;
2845 mProcessesToGc.remove(rec);
2846 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002847 }
2848 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002849 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002850 }
2851 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002852 } else if (app.pid != pid) {
2853 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002854 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002855 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002856 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002857 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002858 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 + thread.asBinder());
2860 }
2861 }
2862
Dan Egnor42471dd2010-01-07 17:25:22 -08002863 /**
2864 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002865 * @param clearTraces causes the dump file to be erased prior to the new
2866 * traces being written, if true; when false, the new traces will be
2867 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002868 * @param firstPids of dalvik VM processes to dump stack traces for first
2869 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002870 * @return file containing stack traces, or null if no dump file is configured
2871 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002872 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2873 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002874 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2875 if (tracesPath == null || tracesPath.length() == 0) {
2876 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002877 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002878
2879 File tracesFile = new File(tracesPath);
2880 try {
2881 File tracesDir = tracesFile.getParentFile();
2882 if (!tracesDir.exists()) tracesFile.mkdirs();
2883 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2884
Christopher Tate6ee412d2010-05-28 12:01:56 -07002885 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002886 tracesFile.createNewFile();
2887 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2888 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002889 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002890 return null;
2891 }
2892
2893 // Use a FileObserver to detect when traces finish writing.
2894 // The order of traces is considered important to maintain for legibility.
2895 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2896 public synchronized void onEvent(int event, String path) { notify(); }
2897 };
2898
2899 try {
2900 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002901
2902 // First collect all of the stacks of the most important pids.
2903 try {
2904 int num = firstPids.size();
2905 for (int i = 0; i < num; i++) {
2906 synchronized (observer) {
2907 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2908 observer.wait(200); // Wait for write-close, give up after 200msec
2909 }
2910 }
2911 } catch (InterruptedException e) {
2912 Log.wtf(TAG, e);
2913 }
2914
2915 // Next measure CPU usage.
2916 if (processStats != null) {
2917 processStats.init();
2918 System.gc();
2919 processStats.update();
2920 try {
2921 synchronized (processStats) {
2922 processStats.wait(500); // measure over 1/2 second.
2923 }
2924 } catch (InterruptedException e) {
2925 }
2926 processStats.update();
2927
2928 // We'll take the stack crawls of just the top apps using CPU.
2929 final int N = processStats.countWorkingStats();
2930 int numProcs = 0;
2931 for (int i=0; i<N && numProcs<5; i++) {
2932 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2933 if (lastPids.indexOfKey(stats.pid) >= 0) {
2934 numProcs++;
2935 try {
2936 synchronized (observer) {
2937 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2938 observer.wait(200); // Wait for write-close, give up after 200msec
2939 }
2940 } catch (InterruptedException e) {
2941 Log.wtf(TAG, e);
2942 }
2943
2944 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002945 }
2946 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002947
2948 return tracesFile;
2949
Dan Egnor42471dd2010-01-07 17:25:22 -08002950 } finally {
2951 observer.stopWatching();
2952 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 }
2954
Jeff Brown4d94a762010-09-23 11:33:28 -07002955 private final class AppNotResponding implements Runnable {
2956 private final ProcessRecord mApp;
2957 private final String mAnnotation;
2958
2959 public AppNotResponding(ProcessRecord app, String annotation) {
2960 mApp = app;
2961 mAnnotation = annotation;
2962 }
2963
2964 @Override
2965 public void run() {
2966 appNotResponding(mApp, null, null, mAnnotation);
2967 }
2968 }
2969
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002970 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2971 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002972 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2973 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2974
Dianne Hackborn287952c2010-09-22 22:34:31 -07002975 if (mController != null) {
2976 try {
2977 // 0 == continue, -1 = kill process immediately
2978 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2979 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2980 } catch (RemoteException e) {
2981 mController = null;
2982 }
2983 }
2984
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002985 long anrTime = SystemClock.uptimeMillis();
2986 if (MONITOR_CPU_USAGE) {
2987 updateCpuStatsNow();
2988 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002989
2990 synchronized (this) {
2991 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2992 if (mShuttingDown) {
2993 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2994 return;
2995 } else if (app.notResponding) {
2996 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2997 return;
2998 } else if (app.crashing) {
2999 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
3000 return;
3001 }
3002
3003 // In case we come through here for the same app before completing
3004 // this one, mark as anring now so we will bail out.
3005 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08003006
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003007 // Log the ANR to the event log.
3008 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
3009 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08003010
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003011 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003012 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003013
3014 int parentPid = app.pid;
3015 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003016 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003017
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003018 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08003019
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003020 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
3021 ProcessRecord r = mLruProcesses.get(i);
3022 if (r != null && r.thread != null) {
3023 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003024 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
3025 if (r.persistent) {
3026 firstPids.add(pid);
3027 } else {
3028 lastPids.put(pid, Boolean.TRUE);
3029 }
3030 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003032 }
3033 }
3034
Dan Egnor42471dd2010-01-07 17:25:22 -08003035 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003036 StringBuilder info = mStringBuilder;
3037 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08003038 info.append("ANR in ").append(app.processName);
3039 if (activity != null && activity.shortComponentName != null) {
3040 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07003041 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08003042 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003044 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003046 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003047 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049
Dianne Hackborn287952c2010-09-22 22:34:31 -07003050 final ProcessStats processStats = new ProcessStats(true);
3051
3052 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
3053
Dan Egnor42471dd2010-01-07 17:25:22 -08003054 String cpuInfo = null;
3055 if (MONITOR_CPU_USAGE) {
3056 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003057 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003058 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003059 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003060 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08003061 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 }
3063
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003064 info.append(processStats.printCurrentState(anrTime));
3065
Joe Onorato8a9b2202010-02-26 18:56:32 -08003066 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08003067 if (tracesFile == null) {
3068 // There is no trace file, so dump (only) the alleged culprit's threads to the log
3069 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
3070 }
3071
3072 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
3073
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003074 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08003076 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
3077 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003079 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3080 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 }
3082 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003083 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003084 }
3085 }
3086
Dan Egnor42471dd2010-01-07 17:25:22 -08003087 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
3088 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
3089 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003090
3091 synchronized (this) {
3092 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003093 Slog.w(TAG, "Killing " + app + ": background ANR");
3094 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
3095 app.processName, app.setAdj, "background ANR");
3096 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003097 return;
3098 }
3099
3100 // Set the app's notResponding state, and look up the errorReportReceiver
3101 makeAppNotRespondingLocked(app,
3102 activity != null ? activity.shortComponentName : null,
3103 annotation != null ? "ANR " + annotation : "ANR",
3104 info.toString());
3105
3106 // Bring up the infamous App Not Responding dialog
3107 Message msg = Message.obtain();
3108 HashMap map = new HashMap();
3109 msg.what = SHOW_NOT_RESPONDING_MSG;
3110 msg.obj = map;
3111 map.put("app", app);
3112 if (activity != null) {
3113 map.put("activity", activity);
3114 }
3115
3116 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003117 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003118 }
3119
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003120 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3121 if (!mLaunchWarningShown) {
3122 mLaunchWarningShown = true;
3123 mHandler.post(new Runnable() {
3124 @Override
3125 public void run() {
3126 synchronized (ActivityManagerService.this) {
3127 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3128 d.show();
3129 mHandler.postDelayed(new Runnable() {
3130 @Override
3131 public void run() {
3132 synchronized (ActivityManagerService.this) {
3133 d.dismiss();
3134 mLaunchWarningShown = false;
3135 }
3136 }
3137 }, 4000);
3138 }
3139 }
3140 });
3141 }
3142 }
3143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144 public boolean clearApplicationUserData(final String packageName,
3145 final IPackageDataObserver observer) {
3146 int uid = Binder.getCallingUid();
3147 int pid = Binder.getCallingPid();
3148 long callingId = Binder.clearCallingIdentity();
3149 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003150 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003151 int pkgUid = -1;
3152 synchronized(this) {
3153 try {
3154 pkgUid = pm.getPackageUid(packageName);
3155 } catch (RemoteException e) {
3156 }
3157 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003158 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 return false;
3160 }
3161 if (uid == pkgUid || checkComponentPermission(
3162 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003163 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003164 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003165 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 } else {
3167 throw new SecurityException(pid+" does not have permission:"+
3168 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3169 "for process:"+packageName);
3170 }
3171 }
3172
3173 try {
3174 //clear application user data
3175 pm.clearApplicationUserData(packageName, observer);
3176 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3177 Uri.fromParts("package", packageName, null));
3178 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003179 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3180 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003181 } catch (RemoteException e) {
3182 }
3183 } finally {
3184 Binder.restoreCallingIdentity(callingId);
3185 }
3186 return true;
3187 }
3188
Dianne Hackborn03abb812010-01-04 18:43:19 -08003189 public void killBackgroundProcesses(final String packageName) {
3190 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3191 != PackageManager.PERMISSION_GRANTED &&
3192 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3193 != PackageManager.PERMISSION_GRANTED) {
3194 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 + Binder.getCallingPid()
3196 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003197 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003198 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199 throw new SecurityException(msg);
3200 }
3201
3202 long callingId = Binder.clearCallingIdentity();
3203 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003204 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 int pkgUid = -1;
3206 synchronized(this) {
3207 try {
3208 pkgUid = pm.getPackageUid(packageName);
3209 } catch (RemoteException e) {
3210 }
3211 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003212 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 return;
3214 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003215 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003216 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003217 }
3218 } finally {
3219 Binder.restoreCallingIdentity(callingId);
3220 }
3221 }
3222
3223 public void forceStopPackage(final String packageName) {
3224 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3225 != PackageManager.PERMISSION_GRANTED) {
3226 String msg = "Permission Denial: forceStopPackage() from pid="
3227 + Binder.getCallingPid()
3228 + ", uid=" + Binder.getCallingUid()
3229 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003230 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003231 throw new SecurityException(msg);
3232 }
3233
3234 long callingId = Binder.clearCallingIdentity();
3235 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003236 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003237 int pkgUid = -1;
3238 synchronized(this) {
3239 try {
3240 pkgUid = pm.getPackageUid(packageName);
3241 } catch (RemoteException e) {
3242 }
3243 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003244 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003245 return;
3246 }
3247 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003248 try {
3249 pm.setPackageStoppedState(packageName, true);
3250 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003251 } catch (IllegalArgumentException e) {
3252 Slog.w(TAG, "Failed trying to unstop package "
3253 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 }
3256 } finally {
3257 Binder.restoreCallingIdentity(callingId);
3258 }
3259 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003260
3261 /*
3262 * The pkg name and uid have to be specified.
3263 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3264 */
3265 public void killApplicationWithUid(String pkg, int uid) {
3266 if (pkg == null) {
3267 return;
3268 }
3269 // Make sure the uid is valid.
3270 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003271 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003272 return;
3273 }
3274 int callerUid = Binder.getCallingUid();
3275 // Only the system server can kill an application
3276 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003277 // Post an aysnc message to kill the application
3278 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3279 msg.arg1 = uid;
3280 msg.arg2 = 0;
3281 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003282 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003283 } else {
3284 throw new SecurityException(callerUid + " cannot kill pkg: " +
3285 pkg);
3286 }
3287 }
3288
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003289 public void closeSystemDialogs(String reason) {
3290 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003291 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003292 if (reason != null) {
3293 intent.putExtra("reason", reason);
3294 }
3295
3296 final int uid = Binder.getCallingUid();
3297 final long origId = Binder.clearCallingIdentity();
3298 synchronized (this) {
3299 int i = mWatchers.beginBroadcast();
3300 while (i > 0) {
3301 i--;
3302 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3303 if (w != null) {
3304 try {
3305 w.closingSystemDialogs(reason);
3306 } catch (RemoteException e) {
3307 }
3308 }
3309 }
3310 mWatchers.finishBroadcast();
3311
Dianne Hackbornffa42482009-09-23 22:20:11 -07003312 mWindowManager.closeSystemDialogs(reason);
3313
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003314 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3315 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003316 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003317 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003318 Activity.RESULT_CANCELED, null, "close-sys");
3319 }
3320 }
3321
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003322 broadcastIntentLocked(null, null, intent, null,
3323 null, 0, null, null, null, false, false, -1, uid);
3324 }
3325 Binder.restoreCallingIdentity(origId);
3326 }
3327
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003328 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003329 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003330 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3331 for (int i=pids.length-1; i>=0; i--) {
3332 infos[i] = new Debug.MemoryInfo();
3333 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003334 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003335 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003336 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003337
3338 public void killApplicationProcess(String processName, int uid) {
3339 if (processName == null) {
3340 return;
3341 }
3342
3343 int callerUid = Binder.getCallingUid();
3344 // Only the system server can kill an application
3345 if (callerUid == Process.SYSTEM_UID) {
3346 synchronized (this) {
3347 ProcessRecord app = getProcessRecordLocked(processName, uid);
Christopher Tate4a627c72011-04-01 14:43:32 -07003348 if (app != null && app.thread != null) {
Christopher Tate5e1ab332009-09-01 20:32:49 -07003349 try {
3350 app.thread.scheduleSuicide();
3351 } catch (RemoteException e) {
3352 // If the other end already died, then our work here is done.
3353 }
3354 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003355 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003356 + processName + " / " + uid);
3357 }
3358 }
3359 } else {
3360 throw new SecurityException(callerUid + " cannot kill app process: " +
3361 processName);
3362 }
3363 }
3364
Dianne Hackborn03abb812010-01-04 18:43:19 -08003365 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003366 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3368 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003369 if (!mProcessesReady) {
3370 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 intent.putExtra(Intent.EXTRA_UID, uid);
3373 broadcastIntentLocked(null, null, intent,
3374 null, null, 0, null, null, null,
3375 false, false, MY_PID, Process.SYSTEM_UID);
3376 }
3377
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003378 private final boolean killPackageProcessesLocked(String packageName, int uid,
3379 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003380 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003381
Dianne Hackborn03abb812010-01-04 18:43:19 -08003382 // Remove all processes this package may have touched: all with the
3383 // same UID (except for the system or root user), and all whose name
3384 // matches the package name.
3385 final String procNamePrefix = packageName + ":";
3386 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3387 final int NA = apps.size();
3388 for (int ia=0; ia<NA; ia++) {
3389 ProcessRecord app = apps.valueAt(ia);
3390 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003391 if (doit) {
3392 procs.add(app);
3393 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003394 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3395 || app.processName.equals(packageName)
3396 || app.processName.startsWith(procNamePrefix)) {
3397 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003398 if (!doit) {
3399 return true;
3400 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003401 app.removed = true;
3402 procs.add(app);
3403 }
3404 }
3405 }
3406 }
3407
3408 int N = procs.size();
3409 for (int i=0; i<N; i++) {
3410 removeProcessLocked(procs.get(i), callerWillRestart);
3411 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003412 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003413 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003414
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003415 private final boolean forceStopPackageLocked(String name, int uid,
3416 boolean callerWillRestart, boolean purgeCache, boolean doit) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07003417 int i;
3418 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420 if (uid < 0) {
3421 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003422 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003423 } catch (RemoteException e) {
3424 }
3425 }
3426
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003427 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003428 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003429
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003430 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3431 while (badApps.hasNext()) {
3432 SparseArray<Long> ba = badApps.next();
3433 if (ba.get(uid) != null) {
3434 badApps.remove();
3435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003436 }
3437 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003438
3439 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3440 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003442 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3443 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003445 if (!doit) {
3446 return true;
3447 }
3448 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003449 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 if (r.app != null) {
3451 r.app.removed = true;
3452 }
3453 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003454 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 }
3456 }
3457
3458 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3459 for (ServiceRecord service : mServices.values()) {
3460 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003461 if (!doit) {
3462 return true;
3463 }
3464 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003465 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003466 if (service.app != null) {
3467 service.app.removed = true;
3468 }
3469 service.app = null;
3470 services.add(service);
3471 }
3472 }
3473
3474 N = services.size();
3475 for (i=0; i<N; i++) {
3476 bringDownServiceLocked(services.get(i), true);
3477 }
3478
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003479 if (doit) {
3480 if (purgeCache) {
3481 AttributeCache ac = AttributeCache.instance();
3482 if (ac != null) {
3483 ac.removePackage(name);
3484 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003485 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003486 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003487 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003488
3489 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003490 }
3491
3492 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3493 final String name = app.processName;
3494 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003495 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 TAG, "Force removing process " + app + " (" + name
3497 + "/" + uid + ")");
3498
3499 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003500 if (mHeavyWeightProcess == app) {
3501 mHeavyWeightProcess = null;
3502 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3503 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 boolean needRestart = false;
3505 if (app.pid > 0 && app.pid != MY_PID) {
3506 int pid = app.pid;
3507 synchronized (mPidsSelfLocked) {
3508 mPidsSelfLocked.remove(pid);
3509 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3510 }
3511 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003512 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 Process.killProcess(pid);
3514
3515 if (app.persistent) {
3516 if (!callerWillRestart) {
3517 addAppLocked(app.info);
3518 } else {
3519 needRestart = true;
3520 }
3521 }
3522 } else {
3523 mRemovedProcesses.add(app);
3524 }
3525
3526 return needRestart;
3527 }
3528
3529 private final void processStartTimedOutLocked(ProcessRecord app) {
3530 final int pid = app.pid;
3531 boolean gone = false;
3532 synchronized (mPidsSelfLocked) {
3533 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3534 if (knownApp != null && knownApp.thread == null) {
3535 mPidsSelfLocked.remove(pid);
3536 gone = true;
3537 }
3538 }
3539
3540 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003541 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003542 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003543 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003544 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003545 if (mHeavyWeightProcess == app) {
3546 mHeavyWeightProcess = null;
3547 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3548 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003549 // Take care of any launching providers waiting for this process.
3550 checkAppInLaunchingProvidersLocked(app, true);
3551 // Take care of any services that are waiting for the process.
3552 for (int i=0; i<mPendingServices.size(); i++) {
3553 ServiceRecord sr = mPendingServices.get(i);
3554 if (app.info.uid == sr.appInfo.uid
3555 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003556 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003557 mPendingServices.remove(i);
3558 i--;
3559 bringDownServiceLocked(sr, true);
3560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003561 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003562 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
3563 app.processName, app.setAdj, "start timeout");
3564 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003565 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003566 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003567 try {
3568 IBackupManager bm = IBackupManager.Stub.asInterface(
3569 ServiceManager.getService(Context.BACKUP_SERVICE));
3570 bm.agentDisconnected(app.info.packageName);
3571 } catch (RemoteException e) {
3572 // Can't happen; the backup manager is local
3573 }
3574 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003575 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003576 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003577 mPendingBroadcast.state = BroadcastRecord.IDLE;
3578 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003579 mPendingBroadcast = null;
3580 scheduleBroadcastsLocked();
3581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003583 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003584 }
3585 }
3586
3587 private final boolean attachApplicationLocked(IApplicationThread thread,
3588 int pid) {
3589
3590 // Find the application record that is being attached... either via
3591 // the pid if we are running in multiple processes, or just pull the
3592 // next app record if we are emulating process with anonymous threads.
3593 ProcessRecord app;
3594 if (pid != MY_PID && pid >= 0) {
3595 synchronized (mPidsSelfLocked) {
3596 app = mPidsSelfLocked.get(pid);
3597 }
3598 } else if (mStartingProcesses.size() > 0) {
3599 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003600 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003601 } else {
3602 app = null;
3603 }
3604
3605 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003606 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003608 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003610 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 } else {
3612 try {
3613 thread.scheduleExit();
3614 } catch (Exception e) {
3615 // Ignore exceptions.
3616 }
3617 }
3618 return false;
3619 }
3620
3621 // If this application record is still attached to a previous
3622 // process, clean it up now.
3623 if (app.thread != null) {
3624 handleAppDiedLocked(app, true);
3625 }
3626
3627 // Tell the process all about itself.
3628
Joe Onorato8a9b2202010-02-26 18:56:32 -08003629 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 TAG, "Binding process pid " + pid + " to record " + app);
3631
3632 String processName = app.processName;
3633 try {
3634 thread.asBinder().linkToDeath(new AppDeathRecipient(
3635 app, pid, thread), 0);
3636 } catch (RemoteException e) {
3637 app.resetPackageList();
3638 startProcessLocked(app, "link fail", processName);
3639 return false;
3640 }
3641
Doug Zongker2bec3d42009-12-04 12:52:44 -08003642 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003643
3644 app.thread = thread;
3645 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003646 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3647 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003648 app.forcingToForeground = null;
3649 app.foregroundServices = false;
3650 app.debugging = false;
3651
3652 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3653
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003654 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003655 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003656
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003657 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003658 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003659 }
3660
Joe Onorato8a9b2202010-02-26 18:56:32 -08003661 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 TAG, "New app record " + app
3663 + " thread=" + thread.asBinder() + " pid=" + pid);
3664 try {
3665 int testMode = IApplicationThread.DEBUG_OFF;
3666 if (mDebugApp != null && mDebugApp.equals(processName)) {
3667 testMode = mWaitForDebugger
3668 ? IApplicationThread.DEBUG_WAIT
3669 : IApplicationThread.DEBUG_ON;
3670 app.debugging = true;
3671 if (mDebugTransient) {
3672 mDebugApp = mOrigDebugApp;
3673 mWaitForDebugger = mOrigWaitForDebugger;
3674 }
3675 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003676
Christopher Tate181fafa2009-05-14 11:12:14 -07003677 // If the app is being launched for restore or full backup, set it up specially
3678 boolean isRestrictedBackupMode = false;
3679 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3680 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07003681 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07003682 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3683 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003684
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003685 ensurePackageDexOpt(app.instrumentationInfo != null
3686 ? app.instrumentationInfo.packageName
3687 : app.info.packageName);
3688 if (app.instrumentationClass != null) {
3689 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003690 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003691 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003692 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003693 ApplicationInfo appInfo = app.instrumentationInfo != null
3694 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003695 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003696 thread.bindApplication(processName, appInfo, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 app.instrumentationClass, app.instrumentationProfileFile,
3698 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003699 isRestrictedBackupMode || !normalMode,
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003700 mConfiguration, app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003701 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003702 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003703 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003704 } catch (Exception e) {
3705 // todo: Yikes! What should we do? For now we will try to
3706 // start another process, but that could easily get us in
3707 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003708 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003709
3710 app.resetPackageList();
3711 startProcessLocked(app, "bind fail", processName);
3712 return false;
3713 }
3714
3715 // Remove this record from the list of starting applications.
3716 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003717 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3718 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003719 mProcessesOnHold.remove(app);
3720
3721 boolean badApp = false;
3722 boolean didSomething = false;
3723
3724 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003725 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003726 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003727 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3728 && processName.equals(hr.processName)) {
3729 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003730 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003731 didSomething = true;
3732 }
3733 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003734 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003735 + hr.intent.getComponent().flattenToShortString(), e);
3736 badApp = true;
3737 }
3738 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003739 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 }
3741 }
3742
3743 // Find any services that should be running in this process...
3744 if (!badApp && mPendingServices.size() > 0) {
3745 ServiceRecord sr = null;
3746 try {
3747 for (int i=0; i<mPendingServices.size(); i++) {
3748 sr = mPendingServices.get(i);
3749 if (app.info.uid != sr.appInfo.uid
3750 || !processName.equals(sr.processName)) {
3751 continue;
3752 }
3753
3754 mPendingServices.remove(i);
3755 i--;
3756 realStartServiceLocked(sr, app);
3757 didSomething = true;
3758 }
3759 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003760 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003761 + sr.shortName, e);
3762 badApp = true;
3763 }
3764 }
3765
3766 // Check if the next broadcast receiver is in this process...
3767 BroadcastRecord br = mPendingBroadcast;
3768 if (!badApp && br != null && br.curApp == app) {
3769 try {
3770 mPendingBroadcast = null;
3771 processCurBroadcastLocked(br, app);
3772 didSomething = true;
3773 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003774 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 + br.curComponent.flattenToShortString(), e);
3776 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003777 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3779 br.resultExtras, br.resultAbort, true);
3780 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003781 // We need to reset the state if we fails to start the receiver.
3782 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 }
3784 }
3785
Christopher Tate181fafa2009-05-14 11:12:14 -07003786 // Check whether the next backup agent is in this process...
3787 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003788 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003789 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003790 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003791 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
3792 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
3793 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07003794 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003795 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003796 e.printStackTrace();
3797 }
3798 }
3799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 if (badApp) {
3801 // todo: Also need to kill application to deal with all
3802 // kinds of exceptions.
3803 handleAppDiedLocked(app, false);
3804 return false;
3805 }
3806
3807 if (!didSomething) {
3808 updateOomAdjLocked();
3809 }
3810
3811 return true;
3812 }
3813
3814 public final void attachApplication(IApplicationThread thread) {
3815 synchronized (this) {
3816 int callingPid = Binder.getCallingPid();
3817 final long origId = Binder.clearCallingIdentity();
3818 attachApplicationLocked(thread, callingPid);
3819 Binder.restoreCallingIdentity(origId);
3820 }
3821 }
3822
Dianne Hackborne88846e2009-09-30 21:34:25 -07003823 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003825 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 Binder.restoreCallingIdentity(origId);
3827 }
3828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003829 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003830 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003831 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 mWindowManager.enableScreenAfterBoot();
3833 }
3834
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003835 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003836 IntentFilter pkgFilter = new IntentFilter();
3837 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3838 pkgFilter.addDataScheme("package");
3839 mContext.registerReceiver(new BroadcastReceiver() {
3840 @Override
3841 public void onReceive(Context context, Intent intent) {
3842 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3843 if (pkgs != null) {
3844 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003845 synchronized (ActivityManagerService.this) {
3846 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3847 setResultCode(Activity.RESULT_OK);
3848 return;
3849 }
3850 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003851 }
3852 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003853 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003854 }, pkgFilter);
3855
3856 synchronized (this) {
3857 // Ensure that any processes we had put on hold are now started
3858 // up.
3859 final int NP = mProcessesOnHold.size();
3860 if (NP > 0) {
3861 ArrayList<ProcessRecord> procs =
3862 new ArrayList<ProcessRecord>(mProcessesOnHold);
3863 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003864 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3865 + procs.get(ip));
3866 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003867 }
3868 }
3869
3870 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003871 // Start looking for apps that are abusing wake locks.
3872 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003873 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003874 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003875 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003876 broadcastIntentLocked(null, null,
3877 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3878 null, null, 0, null, null,
3879 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3880 false, false, MY_PID, Process.SYSTEM_UID);
3881 }
3882 }
3883 }
3884
3885 final void ensureBootCompleted() {
3886 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003887 boolean enableScreen;
3888 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003889 booting = mBooting;
3890 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003891 enableScreen = !mBooted;
3892 mBooted = true;
3893 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003894
3895 if (booting) {
3896 finishBooting();
3897 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003898
3899 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003900 enableScreenAfterBoot();
3901 }
3902 }
3903
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003904 public final void activityPaused(IBinder token) {
3905 final long origId = Binder.clearCallingIdentity();
3906 mMainStack.activityPaused(token, false);
3907 Binder.restoreCallingIdentity(origId);
3908 }
3909
3910 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3911 CharSequence description) {
3912 if (localLOGV) Slog.v(
3913 TAG, "Activity stopped: token=" + token);
3914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003915 // Refuse possible leaked file descriptors
3916 if (icicle != null && icicle.hasFileDescriptors()) {
3917 throw new IllegalArgumentException("File descriptors passed in Bundle");
3918 }
3919
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003920 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003921
3922 final long origId = Binder.clearCallingIdentity();
3923
3924 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003925 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003927 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003928 r.icicle = icicle;
3929 r.haveState = true;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003930 r.updateThumbnail(thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003931 r.stopped = true;
3932 r.state = ActivityState.STOPPED;
3933 if (!r.finishing) {
3934 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003935 r.stack.destroyActivityLocked(r, true);
3936 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 }
3938 }
3939 }
3940 }
3941
3942 if (r != null) {
3943 sendPendingThumbnail(r, null, null, null, false);
3944 }
3945
3946 trimApplications();
3947
3948 Binder.restoreCallingIdentity(origId);
3949 }
3950
3951 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003952 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003953 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003954 }
3955
3956 public String getCallingPackage(IBinder token) {
3957 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003958 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003959 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 }
3961 }
3962
3963 public ComponentName getCallingActivity(IBinder token) {
3964 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003965 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 return r != null ? r.intent.getComponent() : null;
3967 }
3968 }
3969
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003970 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003971 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003973 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003974 if (r != null) {
3975 return r.resultTo;
3976 }
3977 }
3978 return null;
3979 }
3980
3981 public ComponentName getActivityClassForToken(IBinder token) {
3982 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003983 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003984 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003985 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003986 return r.intent.getComponent();
3987 }
3988 return null;
3989 }
3990 }
3991
3992 public String getPackageForToken(IBinder token) {
3993 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003994 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003996 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003997 return r.packageName;
3998 }
3999 return null;
4000 }
4001 }
4002
4003 public IIntentSender getIntentSender(int type,
4004 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004005 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004006 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004007 if (intents != null) {
4008 if (intents.length < 1) {
4009 throw new IllegalArgumentException("Intents array length must be >= 1");
4010 }
4011 for (int i=0; i<intents.length; i++) {
4012 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07004013 if (intent != null) {
4014 if (intent.hasFileDescriptors()) {
4015 throw new IllegalArgumentException("File descriptors passed in Intent");
4016 }
4017 if (type == INTENT_SENDER_BROADCAST &&
4018 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
4019 throw new IllegalArgumentException(
4020 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
4021 }
4022 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004023 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004024 }
4025 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004026 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004027 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004028 }
4029 }
4030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004031 synchronized(this) {
4032 int callingUid = Binder.getCallingUid();
4033 try {
4034 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
4035 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004036 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004037 .getPackageUid(packageName);
4038 if (uid != Binder.getCallingUid()) {
4039 String msg = "Permission Denial: getIntentSender() from pid="
4040 + Binder.getCallingPid()
4041 + ", uid=" + Binder.getCallingUid()
4042 + ", (need uid=" + uid + ")"
4043 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004044 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004045 throw new SecurityException(msg);
4046 }
4047 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004048
4049 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004050 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004052 } catch (RemoteException e) {
4053 throw new SecurityException(e);
4054 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004055 }
4056 }
4057
4058 IIntentSender getIntentSenderLocked(int type,
4059 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004060 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004061 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004062 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004063 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004064 if (index < 0) {
4065 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004066 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004067 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004068 if (activity.finishing) {
4069 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004070 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004071 }
4072
4073 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4074 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4075 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4076 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4077 |PendingIntent.FLAG_UPDATE_CURRENT);
4078
4079 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4080 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004081 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004082 WeakReference<PendingIntentRecord> ref;
4083 ref = mIntentSenderRecords.get(key);
4084 PendingIntentRecord rec = ref != null ? ref.get() : null;
4085 if (rec != null) {
4086 if (!cancelCurrent) {
4087 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004088 if (rec.key.requestIntent != null) {
4089 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4090 }
4091 if (intents != null) {
4092 intents[intents.length-1] = rec.key.requestIntent;
4093 rec.key.allIntents = intents;
4094 rec.key.allResolvedTypes = resolvedTypes;
4095 } else {
4096 rec.key.allIntents = null;
4097 rec.key.allResolvedTypes = null;
4098 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004100 return rec;
4101 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004102 rec.canceled = true;
4103 mIntentSenderRecords.remove(key);
4104 }
4105 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 return rec;
4107 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004108 rec = new PendingIntentRecord(this, key, callingUid);
4109 mIntentSenderRecords.put(key, rec.ref);
4110 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4111 if (activity.pendingResults == null) {
4112 activity.pendingResults
4113 = new HashSet<WeakReference<PendingIntentRecord>>();
4114 }
4115 activity.pendingResults.add(rec.ref);
4116 }
4117 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004118 }
4119
4120 public void cancelIntentSender(IIntentSender sender) {
4121 if (!(sender instanceof PendingIntentRecord)) {
4122 return;
4123 }
4124 synchronized(this) {
4125 PendingIntentRecord rec = (PendingIntentRecord)sender;
4126 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004127 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 .getPackageUid(rec.key.packageName);
4129 if (uid != Binder.getCallingUid()) {
4130 String msg = "Permission Denial: cancelIntentSender() from pid="
4131 + Binder.getCallingPid()
4132 + ", uid=" + Binder.getCallingUid()
4133 + " is not allowed to cancel packges "
4134 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004135 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004136 throw new SecurityException(msg);
4137 }
4138 } catch (RemoteException e) {
4139 throw new SecurityException(e);
4140 }
4141 cancelIntentSenderLocked(rec, true);
4142 }
4143 }
4144
4145 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4146 rec.canceled = true;
4147 mIntentSenderRecords.remove(rec.key);
4148 if (cleanActivity && rec.key.activity != null) {
4149 rec.key.activity.pendingResults.remove(rec.ref);
4150 }
4151 }
4152
4153 public String getPackageForIntentSender(IIntentSender pendingResult) {
4154 if (!(pendingResult instanceof PendingIntentRecord)) {
4155 return null;
4156 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004157 try {
4158 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4159 return res.key.packageName;
4160 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 }
4162 return null;
4163 }
4164
4165 public void setProcessLimit(int max) {
4166 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4167 "setProcessLimit()");
4168 mProcessLimit = max;
4169 }
4170
4171 public int getProcessLimit() {
4172 return mProcessLimit;
4173 }
4174
4175 void foregroundTokenDied(ForegroundToken token) {
4176 synchronized (ActivityManagerService.this) {
4177 synchronized (mPidsSelfLocked) {
4178 ForegroundToken cur
4179 = mForegroundProcesses.get(token.pid);
4180 if (cur != token) {
4181 return;
4182 }
4183 mForegroundProcesses.remove(token.pid);
4184 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4185 if (pr == null) {
4186 return;
4187 }
4188 pr.forcingToForeground = null;
4189 pr.foregroundServices = false;
4190 }
4191 updateOomAdjLocked();
4192 }
4193 }
4194
4195 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4196 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4197 "setProcessForeground()");
4198 synchronized(this) {
4199 boolean changed = false;
4200
4201 synchronized (mPidsSelfLocked) {
4202 ProcessRecord pr = mPidsSelfLocked.get(pid);
4203 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004204 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 return;
4206 }
4207 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4208 if (oldToken != null) {
4209 oldToken.token.unlinkToDeath(oldToken, 0);
4210 mForegroundProcesses.remove(pid);
4211 pr.forcingToForeground = null;
4212 changed = true;
4213 }
4214 if (isForeground && token != null) {
4215 ForegroundToken newToken = new ForegroundToken() {
4216 public void binderDied() {
4217 foregroundTokenDied(this);
4218 }
4219 };
4220 newToken.pid = pid;
4221 newToken.token = token;
4222 try {
4223 token.linkToDeath(newToken, 0);
4224 mForegroundProcesses.put(pid, newToken);
4225 pr.forcingToForeground = token;
4226 changed = true;
4227 } catch (RemoteException e) {
4228 // If the process died while doing this, we will later
4229 // do the cleanup with the process death link.
4230 }
4231 }
4232 }
4233
4234 if (changed) {
4235 updateOomAdjLocked();
4236 }
4237 }
4238 }
4239
4240 // =========================================================
4241 // PERMISSIONS
4242 // =========================================================
4243
4244 static class PermissionController extends IPermissionController.Stub {
4245 ActivityManagerService mActivityManagerService;
4246 PermissionController(ActivityManagerService activityManagerService) {
4247 mActivityManagerService = activityManagerService;
4248 }
4249
4250 public boolean checkPermission(String permission, int pid, int uid) {
4251 return mActivityManagerService.checkPermission(permission, pid,
4252 uid) == PackageManager.PERMISSION_GRANTED;
4253 }
4254 }
4255
4256 /**
4257 * This can be called with or without the global lock held.
4258 */
4259 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004260 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004261 // We might be performing an operation on behalf of an indirect binder
4262 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4263 // client identity accordingly before proceeding.
4264 Identity tlsIdentity = sCallerIdentity.get();
4265 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004266 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4268 uid = tlsIdentity.uid;
4269 pid = tlsIdentity.pid;
4270 }
4271
4272 // Root, system server and our own process get to do everything.
4273 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4274 !Process.supportsProcesses()) {
4275 return PackageManager.PERMISSION_GRANTED;
4276 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004277 // If there is a uid that owns whatever is being accessed, it has
4278 // blanket access to it regardless of the permissions it requires.
4279 if (owningUid >= 0 && uid == owningUid) {
4280 return PackageManager.PERMISSION_GRANTED;
4281 }
4282 // If the target is not exported, then nobody else can get to it.
4283 if (!exported) {
4284 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004285 return PackageManager.PERMISSION_DENIED;
4286 }
4287 if (permission == null) {
4288 return PackageManager.PERMISSION_GRANTED;
4289 }
4290 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004291 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 .checkUidPermission(permission, uid);
4293 } catch (RemoteException e) {
4294 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004295 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004296 }
4297 return PackageManager.PERMISSION_DENIED;
4298 }
4299
4300 /**
4301 * As the only public entry point for permissions checking, this method
4302 * can enforce the semantic that requesting a check on a null global
4303 * permission is automatically denied. (Internally a null permission
4304 * string is used when calling {@link #checkComponentPermission} in cases
4305 * when only uid-based security is needed.)
4306 *
4307 * This can be called with or without the global lock held.
4308 */
4309 public int checkPermission(String permission, int pid, int uid) {
4310 if (permission == null) {
4311 return PackageManager.PERMISSION_DENIED;
4312 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004313 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004314 }
4315
4316 /**
4317 * Binder IPC calls go through the public entry point.
4318 * This can be called with or without the global lock held.
4319 */
4320 int checkCallingPermission(String permission) {
4321 return checkPermission(permission,
4322 Binder.getCallingPid(),
4323 Binder.getCallingUid());
4324 }
4325
4326 /**
4327 * This can be called with or without the global lock held.
4328 */
4329 void enforceCallingPermission(String permission, String func) {
4330 if (checkCallingPermission(permission)
4331 == PackageManager.PERMISSION_GRANTED) {
4332 return;
4333 }
4334
4335 String msg = "Permission Denial: " + func + " from pid="
4336 + Binder.getCallingPid()
4337 + ", uid=" + Binder.getCallingUid()
4338 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004339 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 throw new SecurityException(msg);
4341 }
4342
4343 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004344 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4345 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4346 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4347 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4348 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004350 // Is the component private from the target uid?
4351 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4352
4353 // Acceptable if the there is no read permission needed from the
4354 // target or the target is holding the read permission.
4355 if (!readPerm) {
4356 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004358 == PackageManager.PERMISSION_GRANTED)) {
4359 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 }
4361 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004362
4363 // Acceptable if the there is no write permission needed from the
4364 // target or the target is holding the read permission.
4365 if (!writePerm) {
4366 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004368 == PackageManager.PERMISSION_GRANTED)) {
4369 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004370 }
4371 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004372
4373 // Acceptable if there is a path permission matching the URI that
4374 // the target holds the permission on.
4375 PathPermission[] pps = pi.pathPermissions;
4376 if (pps != null && (!readPerm || !writePerm)) {
4377 final String path = uri.getPath();
4378 int i = pps.length;
4379 while (i > 0 && (!readPerm || !writePerm)) {
4380 i--;
4381 PathPermission pp = pps[i];
4382 if (!readPerm) {
4383 final String pprperm = pp.getReadPermission();
4384 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4385 + pprperm + " for " + pp.getPath()
4386 + ": match=" + pp.match(path)
4387 + " check=" + pm.checkUidPermission(pprperm, uid));
4388 if (pprperm != null && pp.match(path) &&
4389 (pm.checkUidPermission(pprperm, uid)
4390 == PackageManager.PERMISSION_GRANTED)) {
4391 readPerm = true;
4392 }
4393 }
4394 if (!writePerm) {
4395 final String ppwperm = pp.getWritePermission();
4396 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4397 + ppwperm + " for " + pp.getPath()
4398 + ": match=" + pp.match(path)
4399 + " check=" + pm.checkUidPermission(ppwperm, uid));
4400 if (ppwperm != null && pp.match(path) &&
4401 (pm.checkUidPermission(ppwperm, uid)
4402 == PackageManager.PERMISSION_GRANTED)) {
4403 writePerm = true;
4404 }
4405 }
4406 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004408 } catch (RemoteException e) {
4409 return false;
4410 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004411
4412 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 }
4414
4415 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4416 int modeFlags) {
4417 // Root gets to do everything.
4418 if (uid == 0 || !Process.supportsProcesses()) {
4419 return true;
4420 }
4421 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4422 if (perms == null) return false;
4423 UriPermission perm = perms.get(uri);
4424 if (perm == null) return false;
4425 return (modeFlags&perm.modeFlags) == modeFlags;
4426 }
4427
4428 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4429 // Another redirected-binder-call permissions check as in
4430 // {@link checkComponentPermission}.
4431 Identity tlsIdentity = sCallerIdentity.get();
4432 if (tlsIdentity != null) {
4433 uid = tlsIdentity.uid;
4434 pid = tlsIdentity.pid;
4435 }
4436
4437 // Our own process gets to do everything.
4438 if (pid == MY_PID) {
4439 return PackageManager.PERMISSION_GRANTED;
4440 }
4441 synchronized(this) {
4442 return checkUriPermissionLocked(uri, uid, modeFlags)
4443 ? PackageManager.PERMISSION_GRANTED
4444 : PackageManager.PERMISSION_DENIED;
4445 }
4446 }
4447
Dianne Hackborn39792d22010-08-19 18:01:52 -07004448 /**
4449 * Check if the targetPkg can be granted permission to access uri by
4450 * the callingUid using the given modeFlags. Throws a security exception
4451 * if callingUid is not allowed to do this. Returns the uid of the target
4452 * if the URI permission grant should be performed; returns -1 if it is not
4453 * needed (for example targetPkg already has permission to access the URI).
4454 */
4455 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4456 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4458 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4459 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004460 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 }
4462
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004463 if (targetPkg != null) {
4464 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4465 "Checking grant " + targetPkg + " permission to " + uri);
4466 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004467
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004468 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004469
4470 // If this is not a content: uri, we can't do anything with it.
4471 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004472 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004473 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004474 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004475 }
4476
4477 String name = uri.getAuthority();
4478 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004479 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480 if (cpr != null) {
4481 pi = cpr.info;
4482 } else {
4483 try {
4484 pi = pm.resolveContentProvider(name,
4485 PackageManager.GET_URI_PERMISSION_PATTERNS);
4486 } catch (RemoteException ex) {
4487 }
4488 }
4489 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004490 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004491 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004492 }
4493
4494 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004495 if (targetPkg != null) {
4496 try {
4497 targetUid = pm.getPackageUid(targetPkg);
4498 if (targetUid < 0) {
4499 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4500 "Can't grant URI permission no uid for: " + targetPkg);
4501 return -1;
4502 }
4503 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004504 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004506 } else {
4507 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 }
4509
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004510 if (targetUid >= 0) {
4511 // First... does the target actually need this permission?
4512 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4513 // No need to grant the target this permission.
4514 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4515 "Target " + targetPkg + " already has full permission to " + uri);
4516 return -1;
4517 }
4518 } else {
4519 // First... there is no target package, so can anyone access it?
4520 boolean allowed = pi.exported;
4521 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4522 if (pi.readPermission != null) {
4523 allowed = false;
4524 }
4525 }
4526 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4527 if (pi.writePermission != null) {
4528 allowed = false;
4529 }
4530 }
4531 if (allowed) {
4532 return -1;
4533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 }
4535
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004536 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004537 if (!pi.grantUriPermissions) {
4538 throw new SecurityException("Provider " + pi.packageName
4539 + "/" + pi.name
4540 + " does not allow granting of Uri permissions (uri "
4541 + uri + ")");
4542 }
4543 if (pi.uriPermissionPatterns != null) {
4544 final int N = pi.uriPermissionPatterns.length;
4545 boolean allowed = false;
4546 for (int i=0; i<N; i++) {
4547 if (pi.uriPermissionPatterns[i] != null
4548 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4549 allowed = true;
4550 break;
4551 }
4552 }
4553 if (!allowed) {
4554 throw new SecurityException("Provider " + pi.packageName
4555 + "/" + pi.name
4556 + " does not allow granting of permission to path of Uri "
4557 + uri);
4558 }
4559 }
4560
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004561 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004562 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004563 if (callingUid != Process.myUid()) {
4564 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4565 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4566 throw new SecurityException("Uid " + callingUid
4567 + " does not have permission to uri " + uri);
4568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004569 }
4570 }
4571
Dianne Hackborn39792d22010-08-19 18:01:52 -07004572 return targetUid;
4573 }
4574
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004575 public int checkGrantUriPermission(int callingUid, String targetPkg,
4576 Uri uri, int modeFlags) {
4577 synchronized(this) {
4578 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4579 }
4580 }
4581
Dianne Hackborn39792d22010-08-19 18:01:52 -07004582 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4583 Uri uri, int modeFlags, UriPermissionOwner owner) {
4584 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4585 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4586 if (modeFlags == 0) {
4587 return;
4588 }
4589
4590 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004591 // to the uri, and the target doesn't. Let's now give this to
4592 // the target.
4593
Joe Onorato8a9b2202010-02-26 18:56:32 -08004594 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004595 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 HashMap<Uri, UriPermission> targetUris
4598 = mGrantedUriPermissions.get(targetUid);
4599 if (targetUris == null) {
4600 targetUris = new HashMap<Uri, UriPermission>();
4601 mGrantedUriPermissions.put(targetUid, targetUris);
4602 }
4603
4604 UriPermission perm = targetUris.get(uri);
4605 if (perm == null) {
4606 perm = new UriPermission(targetUid, uri);
4607 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004611 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004612 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004613 } else {
4614 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4615 perm.readOwners.add(owner);
4616 owner.addReadPermission(perm);
4617 }
4618 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4619 perm.writeOwners.add(owner);
4620 owner.addWritePermission(perm);
4621 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004622 }
4623 }
4624
Dianne Hackborn39792d22010-08-19 18:01:52 -07004625 void grantUriPermissionLocked(int callingUid,
4626 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004627 if (targetPkg == null) {
4628 throw new NullPointerException("targetPkg");
4629 }
4630
Dianne Hackborn39792d22010-08-19 18:01:52 -07004631 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4632 if (targetUid < 0) {
4633 return;
4634 }
4635
4636 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4637 }
4638
4639 /**
4640 * Like checkGrantUriPermissionLocked, but takes an Intent.
4641 */
4642 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4643 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004644 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004645 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004646 + " from " + intent + "; flags=0x"
4647 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4648
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004649 if (targetPkg == null) {
4650 throw new NullPointerException("targetPkg");
4651 }
4652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004654 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 }
4656 Uri data = intent.getData();
4657 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004658 return -1;
4659 }
4660 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4661 intent.getFlags());
4662 }
4663
4664 /**
4665 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4666 */
4667 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4668 String targetPkg, Intent intent, UriPermissionOwner owner) {
4669 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4670 intent.getFlags(), owner);
4671 }
4672
4673 void grantUriPermissionFromIntentLocked(int callingUid,
4674 String targetPkg, Intent intent, UriPermissionOwner owner) {
4675 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4676 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004677 return;
4678 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004679
4680 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004681 }
4682
4683 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4684 Uri uri, int modeFlags) {
4685 synchronized(this) {
4686 final ProcessRecord r = getRecordForAppLocked(caller);
4687 if (r == null) {
4688 throw new SecurityException("Unable to find app for caller "
4689 + caller
4690 + " when granting permission to uri " + uri);
4691 }
4692 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004693 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 }
4695 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004696 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 }
4698
4699 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4700 null);
4701 }
4702 }
4703
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004704 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004705 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4706 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4707 HashMap<Uri, UriPermission> perms
4708 = mGrantedUriPermissions.get(perm.uid);
4709 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004710 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004711 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 perms.remove(perm.uri);
4713 if (perms.size() == 0) {
4714 mGrantedUriPermissions.remove(perm.uid);
4715 }
4716 }
4717 }
4718 }
4719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4721 int modeFlags) {
4722 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4723 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4724 if (modeFlags == 0) {
4725 return;
4726 }
4727
Joe Onorato8a9b2202010-02-26 18:56:32 -08004728 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004729 "Revoking all granted permissions to " + uri);
4730
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004731 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732
4733 final String authority = uri.getAuthority();
4734 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004735 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004736 if (cpr != null) {
4737 pi = cpr.info;
4738 } else {
4739 try {
4740 pi = pm.resolveContentProvider(authority,
4741 PackageManager.GET_URI_PERMISSION_PATTERNS);
4742 } catch (RemoteException ex) {
4743 }
4744 }
4745 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004746 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 return;
4748 }
4749
4750 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004751 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752 // Right now, if you are not the original owner of the permission,
4753 // you are not allowed to revoke it.
4754 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4755 throw new SecurityException("Uid " + callingUid
4756 + " does not have permission to uri " + uri);
4757 //}
4758 }
4759
4760 // Go through all of the permissions and remove any that match.
4761 final List<String> SEGMENTS = uri.getPathSegments();
4762 if (SEGMENTS != null) {
4763 final int NS = SEGMENTS.size();
4764 int N = mGrantedUriPermissions.size();
4765 for (int i=0; i<N; i++) {
4766 HashMap<Uri, UriPermission> perms
4767 = mGrantedUriPermissions.valueAt(i);
4768 Iterator<UriPermission> it = perms.values().iterator();
4769 toploop:
4770 while (it.hasNext()) {
4771 UriPermission perm = it.next();
4772 Uri targetUri = perm.uri;
4773 if (!authority.equals(targetUri.getAuthority())) {
4774 continue;
4775 }
4776 List<String> targetSegments = targetUri.getPathSegments();
4777 if (targetSegments == null) {
4778 continue;
4779 }
4780 if (targetSegments.size() < NS) {
4781 continue;
4782 }
4783 for (int j=0; j<NS; j++) {
4784 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4785 continue toploop;
4786 }
4787 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004788 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004789 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004790 perm.clearModes(modeFlags);
4791 if (perm.modeFlags == 0) {
4792 it.remove();
4793 }
4794 }
4795 if (perms.size() == 0) {
4796 mGrantedUriPermissions.remove(
4797 mGrantedUriPermissions.keyAt(i));
4798 N--;
4799 i--;
4800 }
4801 }
4802 }
4803 }
4804
4805 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4806 int modeFlags) {
4807 synchronized(this) {
4808 final ProcessRecord r = getRecordForAppLocked(caller);
4809 if (r == null) {
4810 throw new SecurityException("Unable to find app for caller "
4811 + caller
4812 + " when revoking permission to uri " + uri);
4813 }
4814 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004815 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816 return;
4817 }
4818
4819 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4820 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4821 if (modeFlags == 0) {
4822 return;
4823 }
4824
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004825 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826
4827 final String authority = uri.getAuthority();
4828 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004829 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830 if (cpr != null) {
4831 pi = cpr.info;
4832 } else {
4833 try {
4834 pi = pm.resolveContentProvider(authority,
4835 PackageManager.GET_URI_PERMISSION_PATTERNS);
4836 } catch (RemoteException ex) {
4837 }
4838 }
4839 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004840 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 return;
4842 }
4843
4844 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4845 }
4846 }
4847
Dianne Hackborn7e269642010-08-25 19:50:20 -07004848 @Override
4849 public IBinder newUriPermissionOwner(String name) {
4850 synchronized(this) {
4851 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4852 return owner.getExternalTokenLocked();
4853 }
4854 }
4855
4856 @Override
4857 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4858 Uri uri, int modeFlags) {
4859 synchronized(this) {
4860 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4861 if (owner == null) {
4862 throw new IllegalArgumentException("Unknown owner: " + token);
4863 }
4864 if (fromUid != Binder.getCallingUid()) {
4865 if (Binder.getCallingUid() != Process.myUid()) {
4866 // Only system code can grant URI permissions on behalf
4867 // of other users.
4868 throw new SecurityException("nice try");
4869 }
4870 }
4871 if (targetPkg == null) {
4872 throw new IllegalArgumentException("null target");
4873 }
4874 if (uri == null) {
4875 throw new IllegalArgumentException("null uri");
4876 }
4877
4878 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4879 }
4880 }
4881
4882 @Override
4883 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4884 synchronized(this) {
4885 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4886 if (owner == null) {
4887 throw new IllegalArgumentException("Unknown owner: " + token);
4888 }
4889
4890 if (uri == null) {
4891 owner.removeUriPermissionsLocked(mode);
4892 } else {
4893 owner.removeUriPermissionLocked(uri, mode);
4894 }
4895 }
4896 }
4897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004898 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4899 synchronized (this) {
4900 ProcessRecord app =
4901 who != null ? getRecordForAppLocked(who) : null;
4902 if (app == null) return;
4903
4904 Message msg = Message.obtain();
4905 msg.what = WAIT_FOR_DEBUGGER_MSG;
4906 msg.obj = app;
4907 msg.arg1 = waiting ? 1 : 0;
4908 mHandler.sendMessage(msg);
4909 }
4910 }
4911
4912 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4913 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004914 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004916 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004917 }
4918
4919 // =========================================================
4920 // TASK MANAGEMENT
4921 // =========================================================
4922
4923 public List getTasks(int maxNum, int flags,
4924 IThumbnailReceiver receiver) {
4925 ArrayList list = new ArrayList();
4926
4927 PendingThumbnailsRecord pending = null;
4928 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004929 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004930
4931 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004932 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4934 + ", receiver=" + receiver);
4935
4936 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4937 != PackageManager.PERMISSION_GRANTED) {
4938 if (receiver != null) {
4939 // If the caller wants to wait for pending thumbnails,
4940 // it ain't gonna get them.
4941 try {
4942 receiver.finished();
4943 } catch (RemoteException ex) {
4944 }
4945 }
4946 String msg = "Permission Denial: getTasks() from pid="
4947 + Binder.getCallingPid()
4948 + ", uid=" + Binder.getCallingUid()
4949 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004950 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004951 throw new SecurityException(msg);
4952 }
4953
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004954 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004955 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004956 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004957 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004958 TaskRecord curTask = null;
4959 int numActivities = 0;
4960 int numRunning = 0;
4961 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004962 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004964 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965
4966 // Initialize state for next task if needed.
4967 if (top == null ||
4968 (top.state == ActivityState.INITIALIZING
4969 && top.task == r.task)) {
4970 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004971 curTask = r.task;
4972 numActivities = numRunning = 0;
4973 }
4974
4975 // Add 'r' into the current task.
4976 numActivities++;
4977 if (r.app != null && r.app.thread != null) {
4978 numRunning++;
4979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980
Joe Onorato8a9b2202010-02-26 18:56:32 -08004981 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 TAG, r.intent.getComponent().flattenToShortString()
4983 + ": task=" + r.task);
4984
4985 // If the next one is a different task, generate a new
4986 // TaskInfo entry for what we have.
4987 if (next == null || next.task != curTask) {
4988 ActivityManager.RunningTaskInfo ci
4989 = new ActivityManager.RunningTaskInfo();
4990 ci.id = curTask.taskId;
4991 ci.baseActivity = r.intent.getComponent();
4992 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07004993 if (top.thumbHolder != null) {
4994 ci.description = top.thumbHolder.lastDescription;
4995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 ci.numActivities = numActivities;
4997 ci.numRunning = numRunning;
4998 //System.out.println(
4999 // "#" + maxNum + ": " + " descr=" + ci.description);
5000 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005001 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005002 TAG, "State=" + top.state + "Idle=" + top.idle
5003 + " app=" + top.app
5004 + " thr=" + (top.app != null ? top.app.thread : null));
5005 if (top.state == ActivityState.RESUMED
5006 || top.state == ActivityState.PAUSING) {
5007 if (top.idle && top.app != null
5008 && top.app.thread != null) {
5009 topRecord = top;
5010 topThumbnail = top.app.thread;
5011 } else {
5012 top.thumbnailNeeded = true;
5013 }
5014 }
5015 if (pending == null) {
5016 pending = new PendingThumbnailsRecord(receiver);
5017 }
5018 pending.pendingRecords.add(top);
5019 }
5020 list.add(ci);
5021 maxNum--;
5022 top = null;
5023 }
5024 }
5025
5026 if (pending != null) {
5027 mPendingThumbnails.add(pending);
5028 }
5029 }
5030
Joe Onorato8a9b2202010-02-26 18:56:32 -08005031 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032
5033 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005034 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005035 try {
5036 topThumbnail.requestThumbnail(topRecord);
5037 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005038 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005039 sendPendingThumbnail(null, topRecord, null, null, true);
5040 }
5041 }
5042
5043 if (pending == null && receiver != null) {
5044 // In this case all thumbnails were available and the client
5045 // is being asked to be told when the remaining ones come in...
5046 // which is unusually, since the top-most currently running
5047 // activity should never have a canned thumbnail! Oh well.
5048 try {
5049 receiver.finished();
5050 } catch (RemoteException ex) {
5051 }
5052 }
5053
5054 return list;
5055 }
5056
5057 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5058 int flags) {
5059 synchronized (this) {
5060 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5061 "getRecentTasks()");
5062
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005063 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 final int N = mRecentTasks.size();
5066 ArrayList<ActivityManager.RecentTaskInfo> res
5067 = new ArrayList<ActivityManager.RecentTaskInfo>(
5068 maxNum < N ? maxNum : N);
5069 for (int i=0; i<N && maxNum > 0; i++) {
5070 TaskRecord tr = mRecentTasks.get(i);
5071 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
5072 || (tr.intent == null)
5073 || ((tr.intent.getFlags()
5074 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5075 ActivityManager.RecentTaskInfo rti
5076 = new ActivityManager.RecentTaskInfo();
5077 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005078 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 rti.baseIntent = new Intent(
5080 tr.intent != null ? tr.intent : tr.affinityIntent);
5081 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005082 rti.description = tr.lastDescription;
5083
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005084 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5085 // Check whether this activity is currently available.
5086 try {
5087 if (rti.origActivity != null) {
5088 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5089 continue;
5090 }
5091 } else if (rti.baseIntent != null) {
5092 if (pm.queryIntentActivities(rti.baseIntent,
5093 null, 0) == null) {
5094 continue;
5095 }
5096 }
5097 } catch (RemoteException e) {
5098 // Will never happen.
5099 }
5100 }
5101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 res.add(rti);
5103 maxNum--;
5104 }
5105 }
5106 return res;
5107 }
5108 }
5109
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005110 private TaskRecord taskForIdLocked(int id) {
5111 final int N = mRecentTasks.size();
5112 for (int i=0; i<N; i++) {
5113 TaskRecord tr = mRecentTasks.get(i);
5114 if (tr.taskId == id) {
5115 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005116 }
5117 }
5118 return null;
5119 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005120
5121 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5122 synchronized (this) {
5123 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5124 "getTaskThumbnails()");
5125 TaskRecord tr = taskForIdLocked(id);
5126 if (tr != null) {
5127 return mMainStack.getTaskThumbnailsLocked(tr);
5128 }
5129 }
5130 return null;
5131 }
5132
5133 public boolean removeSubTask(int taskId, int subTaskIndex) {
5134 synchronized (this) {
5135 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5136 "removeSubTask()");
5137 long ident = Binder.clearCallingIdentity();
5138 try {
5139 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5140 } finally {
5141 Binder.restoreCallingIdentity(ident);
5142 }
5143 }
5144 }
5145
5146 private void removeTaskProcessesLocked(ActivityRecord root) {
5147 TaskRecord tr = root.task;
5148 Intent baseIntent = new Intent(
5149 tr.intent != null ? tr.intent : tr.affinityIntent);
5150 ComponentName component = baseIntent.getComponent();
5151 if (component == null) {
5152 Slog.w(TAG, "Now component for base intent of task: " + tr);
5153 return;
5154 }
5155
5156 // Find any running services associated with this app.
5157 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5158 for (ServiceRecord sr : mServices.values()) {
5159 if (sr.packageName.equals(component.getPackageName())) {
5160 services.add(sr);
5161 }
5162 }
5163
5164 // Take care of any running services associated with the app.
5165 for (int i=0; i<services.size(); i++) {
5166 ServiceRecord sr = services.get(i);
5167 if (sr.startRequested) {
5168 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
5169 stopServiceLocked(sr);
5170 } else {
5171 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5172 sr.makeNextStartId(), baseIntent, -1));
5173 if (sr.app != null && sr.app.thread != null) {
5174 sendServiceArgsLocked(sr, false);
5175 }
5176 }
5177 }
5178 }
5179
5180 // Find any running processes associated with this app.
5181 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5182 SparseArray<ProcessRecord> appProcs
5183 = mProcessNames.getMap().get(component.getPackageName());
5184 if (appProcs != null) {
5185 for (int i=0; i<appProcs.size(); i++) {
5186 procs.add(appProcs.valueAt(i));
5187 }
5188 }
5189
5190 // Kill the running processes.
5191 for (int i=0; i<procs.size(); i++) {
5192 ProcessRecord pr = procs.get(i);
5193 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5194 Slog.i(TAG, "Killing " + pr + ": remove task");
5195 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5196 pr.processName, pr.setAdj, "remove task");
5197 Process.killProcessQuiet(pr.pid);
5198 } else {
5199 pr.waitingToKill = "remove task";
5200 }
5201 }
5202 }
5203
5204 public boolean removeTask(int taskId, int flags) {
5205 synchronized (this) {
5206 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5207 "removeTask()");
5208 long ident = Binder.clearCallingIdentity();
5209 try {
5210 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5211 if (r != null) {
5212 mRecentTasks.remove(r.task);
5213
5214 if ((flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0) {
5215 removeTaskProcessesLocked(r);
5216 }
5217
5218 return true;
5219 }
5220 } finally {
5221 Binder.restoreCallingIdentity(ident);
5222 }
5223 }
5224 return false;
5225 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005227 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5228 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005229 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005230 TaskRecord jt = startTask;
5231
5232 // First look backwards
5233 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005234 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 if (r.task != jt) {
5236 jt = r.task;
5237 if (affinity.equals(jt.affinity)) {
5238 return j;
5239 }
5240 }
5241 }
5242
5243 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005244 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 jt = startTask;
5246 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005247 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248 if (r.task != jt) {
5249 if (affinity.equals(jt.affinity)) {
5250 return j;
5251 }
5252 jt = r.task;
5253 }
5254 }
5255
5256 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005257 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005258 return N-1;
5259 }
5260
5261 return -1;
5262 }
5263
5264 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005265 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005267 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005268 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5269 "moveTaskToFront()");
5270
5271 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005272 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5273 Binder.getCallingUid(), "Task to front")) {
5274 return;
5275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 final long origId = Binder.clearCallingIdentity();
5277 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005278 TaskRecord tr = taskForIdLocked(task);
5279 if (tr != null) {
5280 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5281 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005282 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005283 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5284 // Caller wants the home activity moved with it. To accomplish this,
5285 // we'll just move the home task to the top first.
5286 mMainStack.moveHomeToFrontLocked();
5287 }
5288 mMainStack.moveTaskToFrontLocked(tr, null);
5289 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005290 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005291 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5292 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005293 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005294 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5295 mMainStack.mUserLeaving = true;
5296 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005297 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5298 // Caller wants the home activity moved with it. To accomplish this,
5299 // we'll just move the home task to the top first.
5300 mMainStack.moveHomeToFrontLocked();
5301 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005302 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005303 return;
5304 }
5305 }
5306 } finally {
5307 Binder.restoreCallingIdentity(origId);
5308 }
5309 }
5310 }
5311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 public void moveTaskToBack(int task) {
5313 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5314 "moveTaskToBack()");
5315
5316 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005317 if (mMainStack.mResumedActivity != null
5318 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005319 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5320 Binder.getCallingUid(), "Task to back")) {
5321 return;
5322 }
5323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005325 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 Binder.restoreCallingIdentity(origId);
5327 }
5328 }
5329
5330 /**
5331 * Moves an activity, and all of the other activities within the same task, to the bottom
5332 * of the history stack. The activity's order within the task is unchanged.
5333 *
5334 * @param token A reference to the activity we wish to move
5335 * @param nonRoot If false then this only works if the activity is the root
5336 * of a task; if true it will work for any activity in a task.
5337 * @return Returns true if the move completed, false if not.
5338 */
5339 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5340 synchronized(this) {
5341 final long origId = Binder.clearCallingIdentity();
5342 int taskId = getTaskForActivityLocked(token, !nonRoot);
5343 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005344 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 }
5346 Binder.restoreCallingIdentity(origId);
5347 }
5348 return false;
5349 }
5350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005351 public void moveTaskBackwards(int task) {
5352 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5353 "moveTaskBackwards()");
5354
5355 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005356 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5357 Binder.getCallingUid(), "Task backwards")) {
5358 return;
5359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005360 final long origId = Binder.clearCallingIdentity();
5361 moveTaskBackwardsLocked(task);
5362 Binder.restoreCallingIdentity(origId);
5363 }
5364 }
5365
5366 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005367 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 }
5369
5370 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5371 synchronized(this) {
5372 return getTaskForActivityLocked(token, onlyRoot);
5373 }
5374 }
5375
5376 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005377 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005378 TaskRecord lastTask = null;
5379 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005380 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005381 if (r == token) {
5382 if (!onlyRoot || lastTask != r.task) {
5383 return r.task.taskId;
5384 }
5385 return -1;
5386 }
5387 lastTask = r.task;
5388 }
5389
5390 return -1;
5391 }
5392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005393 public void finishOtherInstances(IBinder token, ComponentName className) {
5394 synchronized(this) {
5395 final long origId = Binder.clearCallingIdentity();
5396
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005397 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005398 TaskRecord lastTask = null;
5399 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005400 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 if (r.realActivity.equals(className)
5402 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005403 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 null, "others")) {
5405 i--;
5406 N--;
5407 }
5408 }
5409 lastTask = r.task;
5410 }
5411
5412 Binder.restoreCallingIdentity(origId);
5413 }
5414 }
5415
5416 // =========================================================
5417 // THUMBNAILS
5418 // =========================================================
5419
5420 public void reportThumbnail(IBinder token,
5421 Bitmap thumbnail, CharSequence description) {
5422 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5423 final long origId = Binder.clearCallingIdentity();
5424 sendPendingThumbnail(null, token, thumbnail, description, true);
5425 Binder.restoreCallingIdentity(origId);
5426 }
5427
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005428 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 Bitmap thumbnail, CharSequence description, boolean always) {
5430 TaskRecord task = null;
5431 ArrayList receivers = null;
5432
5433 //System.out.println("Send pending thumbnail: " + r);
5434
5435 synchronized(this) {
5436 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005437 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005438 if (index < 0) {
5439 return;
5440 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005441 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005442 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005443 if (thumbnail == null && r.thumbHolder != null) {
5444 thumbnail = r.thumbHolder.lastThumbnail;
5445 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 }
5447 if (thumbnail == null && !always) {
5448 // If there is no thumbnail, and this entry is not actually
5449 // going away, then abort for now and pick up the next
5450 // thumbnail we get.
5451 return;
5452 }
5453 task = r.task;
5454
5455 int N = mPendingThumbnails.size();
5456 int i=0;
5457 while (i<N) {
5458 PendingThumbnailsRecord pr =
5459 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5460 //System.out.println("Looking in " + pr.pendingRecords);
5461 if (pr.pendingRecords.remove(r)) {
5462 if (receivers == null) {
5463 receivers = new ArrayList();
5464 }
5465 receivers.add(pr);
5466 if (pr.pendingRecords.size() == 0) {
5467 pr.finished = true;
5468 mPendingThumbnails.remove(i);
5469 N--;
5470 continue;
5471 }
5472 }
5473 i++;
5474 }
5475 }
5476
5477 if (receivers != null) {
5478 final int N = receivers.size();
5479 for (int i=0; i<N; i++) {
5480 try {
5481 PendingThumbnailsRecord pr =
5482 (PendingThumbnailsRecord)receivers.get(i);
5483 pr.receiver.newThumbnail(
5484 task != null ? task.taskId : -1, thumbnail, description);
5485 if (pr.finished) {
5486 pr.receiver.finished();
5487 }
5488 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005489 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005490 }
5491 }
5492 }
5493 }
5494
5495 // =========================================================
5496 // CONTENT PROVIDERS
5497 // =========================================================
5498
5499 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5500 List providers = null;
5501 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005502 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005503 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005504 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005505 } catch (RemoteException ex) {
5506 }
5507 if (providers != null) {
5508 final int N = providers.size();
5509 for (int i=0; i<N; i++) {
5510 ProviderInfo cpi =
5511 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005512 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 if (cpr == null) {
5514 cpr = new ContentProviderRecord(cpi, app.info);
5515 mProvidersByClass.put(cpi.name, cpr);
5516 }
5517 app.pubProviders.put(cpi.name, cpr);
5518 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005519 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005520 }
5521 }
5522 return providers;
5523 }
5524
5525 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005526 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5528 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5529 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005530 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005531 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005532 return null;
5533 }
5534 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005535 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005536 == PackageManager.PERMISSION_GRANTED) {
5537 return null;
5538 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005539
5540 PathPermission[] pps = cpi.pathPermissions;
5541 if (pps != null) {
5542 int i = pps.length;
5543 while (i > 0) {
5544 i--;
5545 PathPermission pp = pps[i];
5546 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005547 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005548 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005549 return null;
5550 }
5551 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005552 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005553 == PackageManager.PERMISSION_GRANTED) {
5554 return null;
5555 }
5556 }
5557 }
5558
Dianne Hackbornb424b632010-08-18 15:59:05 -07005559 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5560 if (perms != null) {
5561 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5562 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5563 return null;
5564 }
5565 }
5566 }
5567
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005568 String msg;
5569 if (!cpi.exported) {
5570 msg = "Permission Denial: opening provider " + cpi.name
5571 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5572 + ", uid=" + callingUid + ") that is not exported from uid "
5573 + cpi.applicationInfo.uid;
5574 } else {
5575 msg = "Permission Denial: opening provider " + cpi.name
5576 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5577 + ", uid=" + callingUid + ") requires "
5578 + cpi.readPermission + " or " + cpi.writePermission;
5579 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005580 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005581 return msg;
5582 }
5583
5584 private final ContentProviderHolder getContentProviderImpl(
5585 IApplicationThread caller, String name) {
5586 ContentProviderRecord cpr;
5587 ProviderInfo cpi = null;
5588
5589 synchronized(this) {
5590 ProcessRecord r = null;
5591 if (caller != null) {
5592 r = getRecordForAppLocked(caller);
5593 if (r == null) {
5594 throw new SecurityException(
5595 "Unable to find app for caller " + caller
5596 + " (pid=" + Binder.getCallingPid()
5597 + ") when getting content provider " + name);
5598 }
5599 }
5600
5601 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005602 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005603 if (cpr != null) {
5604 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005605 String msg;
5606 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5607 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005608 }
5609
5610 if (r != null && cpr.canRunHere(r)) {
5611 // This provider has been published or is in the process
5612 // of being published... but it is also allowed to run
5613 // in the caller's process, so don't make a connection
5614 // and just let the caller instantiate its own instance.
5615 if (cpr.provider != null) {
5616 // don't give caller the provider object, it needs
5617 // to make its own.
5618 cpr = new ContentProviderRecord(cpr);
5619 }
5620 return cpr;
5621 }
5622
5623 final long origId = Binder.clearCallingIdentity();
5624
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005625 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005626 // return it right away.
5627 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005628 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005629 "Adding provider requested by "
5630 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005631 + cpr.info.processName);
5632 Integer cnt = r.conProviders.get(cpr);
5633 if (cnt == null) {
5634 r.conProviders.put(cpr, new Integer(1));
5635 } else {
5636 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5637 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005638 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005639 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5640 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005641 // make sure to count it as being accessed and thus
5642 // back up on the LRU list. This is good because
5643 // content providers are often expensive to start.
5644 updateLruProcessLocked(cpr.app, false, true);
5645 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005646 } else {
5647 cpr.externals++;
5648 }
5649
5650 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005651 updateOomAdjLocked(cpr.app);
5652 }
5653
5654 Binder.restoreCallingIdentity(origId);
5655
5656 } else {
5657 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005658 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005659 resolveContentProvider(name,
5660 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005661 } catch (RemoteException ex) {
5662 }
5663 if (cpi == null) {
5664 return null;
5665 }
5666
Dianne Hackbornb424b632010-08-18 15:59:05 -07005667 String msg;
5668 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5669 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005670 }
5671
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005672 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005673 && !cpi.processName.equals("system")) {
5674 // If this content provider does not run in the system
5675 // process, and the system is not yet ready to run other
5676 // processes, then fail fast instead of hanging.
5677 throw new IllegalArgumentException(
5678 "Attempt to launch content provider before system ready");
5679 }
5680
Dianne Hackborn860755f2010-06-03 18:47:52 -07005681 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 final boolean firstClass = cpr == null;
5683 if (firstClass) {
5684 try {
5685 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005686 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005687 getApplicationInfo(
5688 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005689 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005690 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005691 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005692 + cpi.name);
5693 return null;
5694 }
5695 cpr = new ContentProviderRecord(cpi, ai);
5696 } catch (RemoteException ex) {
5697 // pm is in same process, this will never happen.
5698 }
5699 }
5700
5701 if (r != null && cpr.canRunHere(r)) {
5702 // If this is a multiprocess provider, then just return its
5703 // info and allow the caller to instantiate it. Only do
5704 // this if the provider is the same user as the caller's
5705 // process, or can run as root (so can be in any process).
5706 return cpr;
5707 }
5708
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005709 if (DEBUG_PROVIDER) {
5710 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005711 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005712 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005713 }
5714
5715 // This is single process, and our app is now connecting to it.
5716 // See if we are already in the process of launching this
5717 // provider.
5718 final int N = mLaunchingProviders.size();
5719 int i;
5720 for (i=0; i<N; i++) {
5721 if (mLaunchingProviders.get(i) == cpr) {
5722 break;
5723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 }
5725
5726 // If the provider is not already being launched, then get it
5727 // started.
5728 if (i >= N) {
5729 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005730
5731 try {
5732 // Content provider is now in use, its package can't be stopped.
5733 try {
5734 AppGlobals.getPackageManager().setPackageStoppedState(
5735 cpr.appInfo.packageName, false);
5736 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005737 } catch (IllegalArgumentException e) {
5738 Slog.w(TAG, "Failed trying to unstop package "
5739 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005740 }
5741
5742 ProcessRecord proc = startProcessLocked(cpi.processName,
5743 cpr.appInfo, false, 0, "content provider",
5744 new ComponentName(cpi.applicationInfo.packageName,
5745 cpi.name), false);
5746 if (proc == null) {
5747 Slog.w(TAG, "Unable to launch app "
5748 + cpi.applicationInfo.packageName + "/"
5749 + cpi.applicationInfo.uid + " for provider "
5750 + name + ": process is bad");
5751 return null;
5752 }
5753 cpr.launchingApp = proc;
5754 mLaunchingProviders.add(cpr);
5755 } finally {
5756 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758 }
5759
5760 // Make sure the provider is published (the same provider class
5761 // may be published under multiple names).
5762 if (firstClass) {
5763 mProvidersByClass.put(cpi.name, cpr);
5764 }
5765 mProvidersByName.put(name, cpr);
5766
5767 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005768 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005769 "Adding provider requested by "
5770 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005771 + cpr.info.processName);
5772 Integer cnt = r.conProviders.get(cpr);
5773 if (cnt == null) {
5774 r.conProviders.put(cpr, new Integer(1));
5775 } else {
5776 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005778 cpr.clients.add(r);
5779 } else {
5780 cpr.externals++;
5781 }
5782 }
5783 }
5784
5785 // Wait for the provider to be published...
5786 synchronized (cpr) {
5787 while (cpr.provider == null) {
5788 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005789 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005790 + cpi.applicationInfo.packageName + "/"
5791 + cpi.applicationInfo.uid + " for provider "
5792 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005793 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005794 cpi.applicationInfo.packageName,
5795 cpi.applicationInfo.uid, name);
5796 return null;
5797 }
5798 try {
5799 cpr.wait();
5800 } catch (InterruptedException ex) {
5801 }
5802 }
5803 }
5804 return cpr;
5805 }
5806
5807 public final ContentProviderHolder getContentProvider(
5808 IApplicationThread caller, String name) {
5809 if (caller == null) {
5810 String msg = "null IApplicationThread when getting content provider "
5811 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005812 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005813 throw new SecurityException(msg);
5814 }
5815
5816 return getContentProviderImpl(caller, name);
5817 }
5818
5819 private ContentProviderHolder getContentProviderExternal(String name) {
5820 return getContentProviderImpl(null, name);
5821 }
5822
5823 /**
5824 * Drop a content provider from a ProcessRecord's bookkeeping
5825 * @param cpr
5826 */
5827 public void removeContentProvider(IApplicationThread caller, String name) {
5828 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005829 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005831 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005832 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005833 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005834 return;
5835 }
5836 final ProcessRecord r = getRecordForAppLocked(caller);
5837 if (r == null) {
5838 throw new SecurityException(
5839 "Unable to find app for caller " + caller +
5840 " when removing content provider " + name);
5841 }
5842 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005843 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005844 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005845 + r.info.processName + " from process "
5846 + localCpr.appInfo.processName);
5847 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005848 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005849 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005850 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 return;
5852 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005853 Integer cnt = r.conProviders.get(localCpr);
5854 if (cnt == null || cnt.intValue() <= 1) {
5855 localCpr.clients.remove(r);
5856 r.conProviders.remove(localCpr);
5857 } else {
5858 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 }
5861 updateOomAdjLocked();
5862 }
5863 }
5864
5865 private void removeContentProviderExternal(String name) {
5866 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005867 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 if(cpr == null) {
5869 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005870 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005871 return;
5872 }
5873
5874 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005875 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005876 localCpr.externals--;
5877 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005878 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 }
5880 updateOomAdjLocked();
5881 }
5882 }
5883
5884 public final void publishContentProviders(IApplicationThread caller,
5885 List<ContentProviderHolder> providers) {
5886 if (providers == null) {
5887 return;
5888 }
5889
5890 synchronized(this) {
5891 final ProcessRecord r = getRecordForAppLocked(caller);
5892 if (r == null) {
5893 throw new SecurityException(
5894 "Unable to find app for caller " + caller
5895 + " (pid=" + Binder.getCallingPid()
5896 + ") when publishing content providers");
5897 }
5898
5899 final long origId = Binder.clearCallingIdentity();
5900
5901 final int N = providers.size();
5902 for (int i=0; i<N; i++) {
5903 ContentProviderHolder src = providers.get(i);
5904 if (src == null || src.info == null || src.provider == null) {
5905 continue;
5906 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005907 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005908 if (dst != null) {
5909 mProvidersByClass.put(dst.info.name, dst);
5910 String names[] = dst.info.authority.split(";");
5911 for (int j = 0; j < names.length; j++) {
5912 mProvidersByName.put(names[j], dst);
5913 }
5914
5915 int NL = mLaunchingProviders.size();
5916 int j;
5917 for (j=0; j<NL; j++) {
5918 if (mLaunchingProviders.get(j) == dst) {
5919 mLaunchingProviders.remove(j);
5920 j--;
5921 NL--;
5922 }
5923 }
5924 synchronized (dst) {
5925 dst.provider = src.provider;
5926 dst.app = r;
5927 dst.notifyAll();
5928 }
5929 updateOomAdjLocked(r);
5930 }
5931 }
5932
5933 Binder.restoreCallingIdentity(origId);
5934 }
5935 }
5936
5937 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005938 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005939 synchronized (mSelf) {
5940 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5941 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005942 if (providers != null) {
5943 for (int i=providers.size()-1; i>=0; i--) {
5944 ProviderInfo pi = (ProviderInfo)providers.get(i);
5945 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5946 Slog.w(TAG, "Not installing system proc provider " + pi.name
5947 + ": not system .apk");
5948 providers.remove(i);
5949 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005950 }
5951 }
5952 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005953 if (providers != null) {
5954 mSystemThread.installSystemProviders(providers);
5955 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005956
5957 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005958 }
5959
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005960 /**
5961 * Allows app to retrieve the MIME type of a URI without having permission
5962 * to access its content provider.
5963 *
5964 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5965 *
5966 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5967 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5968 */
5969 public String getProviderMimeType(Uri uri) {
5970 final String name = uri.getAuthority();
5971 final long ident = Binder.clearCallingIdentity();
5972 ContentProviderHolder holder = null;
5973
5974 try {
5975 holder = getContentProviderExternal(name);
5976 if (holder != null) {
5977 return holder.provider.getType(uri);
5978 }
5979 } catch (RemoteException e) {
5980 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5981 return null;
5982 } finally {
5983 if (holder != null) {
5984 removeContentProviderExternal(name);
5985 }
5986 Binder.restoreCallingIdentity(ident);
5987 }
5988
5989 return null;
5990 }
5991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005992 // =========================================================
5993 // GLOBAL MANAGEMENT
5994 // =========================================================
5995
5996 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5997 ApplicationInfo info, String customProcess) {
5998 String proc = customProcess != null ? customProcess : info.processName;
5999 BatteryStatsImpl.Uid.Proc ps = null;
6000 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6001 synchronized (stats) {
6002 ps = stats.getProcessStatsLocked(info.uid, proc);
6003 }
6004 return new ProcessRecord(ps, thread, info, proc);
6005 }
6006
6007 final ProcessRecord addAppLocked(ApplicationInfo info) {
6008 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
6009
6010 if (app == null) {
6011 app = newProcessRecordLocked(null, info, null);
6012 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006013 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006014 }
6015
Dianne Hackborne7f97212011-02-24 14:40:20 -08006016 // This package really, really can not be stopped.
6017 try {
6018 AppGlobals.getPackageManager().setPackageStoppedState(
6019 info.packageName, false);
6020 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006021 } catch (IllegalArgumentException e) {
6022 Slog.w(TAG, "Failed trying to unstop package "
6023 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006024 }
6025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006026 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6027 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6028 app.persistent = true;
6029 app.maxAdj = CORE_SERVER_ADJ;
6030 }
6031 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6032 mPersistentStartingProcesses.add(app);
6033 startProcessLocked(app, "added application", app.processName);
6034 }
6035
6036 return app;
6037 }
6038
6039 public void unhandledBack() {
6040 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6041 "unhandledBack()");
6042
6043 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006044 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006045 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006046 TAG, "Performing unhandledBack(): stack size = " + count);
6047 if (count > 1) {
6048 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006049 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006050 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6051 Binder.restoreCallingIdentity(origId);
6052 }
6053 }
6054 }
6055
6056 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6057 String name = uri.getAuthority();
6058 ContentProviderHolder cph = getContentProviderExternal(name);
6059 ParcelFileDescriptor pfd = null;
6060 if (cph != null) {
6061 // We record the binder invoker's uid in thread-local storage before
6062 // going to the content provider to open the file. Later, in the code
6063 // that handles all permissions checks, we look for this uid and use
6064 // that rather than the Activity Manager's own uid. The effect is that
6065 // we do the check against the caller's permissions even though it looks
6066 // to the content provider like the Activity Manager itself is making
6067 // the request.
6068 sCallerIdentity.set(new Identity(
6069 Binder.getCallingPid(), Binder.getCallingUid()));
6070 try {
6071 pfd = cph.provider.openFile(uri, "r");
6072 } catch (FileNotFoundException e) {
6073 // do nothing; pfd will be returned null
6074 } finally {
6075 // Ensure that whatever happens, we clean up the identity state
6076 sCallerIdentity.remove();
6077 }
6078
6079 // We've got the fd now, so we're done with the provider.
6080 removeContentProviderExternal(name);
6081 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006082 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006083 }
6084 return pfd;
6085 }
6086
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006087 // Actually is sleeping or shutting down or whatever else in the future
6088 // is an inactive state.
6089 public boolean isSleeping() {
6090 return mSleeping || mShuttingDown;
6091 }
6092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006093 public void goingToSleep() {
6094 synchronized(this) {
6095 mSleeping = true;
6096 mWindowManager.setEventDispatching(false);
6097
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006098 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006099
6100 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006101 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006102 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6103 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006104 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006105 }
6106 }
6107
Dianne Hackborn55280a92009-05-07 15:53:46 -07006108 public boolean shutdown(int timeout) {
6109 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6110 != PackageManager.PERMISSION_GRANTED) {
6111 throw new SecurityException("Requires permission "
6112 + android.Manifest.permission.SHUTDOWN);
6113 }
6114
6115 boolean timedout = false;
6116
6117 synchronized(this) {
6118 mShuttingDown = true;
6119 mWindowManager.setEventDispatching(false);
6120
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006121 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006122 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006123 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006124 while (mMainStack.mResumedActivity != null
6125 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006126 long delay = endTime - System.currentTimeMillis();
6127 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006128 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006129 timedout = true;
6130 break;
6131 }
6132 try {
6133 this.wait();
6134 } catch (InterruptedException e) {
6135 }
6136 }
6137 }
6138 }
6139
6140 mUsageStatsService.shutdown();
6141 mBatteryStatsService.shutdown();
6142
6143 return timedout;
6144 }
6145
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006146 public final void activitySlept(IBinder token) {
6147 if (localLOGV) Slog.v(
6148 TAG, "Activity slept: token=" + token);
6149
6150 ActivityRecord r = null;
6151
6152 final long origId = Binder.clearCallingIdentity();
6153
6154 synchronized (this) {
6155 int index = mMainStack.indexOfTokenLocked(token);
6156 if (index >= 0) {
6157 r = (ActivityRecord)mMainStack.mHistory.get(index);
6158 mMainStack.activitySleptLocked(r);
6159 }
6160 }
6161
6162 Binder.restoreCallingIdentity(origId);
6163 }
6164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006165 public void wakingUp() {
6166 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167 mWindowManager.setEventDispatching(true);
6168 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006169 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006170 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006171 }
6172 }
6173
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006174 public void stopAppSwitches() {
6175 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6176 != PackageManager.PERMISSION_GRANTED) {
6177 throw new SecurityException("Requires permission "
6178 + android.Manifest.permission.STOP_APP_SWITCHES);
6179 }
6180
6181 synchronized(this) {
6182 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6183 + APP_SWITCH_DELAY_TIME;
6184 mDidAppSwitch = false;
6185 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6186 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6187 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6188 }
6189 }
6190
6191 public void resumeAppSwitches() {
6192 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6193 != PackageManager.PERMISSION_GRANTED) {
6194 throw new SecurityException("Requires permission "
6195 + android.Manifest.permission.STOP_APP_SWITCHES);
6196 }
6197
6198 synchronized(this) {
6199 // Note that we don't execute any pending app switches... we will
6200 // let those wait until either the timeout, or the next start
6201 // activity request.
6202 mAppSwitchesAllowedTime = 0;
6203 }
6204 }
6205
6206 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6207 String name) {
6208 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6209 return true;
6210 }
6211
6212 final int perm = checkComponentPermission(
6213 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006214 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006215 if (perm == PackageManager.PERMISSION_GRANTED) {
6216 return true;
6217 }
6218
Joe Onorato8a9b2202010-02-26 18:56:32 -08006219 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006220 return false;
6221 }
6222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006223 public void setDebugApp(String packageName, boolean waitForDebugger,
6224 boolean persistent) {
6225 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6226 "setDebugApp()");
6227
6228 // Note that this is not really thread safe if there are multiple
6229 // callers into it at the same time, but that's not a situation we
6230 // care about.
6231 if (persistent) {
6232 final ContentResolver resolver = mContext.getContentResolver();
6233 Settings.System.putString(
6234 resolver, Settings.System.DEBUG_APP,
6235 packageName);
6236 Settings.System.putInt(
6237 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6238 waitForDebugger ? 1 : 0);
6239 }
6240
6241 synchronized (this) {
6242 if (!persistent) {
6243 mOrigDebugApp = mDebugApp;
6244 mOrigWaitForDebugger = mWaitForDebugger;
6245 }
6246 mDebugApp = packageName;
6247 mWaitForDebugger = waitForDebugger;
6248 mDebugTransient = !persistent;
6249 if (packageName != null) {
6250 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006251 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006252 Binder.restoreCallingIdentity(origId);
6253 }
6254 }
6255 }
6256
6257 public void setAlwaysFinish(boolean enabled) {
6258 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6259 "setAlwaysFinish()");
6260
6261 Settings.System.putInt(
6262 mContext.getContentResolver(),
6263 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6264
6265 synchronized (this) {
6266 mAlwaysFinishActivities = enabled;
6267 }
6268 }
6269
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006270 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006271 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006272 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006273 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006274 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006275 }
6276 }
6277
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006278 public boolean isUserAMonkey() {
6279 // For now the fact that there is a controller implies
6280 // we have a monkey.
6281 synchronized (this) {
6282 return mController != null;
6283 }
6284 }
6285
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006286 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006287 synchronized (this) {
6288 mWatchers.register(watcher);
6289 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006290 }
6291
6292 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006293 synchronized (this) {
6294 mWatchers.unregister(watcher);
6295 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006296 }
6297
Jeff Sharkeya4620792011-05-20 15:29:23 -07006298 public void registerProcessObserver(IProcessObserver observer) {
6299 mProcessObservers.register(observer);
6300 }
6301
6302 public void unregisterProcessObserver(IProcessObserver observer) {
6303 mProcessObservers.unregister(observer);
6304 }
6305
Daniel Sandler69a48172010-06-23 16:29:36 -04006306 public void setImmersive(IBinder token, boolean immersive) {
6307 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006308 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006309 if (index < 0) {
6310 throw new IllegalArgumentException();
6311 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006312 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006313 r.immersive = immersive;
6314 }
6315 }
6316
6317 public boolean isImmersive(IBinder token) {
6318 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006319 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006320 if (index < 0) {
6321 throw new IllegalArgumentException();
6322 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006323 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006324 return r.immersive;
6325 }
6326 }
6327
6328 public boolean isTopActivityImmersive() {
6329 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006330 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006331 return (r != null) ? r.immersive : false;
6332 }
6333 }
6334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006335 public final void enterSafeMode() {
6336 synchronized(this) {
6337 // It only makes sense to do this before the system is ready
6338 // and started launching other packages.
6339 if (!mSystemReady) {
6340 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006341 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 } catch (RemoteException e) {
6343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006344 }
6345 }
6346 }
6347
Jeff Brownb09abc12011-01-13 21:08:27 -08006348 public final void showSafeModeOverlay() {
6349 View v = LayoutInflater.from(mContext).inflate(
6350 com.android.internal.R.layout.safe_mode, null);
6351 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6352 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6353 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6354 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6355 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6356 lp.format = v.getBackground().getOpacity();
6357 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6358 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6359 ((WindowManager)mContext.getSystemService(
6360 Context.WINDOW_SERVICE)).addView(v, lp);
6361 }
6362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 public void noteWakeupAlarm(IIntentSender sender) {
6364 if (!(sender instanceof PendingIntentRecord)) {
6365 return;
6366 }
6367 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6368 synchronized (stats) {
6369 if (mBatteryStatsService.isOnBattery()) {
6370 mBatteryStatsService.enforceCallingPermission();
6371 PendingIntentRecord rec = (PendingIntentRecord)sender;
6372 int MY_UID = Binder.getCallingUid();
6373 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6374 BatteryStatsImpl.Uid.Pkg pkg =
6375 stats.getPackageStatsLocked(uid, rec.key.packageName);
6376 pkg.incWakeupsLocked();
6377 }
6378 }
6379 }
6380
Dianne Hackborn64825172011-03-02 21:32:58 -08006381 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006382 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006383 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006385 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006386 // XXX Note: don't acquire main activity lock here, because the window
6387 // manager calls in with its locks held.
6388
6389 boolean killed = false;
6390 synchronized (mPidsSelfLocked) {
6391 int[] types = new int[pids.length];
6392 int worstType = 0;
6393 for (int i=0; i<pids.length; i++) {
6394 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6395 if (proc != null) {
6396 int type = proc.setAdj;
6397 types[i] = type;
6398 if (type > worstType) {
6399 worstType = type;
6400 }
6401 }
6402 }
6403
Dianne Hackborn64825172011-03-02 21:32:58 -08006404 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006405 // then constrain it so we will kill all hidden procs.
6406 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6407 worstType = HIDDEN_APP_MIN_ADJ;
6408 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006409
6410 // If this is not a secure call, don't let it kill processes that
6411 // are important.
6412 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6413 worstType = SECONDARY_SERVER_ADJ;
6414 }
6415
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006416 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006417 for (int i=0; i<pids.length; i++) {
6418 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6419 if (proc == null) {
6420 continue;
6421 }
6422 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006423 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006424 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006425 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6426 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006427 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006428 proc.killedBackground = true;
6429 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006430 }
6431 }
6432 }
6433 return killed;
6434 }
6435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006436 public final void startRunning(String pkg, String cls, String action,
6437 String data) {
6438 synchronized(this) {
6439 if (mStartRunning) {
6440 return;
6441 }
6442 mStartRunning = true;
6443 mTopComponent = pkg != null && cls != null
6444 ? new ComponentName(pkg, cls) : null;
6445 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6446 mTopData = data;
6447 if (!mSystemReady) {
6448 return;
6449 }
6450 }
6451
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006452 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006453 }
6454
6455 private void retrieveSettings() {
6456 final ContentResolver resolver = mContext.getContentResolver();
6457 String debugApp = Settings.System.getString(
6458 resolver, Settings.System.DEBUG_APP);
6459 boolean waitForDebugger = Settings.System.getInt(
6460 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6461 boolean alwaysFinishActivities = Settings.System.getInt(
6462 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6463
6464 Configuration configuration = new Configuration();
6465 Settings.System.getConfiguration(resolver, configuration);
6466
6467 synchronized (this) {
6468 mDebugApp = mOrigDebugApp = debugApp;
6469 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6470 mAlwaysFinishActivities = alwaysFinishActivities;
6471 // This happens before any activities are started, so we can
6472 // change mConfiguration in-place.
6473 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006474 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006475 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006476 }
6477 }
6478
6479 public boolean testIsSystemReady() {
6480 // no need to synchronize(this) just to read & return the value
6481 return mSystemReady;
6482 }
6483
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006484 private static File getCalledPreBootReceiversFile() {
6485 File dataDir = Environment.getDataDirectory();
6486 File systemDir = new File(dataDir, "system");
6487 File fname = new File(systemDir, "called_pre_boots.dat");
6488 return fname;
6489 }
6490
6491 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6492 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6493 File file = getCalledPreBootReceiversFile();
6494 FileInputStream fis = null;
6495 try {
6496 fis = new FileInputStream(file);
6497 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6498 int vers = dis.readInt();
6499 String codename = dis.readUTF();
6500 if (vers == android.os.Build.VERSION.SDK_INT
6501 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6502 int num = dis.readInt();
6503 while (num > 0) {
6504 num--;
6505 String pkg = dis.readUTF();
6506 String cls = dis.readUTF();
6507 lastDoneReceivers.add(new ComponentName(pkg, cls));
6508 }
6509 }
6510 } catch (FileNotFoundException e) {
6511 } catch (IOException e) {
6512 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6513 } finally {
6514 if (fis != null) {
6515 try {
6516 fis.close();
6517 } catch (IOException e) {
6518 }
6519 }
6520 }
6521 return lastDoneReceivers;
6522 }
6523
6524 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6525 File file = getCalledPreBootReceiversFile();
6526 FileOutputStream fos = null;
6527 DataOutputStream dos = null;
6528 try {
6529 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6530 fos = new FileOutputStream(file);
6531 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6532 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6533 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6534 dos.writeInt(list.size());
6535 for (int i=0; i<list.size(); i++) {
6536 dos.writeUTF(list.get(i).getPackageName());
6537 dos.writeUTF(list.get(i).getClassName());
6538 }
6539 } catch (IOException e) {
6540 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6541 file.delete();
6542 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006543 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006544 if (dos != null) {
6545 try {
6546 dos.close();
6547 } catch (IOException e) {
6548 // TODO Auto-generated catch block
6549 e.printStackTrace();
6550 }
6551 }
6552 }
6553 }
6554
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006555 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006556 // In the simulator, startRunning will never have been called, which
6557 // normally sets a few crucial variables. Do it here instead.
6558 if (!Process.supportsProcesses()) {
6559 mStartRunning = true;
6560 mTopAction = Intent.ACTION_MAIN;
6561 }
6562
6563 synchronized(this) {
6564 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006565 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566 return;
6567 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006568
6569 // Check to see if there are any update receivers to run.
6570 if (!mDidUpdate) {
6571 if (mWaitingUpdate) {
6572 return;
6573 }
6574 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6575 List<ResolveInfo> ris = null;
6576 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006577 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006578 intent, null, 0);
6579 } catch (RemoteException e) {
6580 }
6581 if (ris != null) {
6582 for (int i=ris.size()-1; i>=0; i--) {
6583 if ((ris.get(i).activityInfo.applicationInfo.flags
6584 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6585 ris.remove(i);
6586 }
6587 }
6588 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006589
6590 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6591
6592 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006593 for (int i=0; i<ris.size(); i++) {
6594 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006595 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6596 if (lastDoneReceivers.contains(comp)) {
6597 ris.remove(i);
6598 i--;
6599 }
6600 }
6601
6602 for (int i=0; i<ris.size(); i++) {
6603 ActivityInfo ai = ris.get(i).activityInfo;
6604 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6605 doneReceivers.add(comp);
6606 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006607 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006608 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006609 finisher = new IIntentReceiver.Stub() {
6610 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006611 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006612 boolean sticky) {
6613 // The raw IIntentReceiver interface is called
6614 // with the AM lock held, so redispatch to
6615 // execute our code without the lock.
6616 mHandler.post(new Runnable() {
6617 public void run() {
6618 synchronized (ActivityManagerService.this) {
6619 mDidUpdate = true;
6620 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006621 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006622 systemReady(goingCallback);
6623 }
6624 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006625 }
6626 };
6627 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006628 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006629 broadcastIntentLocked(null, null, intent, null, finisher,
6630 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006631 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006632 mWaitingUpdate = true;
6633 }
6634 }
6635 }
6636 if (mWaitingUpdate) {
6637 return;
6638 }
6639 mDidUpdate = true;
6640 }
6641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006642 mSystemReady = true;
6643 if (!mStartRunning) {
6644 return;
6645 }
6646 }
6647
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006648 ArrayList<ProcessRecord> procsToKill = null;
6649 synchronized(mPidsSelfLocked) {
6650 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6651 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6652 if (!isAllowedWhileBooting(proc.info)){
6653 if (procsToKill == null) {
6654 procsToKill = new ArrayList<ProcessRecord>();
6655 }
6656 procsToKill.add(proc);
6657 }
6658 }
6659 }
6660
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006661 synchronized(this) {
6662 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006663 for (int i=procsToKill.size()-1; i>=0; i--) {
6664 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006665 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006666 removeProcessLocked(proc, true);
6667 }
6668 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006669
6670 // Now that we have cleaned up any update processes, we
6671 // are ready to start launching real processes and know that
6672 // we won't trample on them any more.
6673 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006674 }
6675
Joe Onorato8a9b2202010-02-26 18:56:32 -08006676 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006677 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006678 SystemClock.uptimeMillis());
6679
6680 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006681 // Make sure we have no pre-ready processes sitting around.
6682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006683 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6684 ResolveInfo ri = mContext.getPackageManager()
6685 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006686 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006687 CharSequence errorMsg = null;
6688 if (ri != null) {
6689 ActivityInfo ai = ri.activityInfo;
6690 ApplicationInfo app = ai.applicationInfo;
6691 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6692 mTopAction = Intent.ACTION_FACTORY_TEST;
6693 mTopData = null;
6694 mTopComponent = new ComponentName(app.packageName,
6695 ai.name);
6696 } else {
6697 errorMsg = mContext.getResources().getText(
6698 com.android.internal.R.string.factorytest_not_system);
6699 }
6700 } else {
6701 errorMsg = mContext.getResources().getText(
6702 com.android.internal.R.string.factorytest_no_action);
6703 }
6704 if (errorMsg != null) {
6705 mTopAction = null;
6706 mTopData = null;
6707 mTopComponent = null;
6708 Message msg = Message.obtain();
6709 msg.what = SHOW_FACTORY_ERROR_MSG;
6710 msg.getData().putCharSequence("msg", errorMsg);
6711 mHandler.sendMessage(msg);
6712 }
6713 }
6714 }
6715
6716 retrieveSettings();
6717
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006718 if (goingCallback != null) goingCallback.run();
6719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006720 synchronized (this) {
6721 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6722 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006723 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006724 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006725 if (apps != null) {
6726 int N = apps.size();
6727 int i;
6728 for (i=0; i<N; i++) {
6729 ApplicationInfo info
6730 = (ApplicationInfo)apps.get(i);
6731 if (info != null &&
6732 !info.packageName.equals("android")) {
6733 addAppLocked(info);
6734 }
6735 }
6736 }
6737 } catch (RemoteException ex) {
6738 // pm is in same process, this will never happen.
6739 }
6740 }
6741
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006742 // Start up initial activity.
6743 mBooting = true;
6744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006745 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006746 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006747 Message msg = Message.obtain();
6748 msg.what = SHOW_UID_ERROR_MSG;
6749 mHandler.sendMessage(msg);
6750 }
6751 } catch (RemoteException e) {
6752 }
6753
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006754 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006755 }
6756 }
6757
Dan Egnorb7f03672009-12-09 16:22:32 -08006758 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006759 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006760 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006761 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006762 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006763 startAppProblemLocked(app);
6764 app.stopFreezingAllLocked();
6765 return handleAppCrashLocked(app);
6766 }
6767
Dan Egnorb7f03672009-12-09 16:22:32 -08006768 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006769 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006770 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006771 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006772 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6773 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006774 startAppProblemLocked(app);
6775 app.stopFreezingAllLocked();
6776 }
6777
6778 /**
6779 * Generate a process error record, suitable for attachment to a ProcessRecord.
6780 *
6781 * @param app The ProcessRecord in which the error occurred.
6782 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6783 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006784 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006785 * @param shortMsg Short message describing the crash.
6786 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006787 * @param stackTrace Full crash stack trace, may be null.
6788 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006789 * @return Returns a fully-formed AppErrorStateInfo record.
6790 */
6791 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006792 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006793 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006795 report.condition = condition;
6796 report.processName = app.processName;
6797 report.pid = app.pid;
6798 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006799 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006800 report.shortMsg = shortMsg;
6801 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006802 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006803
6804 return report;
6805 }
6806
Dan Egnor42471dd2010-01-07 17:25:22 -08006807 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006808 synchronized (this) {
6809 app.crashing = false;
6810 app.crashingReport = null;
6811 app.notResponding = false;
6812 app.notRespondingReport = null;
6813 if (app.anrDialog == fromDialog) {
6814 app.anrDialog = null;
6815 }
6816 if (app.waitDialog == fromDialog) {
6817 app.waitDialog = null;
6818 }
6819 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006820 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006821 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07006822 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6823 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006824 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006826 }
6827 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006828
Dan Egnorb7f03672009-12-09 16:22:32 -08006829 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006830 long now = SystemClock.uptimeMillis();
6831
6832 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6833 app.info.uid);
6834 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6835 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006836 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006837 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006838 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006839 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006840 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6841 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006842 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006843 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006844 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006845 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006846 }
6847 }
6848 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006849 // Don't let services in this process be restarted and potentially
6850 // annoy the user repeatedly. Unless it is persistent, since those
6851 // processes run critical code.
6852 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006853 // We don't want to start this process again until the user
6854 // explicitly does so... but for persistent process, we really
6855 // need to keep it running. If a persistent process is actually
6856 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006857 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006858 app.info.processName);
6859 mBadProcesses.put(app.info.processName, app.info.uid, now);
6860 app.bad = true;
6861 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6862 app.removed = true;
6863 removeProcessLocked(app, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006864 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006865 return false;
6866 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006867 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006868 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006869 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006870 if (r.app == app) {
6871 // If the top running activity is from this crashing
6872 // process, then terminate it to avoid getting in a loop.
6873 Slog.w(TAG, " Force finishing activity "
6874 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006875 int index = mMainStack.indexOfTokenLocked(r);
6876 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006877 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006878 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006879 // stopped, to avoid a situation where one will get
6880 // re-start our crashing activity once it gets resumed again.
6881 index--;
6882 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006883 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006884 if (r.state == ActivityState.RESUMED
6885 || r.state == ActivityState.PAUSING
6886 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006887 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006888 Slog.w(TAG, " Force finishing activity "
6889 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006890 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006891 Activity.RESULT_CANCELED, null, "crashed");
6892 }
6893 }
6894 }
6895 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006896 }
6897
6898 // Bump up the crash count of any services currently running in the proc.
6899 if (app.services.size() != 0) {
6900 // Any services running in the application need to be placed
6901 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006902 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006903 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006904 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006905 sr.crashCount++;
6906 }
6907 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006908
6909 // If the crashing process is what we consider to be the "home process" and it has been
6910 // replaced by a third-party app, clear the package preferred activities from packages
6911 // with a home activity running in the process to prevent a repeatedly crashing app
6912 // from blocking the user to manually clear the list.
6913 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6914 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6915 Iterator it = mHomeProcess.activities.iterator();
6916 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006917 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006918 if (r.isHomeActivity) {
6919 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6920 try {
6921 ActivityThread.getPackageManager()
6922 .clearPackagePreferredActivities(r.packageName);
6923 } catch (RemoteException c) {
6924 // pm is in same process, this will never happen.
6925 }
6926 }
6927 }
6928 }
6929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006930 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6931 return true;
6932 }
6933
6934 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006935 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6936 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 skipCurrentReceiverLocked(app);
6938 }
6939
6940 void skipCurrentReceiverLocked(ProcessRecord app) {
6941 boolean reschedule = false;
6942 BroadcastRecord r = app.curReceiver;
6943 if (r != null) {
6944 // The current broadcast is waiting for this app's receiver
6945 // to be finished. Looks like that's not going to happen, so
6946 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006947 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006948 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6949 r.resultExtras, r.resultAbort, true);
6950 reschedule = true;
6951 }
6952 r = mPendingBroadcast;
6953 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006954 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006955 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006956 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006957 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6958 r.resultExtras, r.resultAbort, true);
6959 reschedule = true;
6960 }
6961 if (reschedule) {
6962 scheduleBroadcastsLocked();
6963 }
6964 }
6965
Dan Egnor60d87622009-12-16 16:32:58 -08006966 /**
6967 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6968 * The application process will exit immediately after this call returns.
6969 * @param app object of the crashing app, null for the system server
6970 * @param crashInfo describing the exception
6971 */
6972 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006973 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08006974
6975 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6976 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006977 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006978 crashInfo.exceptionClassName,
6979 crashInfo.exceptionMessage,
6980 crashInfo.throwFileName,
6981 crashInfo.throwLineNumber);
6982
Dan Egnor42471dd2010-01-07 17:25:22 -08006983 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006984
6985 crashApplication(r, crashInfo);
6986 }
6987
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006988 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006989 IBinder app,
6990 int violationMask,
6991 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006992 ProcessRecord r = findAppProcess(app, "StrictMode");
6993 if (r == null) {
6994 return;
6995 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006996
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006997 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006998 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006999 boolean logIt = true;
7000 synchronized (mAlreadyLoggedViolatedStacks) {
7001 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
7002 logIt = false;
7003 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007004 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007005 // the relative pain numbers, without logging all
7006 // the stack traces repeatedly. We'd want to do
7007 // likewise in the client code, which also does
7008 // dup suppression, before the Binder call.
7009 } else {
7010 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
7011 mAlreadyLoggedViolatedStacks.clear();
7012 }
7013 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
7014 }
7015 }
7016 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007017 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007018 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007019 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007020
7021 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
7022 AppErrorResult result = new AppErrorResult();
7023 synchronized (this) {
7024 final long origId = Binder.clearCallingIdentity();
7025
7026 Message msg = Message.obtain();
7027 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7028 HashMap<String, Object> data = new HashMap<String, Object>();
7029 data.put("result", result);
7030 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007031 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007032 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007033 msg.obj = data;
7034 mHandler.sendMessage(msg);
7035
7036 Binder.restoreCallingIdentity(origId);
7037 }
7038 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007039 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007040 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007041 }
7042
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007043 // Depending on the policy in effect, there could be a bunch of
7044 // these in quick succession so we try to batch these together to
7045 // minimize disk writes, number of dropbox entries, and maximize
7046 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007047 private void logStrictModeViolationToDropBox(
7048 ProcessRecord process,
7049 StrictMode.ViolationInfo info) {
7050 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007051 return;
7052 }
7053 final boolean isSystemApp = process == null ||
7054 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7055 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
7056 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7057 final DropBoxManager dbox = (DropBoxManager)
7058 mContext.getSystemService(Context.DROPBOX_SERVICE);
7059
7060 // Exit early if the dropbox isn't configured to accept this report type.
7061 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7062
7063 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007064 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007065 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7066 synchronized (sb) {
7067 bufferWasEmpty = sb.length() == 0;
7068 appendDropBoxProcessHeaders(process, sb);
7069 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7070 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007071 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7072 if (info.violationNumThisLoop != 0) {
7073 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7074 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007075 if (info.numAnimationsRunning != 0) {
7076 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7077 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007078 if (info.broadcastIntentAction != null) {
7079 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7080 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007081 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007082 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007083 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007084 if (info.numInstances != -1) {
7085 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7086 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007087 if (info.tags != null) {
7088 for (String tag : info.tags) {
7089 sb.append("Span-Tag: ").append(tag).append("\n");
7090 }
7091 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007092 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007093 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7094 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007095 }
7096 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007097
7098 // Only buffer up to ~64k. Various logging bits truncate
7099 // things at 128k.
7100 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007101 }
7102
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007103 // Flush immediately if the buffer's grown too large, or this
7104 // is a non-system app. Non-system apps are isolated with a
7105 // different tag & policy and not batched.
7106 //
7107 // Batching is useful during internal testing with
7108 // StrictMode settings turned up high. Without batching,
7109 // thousands of separate files could be created on boot.
7110 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007111 new Thread("Error dump: " + dropboxTag) {
7112 @Override
7113 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007114 String report;
7115 synchronized (sb) {
7116 report = sb.toString();
7117 sb.delete(0, sb.length());
7118 sb.trimToSize();
7119 }
7120 if (report.length() != 0) {
7121 dbox.addText(dropboxTag, report);
7122 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007123 }
7124 }.start();
7125 return;
7126 }
7127
7128 // System app batching:
7129 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007130 // An existing dropbox-writing thread is outstanding, so
7131 // we don't need to start it up. The existing thread will
7132 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007133 return;
7134 }
7135
7136 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7137 // (After this point, we shouldn't access AMS internal data structures.)
7138 new Thread("Error dump: " + dropboxTag) {
7139 @Override
7140 public void run() {
7141 // 5 second sleep to let stacks arrive and be batched together
7142 try {
7143 Thread.sleep(5000); // 5 seconds
7144 } catch (InterruptedException e) {}
7145
7146 String errorReport;
7147 synchronized (mStrictModeBuffer) {
7148 errorReport = mStrictModeBuffer.toString();
7149 if (errorReport.length() == 0) {
7150 return;
7151 }
7152 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7153 mStrictModeBuffer.trimToSize();
7154 }
7155 dbox.addText(dropboxTag, errorReport);
7156 }
7157 }.start();
7158 }
7159
Dan Egnor60d87622009-12-16 16:32:58 -08007160 /**
7161 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7162 * @param app object of the crashing app, null for the system server
7163 * @param tag reported by the caller
7164 * @param crashInfo describing the context of the error
7165 * @return true if the process should exit immediately (WTF is fatal)
7166 */
7167 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007168 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007169 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007170
7171 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7172 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007173 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007174 tag, crashInfo.exceptionMessage);
7175
Dan Egnor42471dd2010-01-07 17:25:22 -08007176 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007177
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007178 if (r != null && r.pid != Process.myPid() &&
7179 Settings.Secure.getInt(mContext.getContentResolver(),
7180 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007181 crashApplication(r, crashInfo);
7182 return true;
7183 } else {
7184 return false;
7185 }
7186 }
7187
7188 /**
7189 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7190 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7191 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007192 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007193 if (app == null) {
7194 return null;
7195 }
7196
7197 synchronized (this) {
7198 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7199 final int NA = apps.size();
7200 for (int ia=0; ia<NA; ia++) {
7201 ProcessRecord p = apps.valueAt(ia);
7202 if (p.thread != null && p.thread.asBinder() == app) {
7203 return p;
7204 }
7205 }
7206 }
7207
Dianne Hackborncb44d962011-03-10 17:02:27 -08007208 Slog.w(TAG, "Can't find mystery application for " + reason
7209 + " from pid=" + Binder.getCallingPid()
7210 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007211 return null;
7212 }
7213 }
7214
7215 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007216 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7217 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007218 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007219 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007220 // Watchdog thread ends up invoking this function (with
7221 // a null ProcessRecord) to add the stack file to dropbox.
7222 // Do not acquire a lock on this (am) in such cases, as it
7223 // could cause a potential deadlock, if and when watchdog
7224 // is invoked due to unavailability of lock on am and it
7225 // would prevent watchdog from killing system_server.
7226 if (process == null) {
7227 sb.append("Process: system_server\n");
7228 return;
7229 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007230 // Note: ProcessRecord 'process' is guarded by the service
7231 // instance. (notably process.pkgList, which could otherwise change
7232 // concurrently during execution of this method)
7233 synchronized (this) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007234 if (process.pid == MY_PID) {
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007235 sb.append("Process: system_server\n");
7236 } else {
7237 sb.append("Process: ").append(process.processName).append("\n");
7238 }
Dan Egnora455d192010-03-12 08:52:28 -08007239 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007240 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007241 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7242 for (String pkg : process.pkgList) {
7243 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007244 try {
Dan Egnora455d192010-03-12 08:52:28 -08007245 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7246 if (pi != null) {
7247 sb.append(" v").append(pi.versionCode);
7248 if (pi.versionName != null) {
7249 sb.append(" (").append(pi.versionName).append(")");
7250 }
7251 }
7252 } catch (RemoteException e) {
7253 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007254 }
Dan Egnora455d192010-03-12 08:52:28 -08007255 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007256 }
Dan Egnora455d192010-03-12 08:52:28 -08007257 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007258 }
7259
7260 private static String processClass(ProcessRecord process) {
7261 if (process == null || process.pid == MY_PID) {
7262 return "system_server";
7263 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7264 return "system_app";
7265 } else {
7266 return "data_app";
7267 }
7268 }
7269
7270 /**
7271 * Write a description of an error (crash, WTF, ANR) to the drop box.
7272 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7273 * @param process which caused the error, null means the system server
7274 * @param activity which triggered the error, null if unknown
7275 * @param parent activity related to the error, null if unknown
7276 * @param subject line related to the error, null if absent
7277 * @param report in long form describing the error, null if absent
7278 * @param logFile to include in the report, null if none
7279 * @param crashInfo giving an application stack trace, null if absent
7280 */
7281 public void addErrorToDropBox(String eventType,
7282 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7283 final String report, final File logFile,
7284 final ApplicationErrorReport.CrashInfo crashInfo) {
7285 // NOTE -- this must never acquire the ActivityManagerService lock,
7286 // otherwise the watchdog may be prevented from resetting the system.
7287
7288 final String dropboxTag = processClass(process) + "_" + eventType;
7289 final DropBoxManager dbox = (DropBoxManager)
7290 mContext.getSystemService(Context.DROPBOX_SERVICE);
7291
7292 // Exit early if the dropbox isn't configured to accept this report type.
7293 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7294
7295 final StringBuilder sb = new StringBuilder(1024);
7296 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007297 if (activity != null) {
7298 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7299 }
7300 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7301 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7302 }
7303 if (parent != null && parent != activity) {
7304 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7305 }
7306 if (subject != null) {
7307 sb.append("Subject: ").append(subject).append("\n");
7308 }
7309 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007310 if (Debug.isDebuggerConnected()) {
7311 sb.append("Debugger: Connected\n");
7312 }
Dan Egnora455d192010-03-12 08:52:28 -08007313 sb.append("\n");
7314
7315 // Do the rest in a worker thread to avoid blocking the caller on I/O
7316 // (After this point, we shouldn't access AMS internal data structures.)
7317 Thread worker = new Thread("Error dump: " + dropboxTag) {
7318 @Override
7319 public void run() {
7320 if (report != null) {
7321 sb.append(report);
7322 }
7323 if (logFile != null) {
7324 try {
7325 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7326 } catch (IOException e) {
7327 Slog.e(TAG, "Error reading " + logFile, e);
7328 }
7329 }
7330 if (crashInfo != null && crashInfo.stackTrace != null) {
7331 sb.append(crashInfo.stackTrace);
7332 }
7333
7334 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7335 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7336 if (lines > 0) {
7337 sb.append("\n");
7338
7339 // Merge several logcat streams, and take the last N lines
7340 InputStreamReader input = null;
7341 try {
7342 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7343 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7344 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7345
7346 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7347 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7348 input = new InputStreamReader(logcat.getInputStream());
7349
7350 int num;
7351 char[] buf = new char[8192];
7352 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7353 } catch (IOException e) {
7354 Slog.e(TAG, "Error running logcat", e);
7355 } finally {
7356 if (input != null) try { input.close(); } catch (IOException e) {}
7357 }
7358 }
7359
7360 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007361 }
Dan Egnora455d192010-03-12 08:52:28 -08007362 };
7363
7364 if (process == null || process.pid == MY_PID) {
7365 worker.run(); // We may be about to die -- need to run this synchronously
7366 } else {
7367 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007368 }
7369 }
7370
7371 /**
7372 * Bring up the "unexpected error" dialog box for a crashing app.
7373 * Deal with edge cases (intercepts from instrumented applications,
7374 * ActivityController, error intent receivers, that sort of thing).
7375 * @param r the application crashing
7376 * @param crashInfo describing the failure
7377 */
7378 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007379 long timeMillis = System.currentTimeMillis();
7380 String shortMsg = crashInfo.exceptionClassName;
7381 String longMsg = crashInfo.exceptionMessage;
7382 String stackTrace = crashInfo.stackTrace;
7383 if (shortMsg != null && longMsg != null) {
7384 longMsg = shortMsg + ": " + longMsg;
7385 } else if (shortMsg != null) {
7386 longMsg = shortMsg;
7387 }
7388
Dan Egnor60d87622009-12-16 16:32:58 -08007389 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007391 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007392 try {
7393 String name = r != null ? r.processName : null;
7394 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007395 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007396 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007397 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398 + " at watcher's request");
7399 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007400 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 }
7402 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007403 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007404 }
7405 }
7406
7407 final long origId = Binder.clearCallingIdentity();
7408
7409 // If this process is running instrumentation, finish it.
7410 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007411 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007412 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007413 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7414 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415 Bundle info = new Bundle();
7416 info.putString("shortMsg", shortMsg);
7417 info.putString("longMsg", longMsg);
7418 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7419 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007420 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007421 }
7422
Dan Egnor60d87622009-12-16 16:32:58 -08007423 // If we can't identify the process or it's already exceeded its crash quota,
7424 // quit right away without showing a crash dialog.
7425 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007426 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007427 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007428 }
7429
7430 Message msg = Message.obtain();
7431 msg.what = SHOW_ERROR_MSG;
7432 HashMap data = new HashMap();
7433 data.put("result", result);
7434 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007435 msg.obj = data;
7436 mHandler.sendMessage(msg);
7437
7438 Binder.restoreCallingIdentity(origId);
7439 }
7440
7441 int res = result.get();
7442
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007443 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007444 synchronized (this) {
7445 if (r != null) {
7446 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7447 SystemClock.uptimeMillis());
7448 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007449 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007450 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007451 }
7452 }
7453
7454 if (appErrorIntent != null) {
7455 try {
7456 mContext.startActivity(appErrorIntent);
7457 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007458 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007462
7463 Intent createAppErrorIntentLocked(ProcessRecord r,
7464 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7465 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007466 if (report == null) {
7467 return null;
7468 }
7469 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7470 result.setComponent(r.errorReportReceiver);
7471 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7472 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7473 return result;
7474 }
7475
Dan Egnorb7f03672009-12-09 16:22:32 -08007476 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7477 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007478 if (r.errorReportReceiver == null) {
7479 return null;
7480 }
7481
7482 if (!r.crashing && !r.notResponding) {
7483 return null;
7484 }
7485
Dan Egnorb7f03672009-12-09 16:22:32 -08007486 ApplicationErrorReport report = new ApplicationErrorReport();
7487 report.packageName = r.info.packageName;
7488 report.installerPackageName = r.errorReportReceiver.getPackageName();
7489 report.processName = r.processName;
7490 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007491 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007492
Dan Egnorb7f03672009-12-09 16:22:32 -08007493 if (r.crashing) {
7494 report.type = ApplicationErrorReport.TYPE_CRASH;
7495 report.crashInfo = crashInfo;
7496 } else if (r.notResponding) {
7497 report.type = ApplicationErrorReport.TYPE_ANR;
7498 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007499
Dan Egnorb7f03672009-12-09 16:22:32 -08007500 report.anrInfo.activity = r.notRespondingReport.tag;
7501 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7502 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007503 }
7504
Dan Egnorb7f03672009-12-09 16:22:32 -08007505 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007506 }
7507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007508 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7509 // assume our apps are happy - lazy create the list
7510 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7511
7512 synchronized (this) {
7513
7514 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007515 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7516 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007517 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7518 // This one's in trouble, so we'll generate a report for it
7519 // crashes are higher priority (in case there's a crash *and* an anr)
7520 ActivityManager.ProcessErrorStateInfo report = null;
7521 if (app.crashing) {
7522 report = app.crashingReport;
7523 } else if (app.notResponding) {
7524 report = app.notRespondingReport;
7525 }
7526
7527 if (report != null) {
7528 if (errList == null) {
7529 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7530 }
7531 errList.add(report);
7532 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007533 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007534 " crashing = " + app.crashing +
7535 " notResponding = " + app.notResponding);
7536 }
7537 }
7538 }
7539 }
7540
7541 return errList;
7542 }
7543
7544 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7545 // Lazy instantiation of list
7546 List<ActivityManager.RunningAppProcessInfo> runList = null;
7547 synchronized (this) {
7548 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007549 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7550 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7552 // Generate process state info for running application
7553 ActivityManager.RunningAppProcessInfo currApp =
7554 new ActivityManager.RunningAppProcessInfo(app.processName,
7555 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007556 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007557 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007558 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007559 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007560 if (app.persistent) {
7561 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007563 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007564 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007565 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7566 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7567 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007568 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7569 } else if (adj >= HOME_APP_ADJ) {
7570 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7571 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007572 } else if (adj >= SECONDARY_SERVER_ADJ) {
7573 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007574 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007575 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007576 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7577 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007578 } else if (adj >= VISIBLE_APP_ADJ) {
7579 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7580 } else {
7581 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7582 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007583 currApp.importanceReasonCode = app.adjTypeCode;
7584 if (app.adjSource instanceof ProcessRecord) {
7585 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007586 } else if (app.adjSource instanceof ActivityRecord) {
7587 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007588 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7589 }
7590 if (app.adjTarget instanceof ComponentName) {
7591 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7592 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007593 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007594 // + " lru=" + currApp.lru);
7595 if (runList == null) {
7596 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7597 }
7598 runList.add(currApp);
7599 }
7600 }
7601 }
7602 return runList;
7603 }
7604
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007605 public List<ApplicationInfo> getRunningExternalApplications() {
7606 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7607 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7608 if (runningApps != null && runningApps.size() > 0) {
7609 Set<String> extList = new HashSet<String>();
7610 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7611 if (app.pkgList != null) {
7612 for (String pkg : app.pkgList) {
7613 extList.add(pkg);
7614 }
7615 }
7616 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007617 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007618 for (String pkg : extList) {
7619 try {
7620 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7621 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7622 retList.add(info);
7623 }
7624 } catch (RemoteException e) {
7625 }
7626 }
7627 }
7628 return retList;
7629 }
7630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007631 @Override
7632 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007633 if (checkCallingPermission(android.Manifest.permission.DUMP)
7634 != PackageManager.PERMISSION_GRANTED) {
7635 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7636 + Binder.getCallingPid()
7637 + ", uid=" + Binder.getCallingUid()
7638 + " without permission "
7639 + android.Manifest.permission.DUMP);
7640 return;
7641 }
7642
7643 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007644 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007645
7646 int opti = 0;
7647 while (opti < args.length) {
7648 String opt = args[opti];
7649 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7650 break;
7651 }
7652 opti++;
7653 if ("-a".equals(opt)) {
7654 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007655 } else if ("-c".equals(opt)) {
7656 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007657 } else if ("-h".equals(opt)) {
7658 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007659 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007660 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007661 pw.println(" a[ctivities]: activity stack state");
7662 pw.println(" b[roadcasts]: broadcast state");
7663 pw.println(" i[ntents]: pending intent state");
7664 pw.println(" p[rocesses]: process state");
7665 pw.println(" o[om]: out of memory management");
7666 pw.println(" prov[iders]: content provider state");
7667 pw.println(" s[ervices]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007668 pw.println(" service [COMP_SPEC]: service client-side state");
7669 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
7670 pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),");
7671 pw.println(" a partial substring in a component name, an");
7672 pw.println(" ActivityRecord hex object identifier, or");
Dianne Hackbornf9302322011-06-14 18:36:14 -07007673 pw.println(" \"all\" for all objects, or");
7674 pw.println(" \"top\" for the top activity.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007675 pw.println(" -a: include all available server state.");
7676 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007677 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007678 } else {
7679 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007680 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007681 }
7682
7683 // Is the caller requesting to dump a particular piece of data?
7684 if (opti < args.length) {
7685 String cmd = args[opti];
7686 opti++;
7687 if ("activities".equals(cmd) || "a".equals(cmd)) {
7688 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007689 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007691 return;
7692 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7693 synchronized (this) {
7694 dumpBroadcastsLocked(fd, pw, args, opti, true);
7695 }
7696 return;
7697 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7698 synchronized (this) {
7699 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7700 }
7701 return;
7702 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7703 synchronized (this) {
7704 dumpProcessesLocked(fd, pw, args, opti, true);
7705 }
7706 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007707 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7708 synchronized (this) {
7709 dumpOomLocked(fd, pw, args, opti, true);
7710 }
7711 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007712 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7713 synchronized (this) {
7714 dumpProvidersLocked(fd, pw, args, opti, true);
7715 }
7716 return;
7717 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007718 String[] newArgs;
7719 String name;
7720 if (opti >= args.length) {
7721 name = null;
7722 newArgs = EMPTY_STRING_ARRAY;
7723 } else {
7724 name = args[opti];
7725 opti++;
7726 newArgs = new String[args.length - opti];
7727 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7728 }
7729 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7730 pw.println("No services match: " + name);
7731 pw.println("Use -h for help.");
7732 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007733 return;
7734 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7735 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007736 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007737 }
7738 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007739 } else {
7740 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007741 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7742 pw.println("Bad activity command, or no activities match: " + cmd);
7743 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007744 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007745 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007746 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007747 }
7748
7749 // No piece of data specified, dump everything.
7750 synchronized (this) {
7751 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007752 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007753 if (needSep) {
7754 pw.println(" ");
7755 }
7756 if (dumpAll) {
7757 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007758 }
7759 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7760 if (needSep) {
7761 pw.println(" ");
7762 }
7763 if (dumpAll) {
7764 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007765 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007766 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007767 if (needSep) {
7768 pw.println(" ");
7769 }
7770 if (dumpAll) {
7771 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007772 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007773 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007774 if (needSep) {
7775 pw.println(" ");
7776 }
7777 if (dumpAll) {
7778 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007779 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007780 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007781 if (needSep) {
7782 pw.println(" ");
7783 }
7784 if (dumpAll) {
7785 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007786 }
7787 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7788 }
7789 }
7790
7791 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007792 int opti, boolean dumpAll, boolean dumpClient) {
7793 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7794 pw.println(" Main stack:");
7795 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007796 pw.println(" ");
7797 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007798 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007799 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007801 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007802 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7803 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007804 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007805 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007806 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007807 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007808 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7809 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007810 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007811 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7812 pw.println(" ");
7813 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007814 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7815 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007816 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007817 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007818 pw.println(" ");
7819 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007820 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7821 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007824 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007825 if (mMainStack.mPausingActivity != null) {
7826 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7827 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007828 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007829 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007830 if (dumpAll) {
7831 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7832 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
7833 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007834
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007835 if (mRecentTasks.size() > 0) {
7836 pw.println();
7837 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007838
7839 final int N = mRecentTasks.size();
7840 for (int i=0; i<N; i++) {
7841 TaskRecord tr = mRecentTasks.get(i);
7842 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7843 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007844 if (dumpAll) {
7845 mRecentTasks.get(i).dump(pw, " ");
7846 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007847 }
7848 }
7849
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007850 if (dumpAll) {
7851 pw.println(" ");
7852 pw.println(" mCurTask: " + mCurTask);
7853 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007854
7855 return true;
7856 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007857
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007858 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7859 int opti, boolean dumpAll) {
7860 boolean needSep = false;
7861 int numPers = 0;
7862
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007863 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7864
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007865 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007866 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7867 final int NA = procs.size();
7868 for (int ia=0; ia<NA; ia++) {
7869 if (!needSep) {
7870 pw.println(" All known processes:");
7871 needSep = true;
7872 }
7873 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007874 pw.print(r.persistent ? " *PERS*" : " *APP*");
7875 pw.print(" UID "); pw.print(procs.keyAt(ia));
7876 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007877 r.dump(pw, " ");
7878 if (r.persistent) {
7879 numPers++;
7880 }
7881 }
7882 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007883 }
7884
7885 if (mLruProcesses.size() > 0) {
7886 if (needSep) pw.println(" ");
7887 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007888 pw.println(" Process LRU list (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007889 dumpProcessOomList(pw, this, mLruProcesses, " ",
7890 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007891 needSep = true;
7892 }
7893
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007894 if (dumpAll) {
7895 synchronized (mPidsSelfLocked) {
7896 if (mPidsSelfLocked.size() > 0) {
7897 if (needSep) pw.println(" ");
7898 needSep = true;
7899 pw.println(" PID mappings:");
7900 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7901 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7902 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
7903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007904 }
7905 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007906 }
7907
7908 if (mForegroundProcesses.size() > 0) {
7909 if (needSep) pw.println(" ");
7910 needSep = true;
7911 pw.println(" Foreground Processes:");
7912 for (int i=0; i<mForegroundProcesses.size(); i++) {
7913 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7914 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007916 }
7917
7918 if (mPersistentStartingProcesses.size() > 0) {
7919 if (needSep) pw.println(" ");
7920 needSep = true;
7921 pw.println(" Persisent processes that are starting:");
7922 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007923 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007924 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007925
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007926 if (mStartingProcesses.size() > 0) {
7927 if (needSep) pw.println(" ");
7928 needSep = true;
7929 pw.println(" Processes that are starting:");
7930 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007931 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007933
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007934 if (mRemovedProcesses.size() > 0) {
7935 if (needSep) pw.println(" ");
7936 needSep = true;
7937 pw.println(" Processes that are being removed:");
7938 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007939 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007940 }
7941
7942 if (mProcessesOnHold.size() > 0) {
7943 if (needSep) pw.println(" ");
7944 needSep = true;
7945 pw.println(" Processes that are on old until the system is ready:");
7946 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007947 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007948 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007949
Dianne Hackborn287952c2010-09-22 22:34:31 -07007950 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007951
7952 if (mProcessCrashTimes.getMap().size() > 0) {
7953 if (needSep) pw.println(" ");
7954 needSep = true;
7955 pw.println(" Time since processes crashed:");
7956 long now = SystemClock.uptimeMillis();
7957 for (Map.Entry<String, SparseArray<Long>> procs
7958 : mProcessCrashTimes.getMap().entrySet()) {
7959 SparseArray<Long> uids = procs.getValue();
7960 final int N = uids.size();
7961 for (int i=0; i<N; i++) {
7962 pw.print(" Process "); pw.print(procs.getKey());
7963 pw.print(" uid "); pw.print(uids.keyAt(i));
7964 pw.print(": last crashed ");
7965 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007966 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007967 }
7968 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007970
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007971 if (mBadProcesses.getMap().size() > 0) {
7972 if (needSep) pw.println(" ");
7973 needSep = true;
7974 pw.println(" Bad processes:");
7975 for (Map.Entry<String, SparseArray<Long>> procs
7976 : mBadProcesses.getMap().entrySet()) {
7977 SparseArray<Long> uids = procs.getValue();
7978 final int N = uids.size();
7979 for (int i=0; i<N; i++) {
7980 pw.print(" Bad process "); pw.print(procs.getKey());
7981 pw.print(" uid "); pw.print(uids.keyAt(i));
7982 pw.print(": crashed at time ");
7983 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007984 }
7985 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007987
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007988 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007989 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007990 if (mHeavyWeightProcess != null) {
7991 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7992 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007993 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007994 if (dumpAll) {
7995 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07007996 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07007997 pw.println(" mScreenCompatPackages:");
7998 for (Map.Entry<String, Integer> entry
7999 : mCompatModePackages.getPackages().entrySet()) {
8000 String pkg = entry.getKey();
8001 int mode = entry.getValue();
8002 pw.print(" "); pw.print(pkg); pw.print(": ");
8003 pw.print(mode); pw.println();
8004 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07008005 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008006 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008007 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
8008 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
8009 || mOrigWaitForDebugger) {
8010 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
8011 + " mDebugTransient=" + mDebugTransient
8012 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
8013 }
8014 if (mAlwaysFinishActivities || mController != null) {
8015 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
8016 + " mController=" + mController);
8017 }
8018 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008019 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008020 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008021 + " mProcessesReady=" + mProcessesReady
8022 + " mSystemReady=" + mSystemReady);
8023 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 + " mBooted=" + mBooted
8025 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008026 pw.print(" mLastPowerCheckRealtime=");
8027 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
8028 pw.println("");
8029 pw.print(" mLastPowerCheckUptime=");
8030 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
8031 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008032 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8033 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008034 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008035 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008036
8037 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008038 }
8039
Dianne Hackborn287952c2010-09-22 22:34:31 -07008040 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
8041 int opti, boolean needSep, boolean dumpAll) {
8042 if (mProcessesToGc.size() > 0) {
8043 if (needSep) pw.println(" ");
8044 needSep = true;
8045 pw.println(" Processes that are waiting to GC:");
8046 long now = SystemClock.uptimeMillis();
8047 for (int i=0; i<mProcessesToGc.size(); i++) {
8048 ProcessRecord proc = mProcessesToGc.get(i);
8049 pw.print(" Process "); pw.println(proc);
8050 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8051 pw.print(", last gced=");
8052 pw.print(now-proc.lastRequestedGc);
8053 pw.print(" ms ago, last lowMem=");
8054 pw.print(now-proc.lastLowMemory);
8055 pw.println(" ms ago");
8056
8057 }
8058 }
8059 return needSep;
8060 }
8061
8062 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8063 int opti, boolean dumpAll) {
8064 boolean needSep = false;
8065
8066 if (mLruProcesses.size() > 0) {
8067 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
8068
8069 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
8070 @Override
8071 public int compare(ProcessRecord object1, ProcessRecord object2) {
8072 if (object1.setAdj != object2.setAdj) {
8073 return object1.setAdj > object2.setAdj ? -1 : 1;
8074 }
8075 if (object1.setSchedGroup != object2.setSchedGroup) {
8076 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
8077 }
8078 if (object1.keeping != object2.keeping) {
8079 return object1.keeping ? -1 : 1;
8080 }
8081 if (object1.pid != object2.pid) {
8082 return object1.pid > object2.pid ? -1 : 1;
8083 }
8084 return 0;
8085 }
8086 };
8087
8088 Collections.sort(procs, comparator);
8089
8090 if (needSep) pw.println(" ");
8091 needSep = true;
8092 pw.println(" Process OOM control:");
8093 dumpProcessOomList(pw, this, procs, " ",
8094 "Proc", "PERS", true);
8095 needSep = true;
8096 }
8097
8098 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
8099
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008100 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008101 pw.println(" mHomeProcess: " + mHomeProcess);
8102 if (mHeavyWeightProcess != null) {
8103 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8104 }
8105
8106 return true;
8107 }
8108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008109 /**
8110 * There are three ways to call this:
8111 * - no service specified: dump all the services
8112 * - a flattened component name that matched an existing service was specified as the
8113 * first arg: dump that one service
8114 * - the first arg isn't the flattened component name of an existing service:
8115 * dump all services whose component contains the first arg as a substring
8116 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008117 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8118 int opti, boolean dumpAll) {
8119 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008120
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008121 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008122 synchronized (this) {
8123 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008124 services.add(r1);
8125 }
8126 }
8127 } else {
8128 ComponentName componentName = name != null
8129 ? ComponentName.unflattenFromString(name) : null;
8130 int objectId = 0;
8131 if (componentName == null) {
8132 // Not a '/' separated full component name; maybe an object ID?
8133 try {
8134 objectId = Integer.parseInt(name, 16);
8135 name = null;
8136 componentName = null;
8137 } catch (RuntimeException e) {
8138 }
8139 }
8140
8141 synchronized (this) {
8142 for (ServiceRecord r1 : mServices.values()) {
8143 if (componentName != null) {
8144 if (r1.name.equals(componentName)) {
8145 services.add(r1);
8146 }
8147 } else if (name != null) {
8148 if (r1.name.flattenToString().contains(name)) {
8149 services.add(r1);
8150 }
8151 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008152 services.add(r1);
8153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008154 }
8155 }
8156 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008157
8158 if (services.size() <= 0) {
8159 return false;
8160 }
8161
8162 boolean needSep = false;
8163 for (int i=0; i<services.size(); i++) {
8164 if (needSep) {
8165 pw.println();
8166 }
8167 needSep = true;
8168 dumpService("", fd, pw, services.get(i), args, dumpAll);
8169 }
8170 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008171 }
8172
8173 /**
8174 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8175 * there is a thread associated with the service.
8176 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008177 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8178 final ServiceRecord r, String[] args, boolean dumpAll) {
8179 String innerPrefix = prefix + " ";
8180 synchronized (this) {
8181 pw.print(prefix); pw.print("SERVICE ");
8182 pw.print(r.shortName); pw.print(" ");
8183 pw.print(Integer.toHexString(System.identityHashCode(r)));
8184 pw.print(" pid=");
8185 if (r.app != null) pw.println(r.app.pid);
8186 else pw.println("(not running)");
8187 if (dumpAll) {
8188 r.dump(pw, innerPrefix);
8189 }
8190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008191 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008192 pw.print(prefix); pw.println(" Client:");
8193 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008194 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008195 TransferPipe tp = new TransferPipe();
8196 try {
8197 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8198 tp.setBufferPrefix(prefix + " ");
8199 tp.go(fd);
8200 } finally {
8201 tp.kill();
8202 }
8203 } catch (IOException e) {
8204 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008205 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008206 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008207 }
8208 }
8209 }
8210
Dianne Hackborn625ac272010-09-17 18:29:22 -07008211 /**
8212 * There are three things that cmd can be:
8213 * - a flattened component name that matched an existing activity
8214 * - the cmd arg isn't the flattened component name of an existing activity:
8215 * dump all activity whose component contains the cmd as a substring
8216 * - A hex number of the ActivityRecord object instance.
8217 */
8218 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8219 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008220 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008221
8222 if ("all".equals(name)) {
8223 synchronized (this) {
8224 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008225 activities.add(r1);
8226 }
8227 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07008228 } else if ("top".equals(name)) {
8229 synchronized (this) {
8230 final int N = mMainStack.mHistory.size();
8231 if (N > 0) {
8232 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
8233 }
8234 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008235 } else {
8236 ComponentName componentName = ComponentName.unflattenFromString(name);
8237 int objectId = 0;
8238 if (componentName == null) {
8239 // Not a '/' separated full component name; maybe an object ID?
8240 try {
8241 objectId = Integer.parseInt(name, 16);
8242 name = null;
8243 componentName = null;
8244 } catch (RuntimeException e) {
8245 }
8246 }
8247
8248 synchronized (this) {
8249 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
8250 if (componentName != null) {
8251 if (r1.intent.getComponent().equals(componentName)) {
8252 activities.add(r1);
8253 }
8254 } else if (name != null) {
8255 if (r1.intent.getComponent().flattenToString().contains(name)) {
8256 activities.add(r1);
8257 }
8258 } else if (System.identityHashCode(r1) == objectId) {
8259 activities.add(r1);
8260 }
8261 }
8262 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008263 }
8264
8265 if (activities.size() <= 0) {
8266 return false;
8267 }
8268
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008269 String[] newArgs = new String[args.length - opti];
8270 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8271
Dianne Hackborn30d71892010-12-11 10:37:55 -08008272 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008273 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008274 for (int i=activities.size()-1; i>=0; i--) {
8275 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008276 if (needSep) {
8277 pw.println();
8278 }
8279 needSep = true;
8280 synchronized (this) {
8281 if (lastTask != r.task) {
8282 lastTask = r.task;
8283 pw.print("TASK "); pw.print(lastTask.affinity);
8284 pw.print(" id="); pw.println(lastTask.taskId);
8285 if (dumpAll) {
8286 lastTask.dump(pw, " ");
8287 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008288 }
8289 }
8290 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008291 }
8292 return true;
8293 }
8294
8295 /**
8296 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8297 * there is a thread associated with the activity.
8298 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008299 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008300 final ActivityRecord r, String[] args, boolean dumpAll) {
8301 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008302 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008303 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8304 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8305 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008306 if (r.app != null) pw.println(r.app.pid);
8307 else pw.println("(not running)");
8308 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008309 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008310 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008311 }
8312 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008313 // flush anything that is already in the PrintWriter since the thread is going
8314 // to write to the file descriptor directly
8315 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008316 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008317 TransferPipe tp = new TransferPipe();
8318 try {
8319 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8320 innerPrefix, args);
8321 tp.go(fd);
8322 } finally {
8323 tp.kill();
8324 }
8325 } catch (IOException e) {
8326 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008327 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008328 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008329 }
8330 }
8331 }
8332
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008333 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8334 int opti, boolean dumpAll) {
8335 boolean needSep = false;
8336
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008337 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008338 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008339 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008340 pw.println(" Registered Receivers:");
8341 Iterator it = mRegisteredReceivers.values().iterator();
8342 while (it.hasNext()) {
8343 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008344 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345 r.dump(pw, " ");
8346 }
8347 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008348
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008349 pw.println();
8350 pw.println(" Receiver Resolver Table:");
8351 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008352 needSep = true;
8353 }
8354
8355 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8356 || mPendingBroadcast != null) {
8357 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008358 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008359 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008360 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008361 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8362 pw.println(" Broadcast #" + i + ":");
8363 mParallelBroadcasts.get(i).dump(pw, " ");
8364 }
8365 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008366 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008367 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008368 }
8369 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8370 pw.println(" Serialized Broadcast #" + i + ":");
8371 mOrderedBroadcasts.get(i).dump(pw, " ");
8372 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008373 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008374 pw.println(" Pending broadcast:");
8375 if (mPendingBroadcast != null) {
8376 mPendingBroadcast.dump(pw, " ");
8377 } else {
8378 pw.println(" (null)");
8379 }
8380 needSep = true;
8381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008382
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008383 if (needSep) {
8384 pw.println();
8385 }
8386 pw.println(" Historical broadcasts:");
8387 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8388 BroadcastRecord r = mBroadcastHistory[i];
8389 if (r == null) {
8390 break;
8391 }
8392 if (dumpAll) {
8393 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8394 r.dump(pw, " ");
8395 } else {
8396 if (i >= 50) {
8397 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008398 break;
8399 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008400 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008401 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008402 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008403 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008404
8405 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008406 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008407 pw.println(" Sticky broadcasts:");
8408 StringBuilder sb = new StringBuilder(128);
8409 for (Map.Entry<String, ArrayList<Intent>> ent
8410 : mStickyBroadcasts.entrySet()) {
8411 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008412 if (dumpAll) {
8413 pw.println(":");
8414 ArrayList<Intent> intents = ent.getValue();
8415 final int N = intents.size();
8416 for (int i=0; i<N; i++) {
8417 sb.setLength(0);
8418 sb.append(" Intent: ");
8419 intents.get(i).toShortString(sb, true, false);
8420 pw.println(sb.toString());
8421 Bundle bundle = intents.get(i).getExtras();
8422 if (bundle != null) {
8423 pw.print(" ");
8424 pw.println(bundle.toString());
8425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008426 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008427 } else {
8428 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008429 }
8430 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008431 needSep = true;
8432 }
8433
8434 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008435 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008436 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008437 pw.println(" mHandler:");
8438 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008439 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008440 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008441
8442 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443 }
8444
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008445 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008446 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008447 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008448
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008449 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8450 if (mServices.size() > 0) {
8451 pw.println(" Active services:");
8452 long nowReal = SystemClock.elapsedRealtime();
8453 Iterator<ServiceRecord> it = mServices.values().iterator();
8454 needSep = false;
8455 while (it.hasNext()) {
8456 ServiceRecord r = it.next();
8457 if (needSep) {
8458 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008459 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008460 pw.print(" * "); pw.println(r);
8461 if (dumpAll) {
8462 r.dump(pw, " ");
8463 needSep = true;
8464 } else {
8465 pw.print(" app="); pw.println(r.app);
8466 pw.print(" created=");
8467 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8468 pw.print(" started="); pw.print(r.startRequested);
8469 pw.print(" connections="); pw.println(r.connections.size());
8470 }
8471 if (dumpClient && r.app != null && r.app.thread != null) {
8472 pw.println(" Client:");
8473 pw.flush();
8474 try {
8475 TransferPipe tp = new TransferPipe();
8476 try {
8477 r.app.thread.dumpService(
8478 tp.getWriteFd().getFileDescriptor(), r, args);
8479 tp.setBufferPrefix(" ");
8480 // Short timeout, since blocking here can
8481 // deadlock with the application.
8482 tp.go(fd, 2000);
8483 } finally {
8484 tp.kill();
8485 }
8486 } catch (IOException e) {
8487 pw.println(" Failure while dumping the service: " + e);
8488 } catch (RemoteException e) {
8489 pw.println(" Got a RemoteException while dumping the service");
8490 }
8491 needSep = true;
8492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008493 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008494 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008496
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008497 if (mPendingServices.size() > 0) {
8498 if (needSep) pw.println(" ");
8499 pw.println(" Pending services:");
8500 for (int i=0; i<mPendingServices.size(); i++) {
8501 ServiceRecord r = mPendingServices.get(i);
8502 pw.print(" * Pending "); pw.println(r);
8503 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008504 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008505 needSep = true;
8506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008507
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008508 if (mRestartingServices.size() > 0) {
8509 if (needSep) pw.println(" ");
8510 pw.println(" Restarting services:");
8511 for (int i=0; i<mRestartingServices.size(); i++) {
8512 ServiceRecord r = mRestartingServices.get(i);
8513 pw.print(" * Restarting "); pw.println(r);
8514 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008516 needSep = true;
8517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008519 if (mStoppingServices.size() > 0) {
8520 if (needSep) pw.println(" ");
8521 pw.println(" Stopping services:");
8522 for (int i=0; i<mStoppingServices.size(); i++) {
8523 ServiceRecord r = mStoppingServices.get(i);
8524 pw.print(" * Stopping "); pw.println(r);
8525 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008526 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008527 needSep = true;
8528 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008529
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008530 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008531 if (mServiceConnections.size() > 0) {
8532 if (needSep) pw.println(" ");
8533 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008534 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008535 = mServiceConnections.values().iterator();
8536 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008537 ArrayList<ConnectionRecord> r = it.next();
8538 for (int i=0; i<r.size(); i++) {
8539 pw.print(" * "); pw.println(r.get(i));
8540 r.get(i).dump(pw, " ");
8541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008542 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008543 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008544 }
8545 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008546
8547 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008548 }
8549
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008550 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8551 int opti, boolean dumpAll) {
8552 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008553
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008554 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8555 if (mProvidersByClass.size() > 0) {
8556 if (needSep) pw.println(" ");
8557 pw.println(" Published content providers (by class):");
8558 Iterator<Map.Entry<String, ContentProviderRecord>> it
8559 = mProvidersByClass.entrySet().iterator();
8560 while (it.hasNext()) {
8561 Map.Entry<String, ContentProviderRecord> e = it.next();
8562 ContentProviderRecord r = e.getValue();
8563 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008564 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008565 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008566 } else {
8567 pw.print(" * "); pw.print(r.name.toShortString());
8568 if (r.app != null) {
8569 pw.println(":");
8570 pw.print(" "); pw.println(r.app);
8571 } else {
8572 pw.println();
8573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008575 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008576 needSep = true;
8577 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008578
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008579 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008580 if (mProvidersByName.size() > 0) {
8581 pw.println(" ");
8582 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008583 Iterator<Map.Entry<String, ContentProviderRecord>> it
8584 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008585 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008586 Map.Entry<String, ContentProviderRecord> e = it.next();
8587 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008588 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8589 pw.println(r);
8590 }
8591 needSep = true;
8592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008593 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008594
8595 if (mLaunchingProviders.size() > 0) {
8596 if (needSep) pw.println(" ");
8597 pw.println(" Launching content providers:");
8598 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8599 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8600 pw.println(mLaunchingProviders.get(i));
8601 }
8602 needSep = true;
8603 }
8604
8605 if (mGrantedUriPermissions.size() > 0) {
8606 pw.println();
8607 pw.println("Granted Uri Permissions:");
8608 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8609 int uid = mGrantedUriPermissions.keyAt(i);
8610 HashMap<Uri, UriPermission> perms
8611 = mGrantedUriPermissions.valueAt(i);
8612 pw.print(" * UID "); pw.print(uid);
8613 pw.println(" holds:");
8614 for (UriPermission perm : perms.values()) {
8615 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008616 if (dumpAll) {
8617 perm.dump(pw, " ");
8618 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008619 }
8620 }
8621 needSep = true;
8622 }
8623
8624 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008625 }
8626
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008627 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8628 int opti, boolean dumpAll) {
8629 boolean needSep = false;
8630
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008631 if (this.mIntentSenderRecords.size() > 0) {
8632 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8633 Iterator<WeakReference<PendingIntentRecord>> it
8634 = mIntentSenderRecords.values().iterator();
8635 while (it.hasNext()) {
8636 WeakReference<PendingIntentRecord> ref = it.next();
8637 PendingIntentRecord rec = ref != null ? ref.get(): null;
8638 needSep = true;
8639 if (rec != null) {
8640 pw.print(" * "); pw.println(rec);
8641 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008642 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008644 } else {
8645 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008646 }
8647 }
8648 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008649
8650 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008651 }
8652
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008653 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8654 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008655 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008656 boolean needNL = false;
8657 final String innerPrefix = prefix + " ";
8658 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008659 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008660 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008661 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008662 if (needNL) {
8663 pw.println(" ");
8664 needNL = false;
8665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008666 if (lastTask != r.task) {
8667 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008668 pw.print(prefix);
8669 pw.print(full ? "* " : " ");
8670 pw.println(lastTask);
8671 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008672 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008673 } else if (complete) {
8674 // Complete + brief == give a summary. Isn't that obvious?!?
8675 if (lastTask.intent != null) {
8676 pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
8677 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008679 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008680 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8681 pw.print(" #"); pw.print(i); pw.print(": ");
8682 pw.println(r);
8683 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008684 r.dump(pw, innerPrefix);
8685 } else if (complete) {
8686 // Complete + brief == give a summary. Isn't that obvious?!?
8687 pw.print(innerPrefix); pw.println(r.intent);
8688 if (r.app != null) {
8689 pw.print(innerPrefix); pw.println(r.app);
8690 }
8691 }
8692 if (client && r.app != null && r.app.thread != null) {
8693 // flush anything that is already in the PrintWriter since the thread is going
8694 // to write to the file descriptor directly
8695 pw.flush();
8696 try {
8697 TransferPipe tp = new TransferPipe();
8698 try {
8699 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8700 innerPrefix, args);
8701 // Short timeout, since blocking here can
8702 // deadlock with the application.
8703 tp.go(fd, 2000);
8704 } finally {
8705 tp.kill();
8706 }
8707 } catch (IOException e) {
8708 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8709 } catch (RemoteException e) {
8710 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8711 }
8712 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008714 }
8715 }
8716
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008717 private static String buildOomTag(String prefix, String space, int val, int base) {
8718 if (val == base) {
8719 if (space == null) return prefix;
8720 return prefix + " ";
8721 }
8722 return prefix + "+" + Integer.toString(val-base);
8723 }
8724
8725 private static final int dumpProcessList(PrintWriter pw,
8726 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008727 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008728 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008729 final int N = list.size()-1;
8730 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008731 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008732 pw.println(String.format("%s%s #%2d: %s",
8733 prefix, (r.persistent ? persistentLabel : normalLabel),
8734 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008735 if (r.persistent) {
8736 numPers++;
8737 }
8738 }
8739 return numPers;
8740 }
8741
Dianne Hackborn287952c2010-09-22 22:34:31 -07008742 private static final void dumpProcessOomList(PrintWriter pw,
8743 ActivityManagerService service, List<ProcessRecord> list,
8744 String prefix, String normalLabel, String persistentLabel,
8745 boolean inclDetails) {
8746
8747 final long curRealtime = SystemClock.elapsedRealtime();
8748 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8749 final long curUptime = SystemClock.uptimeMillis();
8750 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8751
8752 final int N = list.size()-1;
8753 for (int i=N; i>=0; i--) {
8754 ProcessRecord r = list.get(i);
8755 String oomAdj;
8756 if (r.setAdj >= EMPTY_APP_ADJ) {
8757 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8758 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8759 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8760 } else if (r.setAdj >= HOME_APP_ADJ) {
8761 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8762 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8763 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8764 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8765 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8766 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8767 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8768 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8769 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8770 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8771 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8772 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8773 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8774 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8775 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8776 } else if (r.setAdj >= SYSTEM_ADJ) {
8777 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8778 } else {
8779 oomAdj = Integer.toString(r.setAdj);
8780 }
8781 String schedGroup;
8782 switch (r.setSchedGroup) {
8783 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8784 schedGroup = "B";
8785 break;
8786 case Process.THREAD_GROUP_DEFAULT:
8787 schedGroup = "F";
8788 break;
8789 default:
8790 schedGroup = Integer.toString(r.setSchedGroup);
8791 break;
8792 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008793 String foreground;
8794 if (r.foregroundActivities) {
8795 foreground = "A";
8796 } else if (r.foregroundServices) {
8797 foreground = "S";
8798 } else {
8799 foreground = " ";
8800 }
8801 pw.println(String.format("%s%s #%2d: adj=%s/%s%s %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008802 prefix, (r.persistent ? persistentLabel : normalLabel),
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008803 N-i, oomAdj, schedGroup, foreground, r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07008804 if (r.adjSource != null || r.adjTarget != null) {
8805 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008806 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008807 if (r.adjTarget instanceof ComponentName) {
8808 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8809 } else if (r.adjTarget != null) {
8810 pw.print(r.adjTarget.toString());
8811 } else {
8812 pw.print("{null}");
8813 }
8814 pw.print("<=");
8815 if (r.adjSource instanceof ProcessRecord) {
8816 pw.print("Proc{");
8817 pw.print(((ProcessRecord)r.adjSource).toShortString());
8818 pw.println("}");
8819 } else if (r.adjSource != null) {
8820 pw.println(r.adjSource.toString());
8821 } else {
8822 pw.println("{null}");
8823 }
8824 }
8825 if (inclDetails) {
8826 pw.print(prefix);
8827 pw.print(" ");
8828 pw.print("oom: max="); pw.print(r.maxAdj);
8829 pw.print(" hidden="); pw.print(r.hiddenAdj);
8830 pw.print(" curRaw="); pw.print(r.curRawAdj);
8831 pw.print(" setRaw="); pw.print(r.setRawAdj);
8832 pw.print(" cur="); pw.print(r.curAdj);
8833 pw.print(" set="); pw.println(r.setAdj);
8834 pw.print(prefix);
8835 pw.print(" ");
8836 pw.print("keeping="); pw.print(r.keeping);
8837 pw.print(" hidden="); pw.print(r.hidden);
8838 pw.print(" empty="); pw.println(r.empty);
8839
8840 if (!r.keeping) {
8841 if (r.lastWakeTime != 0) {
8842 long wtime;
8843 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8844 synchronized (stats) {
8845 wtime = stats.getProcessWakeTime(r.info.uid,
8846 r.pid, curRealtime);
8847 }
8848 long timeUsed = wtime - r.lastWakeTime;
8849 pw.print(prefix);
8850 pw.print(" ");
8851 pw.print("keep awake over ");
8852 TimeUtils.formatDuration(realtimeSince, pw);
8853 pw.print(" used ");
8854 TimeUtils.formatDuration(timeUsed, pw);
8855 pw.print(" (");
8856 pw.print((timeUsed*100)/realtimeSince);
8857 pw.println("%)");
8858 }
8859 if (r.lastCpuTime != 0) {
8860 long timeUsed = r.curCpuTime - r.lastCpuTime;
8861 pw.print(prefix);
8862 pw.print(" ");
8863 pw.print("run cpu over ");
8864 TimeUtils.formatDuration(uptimeSince, pw);
8865 pw.print(" used ");
8866 TimeUtils.formatDuration(timeUsed, pw);
8867 pw.print(" (");
8868 pw.print((timeUsed*100)/uptimeSince);
8869 pw.println("%)");
8870 }
8871 }
8872 }
8873 }
8874 }
8875
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008876 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
8877 ArrayList<ProcessRecord> procs;
8878 synchronized (this) {
8879 if (args != null && args.length > 0
8880 && args[0].charAt(0) != '-') {
8881 procs = new ArrayList<ProcessRecord>();
8882 int pid = -1;
8883 try {
8884 pid = Integer.parseInt(args[0]);
8885 } catch (NumberFormatException e) {
8886
8887 }
8888 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8889 ProcessRecord proc = mLruProcesses.get(i);
8890 if (proc.pid == pid) {
8891 procs.add(proc);
8892 } else if (proc.processName.equals(args[0])) {
8893 procs.add(proc);
8894 }
8895 }
8896 if (procs.size() <= 0) {
8897 pw.println("No process found for: " + args[0]);
8898 return null;
8899 }
8900 } else {
8901 procs = new ArrayList<ProcessRecord>(mLruProcesses);
8902 }
8903 }
8904 return procs;
8905 }
8906
8907 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
8908 PrintWriter pw, String[] args) {
8909 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8910 if (procs == null) {
8911 return;
8912 }
8913
8914 long uptime = SystemClock.uptimeMillis();
8915 long realtime = SystemClock.elapsedRealtime();
8916 pw.println("Applications Graphics Acceleration Info:");
8917 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8918
8919 String callArgs[] = {"graphics"};
8920 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8921 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008922 if (r.thread != null) {
8923 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
8924 pw.flush();
8925 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008926 TransferPipe.goDump(r.thread.asBinder(), fd, callArgs);
8927 } catch (IOException e) {
8928 pw.println("Failure: " + e);
8929 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07008930 } catch (RemoteException e) {
8931 pw.println("Got RemoteException!");
8932 pw.flush();
8933 }
8934 }
8935 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07008936 }
8937
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008938 final void dumpApplicationMemoryUsage(FileDescriptor fd,
8939 PrintWriter pw, String prefix, String[] args) {
8940 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8941 if (procs == null) {
8942 return;
8943 }
8944
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008945 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008946 long uptime = SystemClock.uptimeMillis();
8947 long realtime = SystemClock.elapsedRealtime();
8948
8949 if (isCheckinRequest) {
8950 // short checkin version
8951 pw.println(uptime + "," + realtime);
8952 pw.flush();
8953 } else {
8954 pw.println("Applications Memory Usage (kB):");
8955 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8956 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008957 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8958 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008959 if (r.thread != null) {
8960 if (!isCheckinRequest) {
8961 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8962 pw.flush();
8963 }
8964 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008965 TransferPipe.goDump(r.thread.asBinder(), fd, args);
8966 } catch (IOException e) {
8967 pw.println("Failure: " + e);
8968 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008969 } catch (RemoteException e) {
8970 if (!isCheckinRequest) {
8971 pw.println("Got RemoteException!");
8972 pw.flush();
8973 }
8974 }
8975 }
8976 }
8977 }
8978
8979 /**
8980 * Searches array of arguments for the specified string
8981 * @param args array of argument strings
8982 * @param value value to search for
8983 * @return true if the value is contained in the array
8984 */
8985 private static boolean scanArgs(String[] args, String value) {
8986 if (args != null) {
8987 for (String arg : args) {
8988 if (value.equals(arg)) {
8989 return true;
8990 }
8991 }
8992 }
8993 return false;
8994 }
8995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008996 private final void killServicesLocked(ProcessRecord app,
8997 boolean allowRestart) {
8998 // Report disconnected services.
8999 if (false) {
9000 // XXX we are letting the client link to the service for
9001 // death notifications.
9002 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009003 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009004 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009005 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009006 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009007 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009008 = r.connections.values().iterator();
9009 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009010 ArrayList<ConnectionRecord> cl = jt.next();
9011 for (int i=0; i<cl.size(); i++) {
9012 ConnectionRecord c = cl.get(i);
9013 if (c.binding.client != app) {
9014 try {
9015 //c.conn.connected(r.className, null);
9016 } catch (Exception e) {
9017 // todo: this should be asynchronous!
9018 Slog.w(TAG, "Exception thrown disconnected servce "
9019 + r.shortName
9020 + " from app " + app.processName, e);
9021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009022 }
9023 }
9024 }
9025 }
9026 }
9027 }
9028 }
9029
9030 // Clean up any connections this application has to other services.
9031 if (app.connections.size() > 0) {
9032 Iterator<ConnectionRecord> it = app.connections.iterator();
9033 while (it.hasNext()) {
9034 ConnectionRecord r = it.next();
9035 removeConnectionLocked(r, app, null);
9036 }
9037 }
9038 app.connections.clear();
9039
9040 if (app.services.size() != 0) {
9041 // Any services running in the application need to be placed
9042 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009043 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009044 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009045 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009046 synchronized (sr.stats.getBatteryStats()) {
9047 sr.stats.stopLaunchedLocked();
9048 }
9049 sr.app = null;
9050 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009051 if (mStoppingServices.remove(sr)) {
9052 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
9053 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009054
9055 boolean hasClients = sr.bindings.size() > 0;
9056 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009057 Iterator<IntentBindRecord> bindings
9058 = sr.bindings.values().iterator();
9059 while (bindings.hasNext()) {
9060 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009061 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009062 + ": shouldUnbind=" + b.hasBound);
9063 b.binder = null;
9064 b.requested = b.received = b.hasBound = false;
9065 }
9066 }
9067
Dianne Hackborn070783f2010-12-29 16:46:28 -08009068 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
9069 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009070 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009071 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009072 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009073 sr.crashCount, sr.shortName, app.pid);
9074 bringDownServiceLocked(sr, true);
9075 } else if (!allowRestart) {
9076 bringDownServiceLocked(sr, true);
9077 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009078 boolean canceled = scheduleServiceRestartLocked(sr, true);
9079
9080 // Should the service remain running? Note that in the
9081 // extreme case of so many attempts to deliver a command
9082 // that it failed, that we also will stop it here.
9083 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
9084 if (sr.pendingStarts.size() == 0) {
9085 sr.startRequested = false;
9086 if (!hasClients) {
9087 // Whoops, no reason to restart!
9088 bringDownServiceLocked(sr, true);
9089 }
9090 }
9091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009092 }
9093 }
9094
9095 if (!allowRestart) {
9096 app.services.clear();
9097 }
9098 }
9099
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009100 // Make sure we have no more records on the stopping list.
9101 int i = mStoppingServices.size();
9102 while (i > 0) {
9103 i--;
9104 ServiceRecord sr = mStoppingServices.get(i);
9105 if (sr.app == app) {
9106 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009107 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009108 }
9109 }
9110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009111 app.executingServices.clear();
9112 }
9113
9114 private final void removeDyingProviderLocked(ProcessRecord proc,
9115 ContentProviderRecord cpr) {
9116 synchronized (cpr) {
9117 cpr.launchingApp = null;
9118 cpr.notifyAll();
9119 }
9120
9121 mProvidersByClass.remove(cpr.info.name);
9122 String names[] = cpr.info.authority.split(";");
9123 for (int j = 0; j < names.length; j++) {
9124 mProvidersByName.remove(names[j]);
9125 }
9126
9127 Iterator<ProcessRecord> cit = cpr.clients.iterator();
9128 while (cit.hasNext()) {
9129 ProcessRecord capp = cit.next();
9130 if (!capp.persistent && capp.thread != null
9131 && capp.pid != 0
9132 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009133 Slog.i(TAG, "Kill " + capp.processName
9134 + " (pid " + capp.pid + "): provider " + cpr.info.name
9135 + " in dying process " + proc.processName);
9136 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
9137 capp.processName, capp.setAdj, "dying provider " + proc.processName);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009138 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009139 }
9140 }
9141
9142 mLaunchingProviders.remove(cpr);
9143 }
9144
9145 /**
9146 * Main code for cleaning up a process when it has gone away. This is
9147 * called both as a result of the process dying, or directly when stopping
9148 * a process when running in single process mode.
9149 */
9150 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
9151 boolean restarting, int index) {
9152 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009153 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009154 }
9155
Dianne Hackborn36124872009-10-08 16:22:03 -07009156 mProcessesToGc.remove(app);
9157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009158 // Dismiss any open dialogs.
9159 if (app.crashDialog != null) {
9160 app.crashDialog.dismiss();
9161 app.crashDialog = null;
9162 }
9163 if (app.anrDialog != null) {
9164 app.anrDialog.dismiss();
9165 app.anrDialog = null;
9166 }
9167 if (app.waitDialog != null) {
9168 app.waitDialog.dismiss();
9169 app.waitDialog = null;
9170 }
9171
9172 app.crashing = false;
9173 app.notResponding = false;
9174
9175 app.resetPackageList();
9176 app.thread = null;
9177 app.forcingToForeground = null;
9178 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009179 app.foregroundActivities = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009180
9181 killServicesLocked(app, true);
9182
9183 boolean restart = false;
9184
9185 int NL = mLaunchingProviders.size();
9186
9187 // Remove published content providers.
9188 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009189 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009190 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009191 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009192 cpr.provider = null;
9193 cpr.app = null;
9194
9195 // See if someone is waiting for this provider... in which
9196 // case we don't remove it, but just let it restart.
9197 int i = 0;
9198 if (!app.bad) {
9199 for (; i<NL; i++) {
9200 if (mLaunchingProviders.get(i) == cpr) {
9201 restart = true;
9202 break;
9203 }
9204 }
9205 } else {
9206 i = NL;
9207 }
9208
9209 if (i >= NL) {
9210 removeDyingProviderLocked(app, cpr);
9211 NL = mLaunchingProviders.size();
9212 }
9213 }
9214 app.pubProviders.clear();
9215 }
9216
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009217 // Take care of any launching providers waiting for this process.
9218 if (checkAppInLaunchingProvidersLocked(app, false)) {
9219 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009220 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009222 // Unregister from connected content providers.
9223 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009224 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009225 while (it.hasNext()) {
9226 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9227 cpr.clients.remove(app);
9228 }
9229 app.conProviders.clear();
9230 }
9231
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009232 // At this point there may be remaining entries in mLaunchingProviders
9233 // where we were the only one waiting, so they are no longer of use.
9234 // Look for these and clean up if found.
9235 // XXX Commented out for now. Trying to figure out a way to reproduce
9236 // the actual situation to identify what is actually going on.
9237 if (false) {
9238 for (int i=0; i<NL; i++) {
9239 ContentProviderRecord cpr = (ContentProviderRecord)
9240 mLaunchingProviders.get(i);
9241 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9242 synchronized (cpr) {
9243 cpr.launchingApp = null;
9244 cpr.notifyAll();
9245 }
9246 }
9247 }
9248 }
9249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 skipCurrentReceiverLocked(app);
9251
9252 // Unregister any receivers.
9253 if (app.receivers.size() > 0) {
9254 Iterator<ReceiverList> it = app.receivers.iterator();
9255 while (it.hasNext()) {
9256 removeReceiverLocked(it.next());
9257 }
9258 app.receivers.clear();
9259 }
9260
Christopher Tate181fafa2009-05-14 11:12:14 -07009261 // If the app is undergoing backup, tell the backup manager about it
9262 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009263 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009264 try {
9265 IBackupManager bm = IBackupManager.Stub.asInterface(
9266 ServiceManager.getService(Context.BACKUP_SERVICE));
9267 bm.agentDisconnected(app.info.packageName);
9268 } catch (RemoteException e) {
9269 // can't happen; backup manager is local
9270 }
9271 }
9272
Jeff Sharkey287bd832011-05-28 19:36:26 -07009273 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009275 // If the caller is restarting this app, then leave it in its
9276 // current lists and let the caller take care of it.
9277 if (restarting) {
9278 return;
9279 }
9280
9281 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009282 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009283 "Removing non-persistent process during cleanup: " + app);
9284 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009285 if (mHeavyWeightProcess == app) {
9286 mHeavyWeightProcess = null;
9287 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009289 } else if (!app.removed) {
9290 // This app is persistent, so we need to keep its record around.
9291 // If it is not already on the pending app list, add it there
9292 // and start a new process for it.
9293 app.thread = null;
9294 app.forcingToForeground = null;
9295 app.foregroundServices = false;
9296 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9297 mPersistentStartingProcesses.add(app);
9298 restart = true;
9299 }
9300 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009301 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9302 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009303 mProcessesOnHold.remove(app);
9304
The Android Open Source Project4df24232009-03-05 14:34:35 -08009305 if (app == mHomeProcess) {
9306 mHomeProcess = null;
9307 }
9308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009309 if (restart) {
9310 // We have components that still need to be running in the
9311 // process, so re-launch it.
9312 mProcessNames.put(app.processName, app.info.uid, app);
9313 startProcessLocked(app, "restart", app.processName);
9314 } else if (app.pid > 0 && app.pid != MY_PID) {
9315 // Goodbye!
9316 synchronized (mPidsSelfLocked) {
9317 mPidsSelfLocked.remove(app.pid);
9318 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9319 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009320 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009321 }
9322 }
9323
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009324 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9325 // Look through the content providers we are waiting to have launched,
9326 // and if any run in this process then either schedule a restart of
9327 // the process or kill the client waiting for it if this process has
9328 // gone bad.
9329 int NL = mLaunchingProviders.size();
9330 boolean restart = false;
9331 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009332 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009333 if (cpr.launchingApp == app) {
9334 if (!alwaysBad && !app.bad) {
9335 restart = true;
9336 } else {
9337 removeDyingProviderLocked(app, cpr);
9338 NL = mLaunchingProviders.size();
9339 }
9340 }
9341 }
9342 return restart;
9343 }
9344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009345 // =========================================================
9346 // SERVICES
9347 // =========================================================
9348
9349 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9350 ActivityManager.RunningServiceInfo info =
9351 new ActivityManager.RunningServiceInfo();
9352 info.service = r.name;
9353 if (r.app != null) {
9354 info.pid = r.app.pid;
9355 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009356 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009357 info.process = r.processName;
9358 info.foreground = r.isForeground;
9359 info.activeSince = r.createTime;
9360 info.started = r.startRequested;
9361 info.clientCount = r.connections.size();
9362 info.crashCount = r.crashCount;
9363 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009364 if (r.isForeground) {
9365 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9366 }
9367 if (r.startRequested) {
9368 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9369 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009370 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009371 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9372 }
9373 if (r.app != null && r.app.persistent) {
9374 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9375 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009376
9377 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9378 for (int i=0; i<connl.size(); i++) {
9379 ConnectionRecord conn = connl.get(i);
9380 if (conn.clientLabel != 0) {
9381 info.clientPackage = conn.binding.client.info.packageName;
9382 info.clientLabel = conn.clientLabel;
9383 return info;
9384 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009385 }
9386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009387 return info;
9388 }
9389
9390 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9391 int flags) {
9392 synchronized (this) {
9393 ArrayList<ActivityManager.RunningServiceInfo> res
9394 = new ArrayList<ActivityManager.RunningServiceInfo>();
9395
9396 if (mServices.size() > 0) {
9397 Iterator<ServiceRecord> it = mServices.values().iterator();
9398 while (it.hasNext() && res.size() < maxNum) {
9399 res.add(makeRunningServiceInfoLocked(it.next()));
9400 }
9401 }
9402
9403 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9404 ServiceRecord r = mRestartingServices.get(i);
9405 ActivityManager.RunningServiceInfo info =
9406 makeRunningServiceInfoLocked(r);
9407 info.restarting = r.nextRestartTime;
9408 res.add(info);
9409 }
9410
9411 return res;
9412 }
9413 }
9414
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009415 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9416 synchronized (this) {
9417 ServiceRecord r = mServices.get(name);
9418 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009419 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9420 for (int i=0; i<conn.size(); i++) {
9421 if (conn.get(i).clientIntent != null) {
9422 return conn.get(i).clientIntent;
9423 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009424 }
9425 }
9426 }
9427 }
9428 return null;
9429 }
9430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009431 private final ServiceRecord findServiceLocked(ComponentName name,
9432 IBinder token) {
9433 ServiceRecord r = mServices.get(name);
9434 return r == token ? r : null;
9435 }
9436
9437 private final class ServiceLookupResult {
9438 final ServiceRecord record;
9439 final String permission;
9440
9441 ServiceLookupResult(ServiceRecord _record, String _permission) {
9442 record = _record;
9443 permission = _permission;
9444 }
9445 };
9446
9447 private ServiceLookupResult findServiceLocked(Intent service,
9448 String resolvedType) {
9449 ServiceRecord r = null;
9450 if (service.getComponent() != null) {
9451 r = mServices.get(service.getComponent());
9452 }
9453 if (r == null) {
9454 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9455 r = mServicesByIntent.get(filter);
9456 }
9457
9458 if (r == null) {
9459 try {
9460 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009461 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009462 service, resolvedType, 0);
9463 ServiceInfo sInfo =
9464 rInfo != null ? rInfo.serviceInfo : null;
9465 if (sInfo == null) {
9466 return null;
9467 }
9468
9469 ComponentName name = new ComponentName(
9470 sInfo.applicationInfo.packageName, sInfo.name);
9471 r = mServices.get(name);
9472 } catch (RemoteException ex) {
9473 // pm is in same process, this will never happen.
9474 }
9475 }
9476 if (r != null) {
9477 int callingPid = Binder.getCallingPid();
9478 int callingUid = Binder.getCallingUid();
9479 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009480 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009481 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009482 if (!r.exported) {
9483 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9484 + " from pid=" + callingPid
9485 + ", uid=" + callingUid
9486 + " that is not exported from uid " + r.appInfo.uid);
9487 return new ServiceLookupResult(null, "not exported from uid "
9488 + r.appInfo.uid);
9489 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009490 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009491 + " from pid=" + callingPid
9492 + ", uid=" + callingUid
9493 + " requires " + r.permission);
9494 return new ServiceLookupResult(null, r.permission);
9495 }
9496 return new ServiceLookupResult(r, null);
9497 }
9498 return null;
9499 }
9500
9501 private class ServiceRestarter implements Runnable {
9502 private ServiceRecord mService;
9503
9504 void setService(ServiceRecord service) {
9505 mService = service;
9506 }
9507
9508 public void run() {
9509 synchronized(ActivityManagerService.this) {
9510 performServiceRestartLocked(mService);
9511 }
9512 }
9513 }
9514
9515 private ServiceLookupResult retrieveServiceLocked(Intent service,
9516 String resolvedType, int callingPid, int callingUid) {
9517 ServiceRecord r = null;
9518 if (service.getComponent() != null) {
9519 r = mServices.get(service.getComponent());
9520 }
9521 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9522 r = mServicesByIntent.get(filter);
9523 if (r == null) {
9524 try {
9525 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009526 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009527 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009528 ServiceInfo sInfo =
9529 rInfo != null ? rInfo.serviceInfo : null;
9530 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009531 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009532 ": not found");
9533 return null;
9534 }
9535
9536 ComponentName name = new ComponentName(
9537 sInfo.applicationInfo.packageName, sInfo.name);
9538 r = mServices.get(name);
9539 if (r == null) {
9540 filter = new Intent.FilterComparison(service.cloneFilter());
9541 ServiceRestarter res = new ServiceRestarter();
9542 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9543 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9544 synchronized (stats) {
9545 ss = stats.getServiceStatsLocked(
9546 sInfo.applicationInfo.uid, sInfo.packageName,
9547 sInfo.name);
9548 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009549 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 res.setService(r);
9551 mServices.put(name, r);
9552 mServicesByIntent.put(filter, r);
9553
9554 // Make sure this component isn't in the pending list.
9555 int N = mPendingServices.size();
9556 for (int i=0; i<N; i++) {
9557 ServiceRecord pr = mPendingServices.get(i);
9558 if (pr.name.equals(name)) {
9559 mPendingServices.remove(i);
9560 i--;
9561 N--;
9562 }
9563 }
9564 }
9565 } catch (RemoteException ex) {
9566 // pm is in same process, this will never happen.
9567 }
9568 }
9569 if (r != null) {
9570 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009571 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009572 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009573 if (!r.exported) {
9574 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9575 + " from pid=" + callingPid
9576 + ", uid=" + callingUid
9577 + " that is not exported from uid " + r.appInfo.uid);
9578 return new ServiceLookupResult(null, "not exported from uid "
9579 + r.appInfo.uid);
9580 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009581 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009582 + " from pid=" + callingPid
9583 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009584 + " requires " + r.permission);
9585 return new ServiceLookupResult(null, r.permission);
9586 }
9587 return new ServiceLookupResult(r, null);
9588 }
9589 return null;
9590 }
9591
Dianne Hackborn287952c2010-09-22 22:34:31 -07009592 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9593 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9594 + why + " of " + r + " in app " + r.app);
9595 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9596 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009597 long now = SystemClock.uptimeMillis();
9598 if (r.executeNesting == 0 && r.app != null) {
9599 if (r.app.executingServices.size() == 0) {
9600 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9601 msg.obj = r.app;
9602 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9603 }
9604 r.app.executingServices.add(r);
9605 }
9606 r.executeNesting++;
9607 r.executingStart = now;
9608 }
9609
9610 private final void sendServiceArgsLocked(ServiceRecord r,
9611 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009612 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009613 if (N == 0) {
9614 return;
9615 }
9616
Dianne Hackborn39792d22010-08-19 18:01:52 -07009617 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009618 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009619 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009620 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9621 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009622 if (si.intent == null && N > 1) {
9623 // If somehow we got a dummy null intent in the middle,
9624 // then skip it. DO NOT skip a null intent when it is
9625 // the only one in the list -- this is to support the
9626 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009627 continue;
9628 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009629 si.deliveredTime = SystemClock.uptimeMillis();
9630 r.deliveredStarts.add(si);
9631 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009632 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009633 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009634 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009635 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009636 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009637 if (!oomAdjusted) {
9638 oomAdjusted = true;
9639 updateOomAdjLocked(r.app);
9640 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009641 int flags = 0;
9642 if (si.deliveryCount > 0) {
9643 flags |= Service.START_FLAG_RETRY;
9644 }
9645 if (si.doneExecutingCount > 0) {
9646 flags |= Service.START_FLAG_REDELIVERY;
9647 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009648 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009649 } catch (RemoteException e) {
9650 // Remote process gone... we'll let the normal cleanup take
9651 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009652 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009653 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009654 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009655 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009656 break;
9657 }
9658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009659 }
9660
9661 private final boolean requestServiceBindingLocked(ServiceRecord r,
9662 IntentBindRecord i, boolean rebind) {
9663 if (r.app == null || r.app.thread == null) {
9664 // If service is not currently running, can't yet bind.
9665 return false;
9666 }
9667 if ((!i.requested || rebind) && i.apps.size() > 0) {
9668 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009669 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009670 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9671 if (!rebind) {
9672 i.requested = true;
9673 }
9674 i.hasBound = true;
9675 i.doRebind = false;
9676 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009677 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009678 return false;
9679 }
9680 }
9681 return true;
9682 }
9683
9684 private final void requestServiceBindingsLocked(ServiceRecord r) {
9685 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9686 while (bindings.hasNext()) {
9687 IntentBindRecord i = bindings.next();
9688 if (!requestServiceBindingLocked(r, i, false)) {
9689 break;
9690 }
9691 }
9692 }
9693
9694 private final void realStartServiceLocked(ServiceRecord r,
9695 ProcessRecord app) throws RemoteException {
9696 if (app.thread == null) {
9697 throw new RemoteException();
9698 }
9699
9700 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009701 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702
9703 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009704 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009705 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009706
9707 boolean created = false;
9708 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009709 mStringBuilder.setLength(0);
9710 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009711 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009712 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009713 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009714 synchronized (r.stats.getBatteryStats()) {
9715 r.stats.startLaunchedLocked();
9716 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009717 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04009718 app.thread.scheduleCreateService(r, r.serviceInfo,
9719 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009720 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009721 created = true;
9722 } finally {
9723 if (!created) {
9724 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009725 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009726 }
9727 }
9728
9729 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009730
9731 // If the service is in the started state, and there are no
9732 // pending arguments, then fake up one so its onStartCommand() will
9733 // be called.
9734 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009735 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
9736 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009737 }
9738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009739 sendServiceArgsLocked(r, true);
9740 }
9741
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009742 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9743 boolean allowCancel) {
9744 boolean canceled = false;
9745
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009746 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009747 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009748 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009749
Dianne Hackborn070783f2010-12-29 16:46:28 -08009750 if ((r.serviceInfo.applicationInfo.flags
9751 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9752 minDuration /= 4;
9753 }
9754
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009755 // Any delivered but not yet finished starts should be put back
9756 // on the pending list.
9757 final int N = r.deliveredStarts.size();
9758 if (N > 0) {
9759 for (int i=N-1; i>=0; i--) {
9760 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009761 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009762 if (si.intent == null) {
9763 // We'll generate this again if needed.
9764 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9765 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9766 r.pendingStarts.add(0, si);
9767 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9768 dur *= 2;
9769 if (minDuration < dur) minDuration = dur;
9770 if (resetTime < dur) resetTime = dur;
9771 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009772 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009773 + r.name);
9774 canceled = true;
9775 }
9776 }
9777 r.deliveredStarts.clear();
9778 }
9779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780 r.totalRestartCount++;
9781 if (r.restartDelay == 0) {
9782 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009783 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 } else {
9785 // If it has been a "reasonably long time" since the service
9786 // was started, then reset our restart duration back to
9787 // the beginning, so we don't infinitely increase the duration
9788 // on a service that just occasionally gets killed (which is
9789 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009790 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009792 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009793 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009794 if ((r.serviceInfo.applicationInfo.flags
9795 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9796 // Services in peristent processes will restart much more
9797 // quickly, since they are pretty important. (Think SystemUI).
9798 r.restartDelay += minDuration/2;
9799 } else {
9800 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9801 if (r.restartDelay < minDuration) {
9802 r.restartDelay = minDuration;
9803 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009805 }
9806 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009807
9808 r.nextRestartTime = now + r.restartDelay;
9809
9810 // Make sure that we don't end up restarting a bunch of services
9811 // all at the same time.
9812 boolean repeat;
9813 do {
9814 repeat = false;
9815 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9816 ServiceRecord r2 = mRestartingServices.get(i);
9817 if (r2 != r && r.nextRestartTime
9818 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9819 && r.nextRestartTime
9820 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9821 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9822 r.restartDelay = r.nextRestartTime - now;
9823 repeat = true;
9824 break;
9825 }
9826 }
9827 } while (repeat);
9828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009829 if (!mRestartingServices.contains(r)) {
9830 mRestartingServices.add(r);
9831 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009832
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009833 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009835 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009836 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009837 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009838 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009840 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009841 r.shortName, r.restartDelay);
9842
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009843 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009844 }
9845
9846 final void performServiceRestartLocked(ServiceRecord r) {
9847 if (!mRestartingServices.contains(r)) {
9848 return;
9849 }
9850 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9851 }
9852
9853 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9854 if (r.restartDelay == 0) {
9855 return false;
9856 }
9857 r.resetRestartCounter();
9858 mRestartingServices.remove(r);
9859 mHandler.removeCallbacks(r.restarter);
9860 return true;
9861 }
9862
9863 private final boolean bringUpServiceLocked(ServiceRecord r,
9864 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009865 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009866 //r.dump(" ");
9867
Dianne Hackborn36124872009-10-08 16:22:03 -07009868 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009869 sendServiceArgsLocked(r, false);
9870 return true;
9871 }
9872
9873 if (!whileRestarting && r.restartDelay > 0) {
9874 // If waiting for a restart, then do nothing.
9875 return true;
9876 }
9877
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009878 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009879
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009880 // We are now bringing the service up, so no longer in the
9881 // restarting state.
9882 mRestartingServices.remove(r);
9883
Dianne Hackborne7f97212011-02-24 14:40:20 -08009884 // Service is now being launched, its package can't be stopped.
9885 try {
9886 AppGlobals.getPackageManager().setPackageStoppedState(
9887 r.packageName, false);
9888 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009889 } catch (IllegalArgumentException e) {
9890 Slog.w(TAG, "Failed trying to unstop package "
9891 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009892 }
9893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009894 final String appName = r.processName;
9895 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9896 if (app != null && app.thread != null) {
9897 try {
9898 realStartServiceLocked(r, app);
9899 return true;
9900 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009901 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009902 }
9903
9904 // If a dead object exception was thrown -- fall through to
9905 // restart the application.
9906 }
9907
Dianne Hackborn36124872009-10-08 16:22:03 -07009908 // Not running -- get it started, and enqueue this service record
9909 // to be executed when the app comes up.
9910 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9911 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009912 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009913 + r.appInfo.packageName + "/"
9914 + r.appInfo.uid + " for service "
9915 + r.intent.getIntent() + ": process is bad");
9916 bringDownServiceLocked(r, true);
9917 return false;
9918 }
9919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009920 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009921 mPendingServices.add(r);
9922 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009924 return true;
9925 }
9926
9927 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009928 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009929 //r.dump(" ");
9930
9931 // Does it still need to run?
9932 if (!force && r.startRequested) {
9933 return;
9934 }
9935 if (r.connections.size() > 0) {
9936 if (!force) {
9937 // XXX should probably keep a count of the number of auto-create
9938 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009939 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009940 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009941 ArrayList<ConnectionRecord> cr = it.next();
9942 for (int i=0; i<cr.size(); i++) {
9943 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9944 return;
9945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009946 }
9947 }
9948 }
9949
9950 // Report to all of the connections that the service is no longer
9951 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009952 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009953 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009954 ArrayList<ConnectionRecord> c = it.next();
9955 for (int i=0; i<c.size(); i++) {
9956 try {
9957 c.get(i).conn.connected(r.name, null);
9958 } catch (Exception e) {
9959 Slog.w(TAG, "Failure disconnecting service " + r.name +
9960 " to connection " + c.get(i).conn.asBinder() +
9961 " (in " + c.get(i).binding.client.processName + ")", e);
9962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009963 }
9964 }
9965 }
9966
9967 // Tell the service that it has been unbound.
9968 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9969 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9970 while (it.hasNext()) {
9971 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009972 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009973 + ": hasBound=" + ibr.hasBound);
9974 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9975 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009976 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009977 updateOomAdjLocked(r.app);
9978 ibr.hasBound = false;
9979 r.app.thread.scheduleUnbindService(r,
9980 ibr.intent.getIntent());
9981 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009982 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009983 + r.shortName, e);
9984 serviceDoneExecutingLocked(r, true);
9985 }
9986 }
9987 }
9988 }
9989
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009990 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009991 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009992 System.identityHashCode(r), r.shortName,
9993 (r.app != null) ? r.app.pid : -1);
9994
9995 mServices.remove(r.name);
9996 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009997 r.totalRestartCount = 0;
9998 unscheduleServiceRestartLocked(r);
9999
10000 // Also make sure it is not on the pending list.
10001 int N = mPendingServices.size();
10002 for (int i=0; i<N; i++) {
10003 if (mPendingServices.get(i) == r) {
10004 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010005 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 i--;
10007 N--;
10008 }
10009 }
10010
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010011 r.cancelNotification();
10012 r.isForeground = false;
10013 r.foregroundId = 0;
10014 r.foregroundNoti = null;
10015
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010016 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070010017 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010018 r.pendingStarts.clear();
10019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010020 if (r.app != null) {
10021 synchronized (r.stats.getBatteryStats()) {
10022 r.stats.stopLaunchedLocked();
10023 }
10024 r.app.services.remove(r);
10025 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010026 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010027 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010028 mStoppingServices.add(r);
10029 updateOomAdjLocked(r.app);
10030 r.app.thread.scheduleStopService(r);
10031 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010032 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010033 + r.shortName, e);
10034 serviceDoneExecutingLocked(r, true);
10035 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010036 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010037 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010038 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010039 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010040 }
10041 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010042 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010043 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010044 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080010045
10046 if (r.bindings.size() > 0) {
10047 r.bindings.clear();
10048 }
10049
10050 if (r.restarter instanceof ServiceRestarter) {
10051 ((ServiceRestarter)r.restarter).setService(null);
10052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010053 }
10054
10055 ComponentName startServiceLocked(IApplicationThread caller,
10056 Intent service, String resolvedType,
10057 int callingPid, int callingUid) {
10058 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010059 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010060 + " type=" + resolvedType + " args=" + service.getExtras());
10061
10062 if (caller != null) {
10063 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10064 if (callerApp == null) {
10065 throw new SecurityException(
10066 "Unable to find app for caller " + caller
10067 + " (pid=" + Binder.getCallingPid()
10068 + ") when starting service " + service);
10069 }
10070 }
10071
10072 ServiceLookupResult res =
10073 retrieveServiceLocked(service, resolvedType,
10074 callingPid, callingUid);
10075 if (res == null) {
10076 return null;
10077 }
10078 if (res.record == null) {
10079 return new ComponentName("!", res.permission != null
10080 ? res.permission : "private to package");
10081 }
10082 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070010083 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
10084 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010085 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010086 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010087 }
10088 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010089 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010090 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070010091 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010092 r.lastActivity = SystemClock.uptimeMillis();
10093 synchronized (r.stats.getBatteryStats()) {
10094 r.stats.startRunningLocked();
10095 }
10096 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
10097 return new ComponentName("!", "Service process is bad");
10098 }
10099 return r.name;
10100 }
10101 }
10102
10103 public ComponentName startService(IApplicationThread caller, Intent service,
10104 String resolvedType) {
10105 // Refuse possible leaked file descriptors
10106 if (service != null && service.hasFileDescriptors() == true) {
10107 throw new IllegalArgumentException("File descriptors passed in Intent");
10108 }
10109
10110 synchronized(this) {
10111 final int callingPid = Binder.getCallingPid();
10112 final int callingUid = Binder.getCallingUid();
10113 final long origId = Binder.clearCallingIdentity();
10114 ComponentName res = startServiceLocked(caller, service,
10115 resolvedType, callingPid, callingUid);
10116 Binder.restoreCallingIdentity(origId);
10117 return res;
10118 }
10119 }
10120
10121 ComponentName startServiceInPackage(int uid,
10122 Intent service, String resolvedType) {
10123 synchronized(this) {
10124 final long origId = Binder.clearCallingIdentity();
10125 ComponentName res = startServiceLocked(null, service,
10126 resolvedType, -1, uid);
10127 Binder.restoreCallingIdentity(origId);
10128 return res;
10129 }
10130 }
10131
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010132 private void stopServiceLocked(ServiceRecord service) {
10133 synchronized (service.stats.getBatteryStats()) {
10134 service.stats.stopRunningLocked();
10135 }
10136 service.startRequested = false;
10137 service.callStart = false;
10138 bringDownServiceLocked(service, false);
10139 }
10140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010141 public int stopService(IApplicationThread caller, Intent service,
10142 String resolvedType) {
10143 // Refuse possible leaked file descriptors
10144 if (service != null && service.hasFileDescriptors() == true) {
10145 throw new IllegalArgumentException("File descriptors passed in Intent");
10146 }
10147
10148 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010149 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010150 + " type=" + resolvedType);
10151
10152 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10153 if (caller != null && callerApp == null) {
10154 throw new SecurityException(
10155 "Unable to find app for caller " + caller
10156 + " (pid=" + Binder.getCallingPid()
10157 + ") when stopping service " + service);
10158 }
10159
10160 // If this service is active, make sure it is stopped.
10161 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10162 if (r != null) {
10163 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010164 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010165 try {
10166 stopServiceLocked(r.record);
10167 } finally {
10168 Binder.restoreCallingIdentity(origId);
10169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010170 return 1;
10171 }
10172 return -1;
10173 }
10174 }
10175
10176 return 0;
10177 }
10178
10179 public IBinder peekService(Intent service, String resolvedType) {
10180 // Refuse possible leaked file descriptors
10181 if (service != null && service.hasFileDescriptors() == true) {
10182 throw new IllegalArgumentException("File descriptors passed in Intent");
10183 }
10184
10185 IBinder ret = null;
10186
10187 synchronized(this) {
10188 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10189
10190 if (r != null) {
10191 // r.record is null if findServiceLocked() failed the caller permission check
10192 if (r.record == null) {
10193 throw new SecurityException(
10194 "Permission Denial: Accessing service " + r.record.name
10195 + " from pid=" + Binder.getCallingPid()
10196 + ", uid=" + Binder.getCallingUid()
10197 + " requires " + r.permission);
10198 }
10199 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10200 if (ib != null) {
10201 ret = ib.binder;
10202 }
10203 }
10204 }
10205
10206 return ret;
10207 }
10208
10209 public boolean stopServiceToken(ComponentName className, IBinder token,
10210 int startId) {
10211 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010212 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010213 + " " + token + " startId=" + startId);
10214 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010215 if (r != null) {
10216 if (startId >= 0) {
10217 // Asked to only stop if done with all work. Note that
10218 // to avoid leaks, we will take this as dropping all
10219 // start items up to and including this one.
10220 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10221 if (si != null) {
10222 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010223 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10224 cur.removeUriPermissionsLocked();
10225 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010226 break;
10227 }
10228 }
10229 }
10230
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010231 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010232 return false;
10233 }
10234
10235 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010236 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010237 + " is last, but have " + r.deliveredStarts.size()
10238 + " remaining args");
10239 }
10240 }
10241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 synchronized (r.stats.getBatteryStats()) {
10243 r.stats.stopRunningLocked();
10244 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010245 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010246 }
10247 final long origId = Binder.clearCallingIdentity();
10248 bringDownServiceLocked(r, false);
10249 Binder.restoreCallingIdentity(origId);
10250 return true;
10251 }
10252 }
10253 return false;
10254 }
10255
10256 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010257 int id, Notification notification, boolean removeNotification) {
10258 final long origId = Binder.clearCallingIdentity();
10259 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010260 synchronized(this) {
10261 ServiceRecord r = findServiceLocked(className, token);
10262 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010263 if (id != 0) {
10264 if (notification == null) {
10265 throw new IllegalArgumentException("null notification");
10266 }
10267 if (r.foregroundId != id) {
10268 r.cancelNotification();
10269 r.foregroundId = id;
10270 }
10271 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10272 r.foregroundNoti = notification;
10273 r.isForeground = true;
10274 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010275 if (r.app != null) {
10276 updateServiceForegroundLocked(r.app, true);
10277 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010278 } else {
10279 if (r.isForeground) {
10280 r.isForeground = false;
10281 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010282 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010283 updateServiceForegroundLocked(r.app, true);
10284 }
10285 }
10286 if (removeNotification) {
10287 r.cancelNotification();
10288 r.foregroundId = 0;
10289 r.foregroundNoti = null;
10290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010291 }
10292 }
10293 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010294 } finally {
10295 Binder.restoreCallingIdentity(origId);
10296 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010297 }
10298
10299 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10300 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010301 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010302 if (sr.isForeground) {
10303 anyForeground = true;
10304 break;
10305 }
10306 }
10307 if (anyForeground != proc.foregroundServices) {
10308 proc.foregroundServices = anyForeground;
10309 if (oomAdj) {
10310 updateOomAdjLocked();
10311 }
10312 }
10313 }
10314
10315 public int bindService(IApplicationThread caller, IBinder token,
10316 Intent service, String resolvedType,
10317 IServiceConnection connection, int flags) {
10318 // Refuse possible leaked file descriptors
10319 if (service != null && service.hasFileDescriptors() == true) {
10320 throw new IllegalArgumentException("File descriptors passed in Intent");
10321 }
10322
10323 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010324 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010325 + " type=" + resolvedType + " conn=" + connection.asBinder()
10326 + " flags=0x" + Integer.toHexString(flags));
10327 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10328 if (callerApp == null) {
10329 throw new SecurityException(
10330 "Unable to find app for caller " + caller
10331 + " (pid=" + Binder.getCallingPid()
10332 + ") when binding service " + service);
10333 }
10334
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010335 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010336 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010337 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010339 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010340 return 0;
10341 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010342 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010343 }
10344
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010345 int clientLabel = 0;
10346 PendingIntent clientIntent = null;
10347
10348 if (callerApp.info.uid == Process.SYSTEM_UID) {
10349 // Hacky kind of thing -- allow system stuff to tell us
10350 // what they are, so we can report this elsewhere for
10351 // others to know why certain services are running.
10352 try {
10353 clientIntent = (PendingIntent)service.getParcelableExtra(
10354 Intent.EXTRA_CLIENT_INTENT);
10355 } catch (RuntimeException e) {
10356 }
10357 if (clientIntent != null) {
10358 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10359 if (clientLabel != 0) {
10360 // There are no useful extras in the intent, trash them.
10361 // System code calling with this stuff just needs to know
10362 // this will happen.
10363 service = service.cloneFilter();
10364 }
10365 }
10366 }
10367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010368 ServiceLookupResult res =
10369 retrieveServiceLocked(service, resolvedType,
10370 Binder.getCallingPid(), Binder.getCallingUid());
10371 if (res == null) {
10372 return 0;
10373 }
10374 if (res.record == null) {
10375 return -1;
10376 }
10377 ServiceRecord s = res.record;
10378
10379 final long origId = Binder.clearCallingIdentity();
10380
10381 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010382 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010383 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010384 }
10385
10386 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10387 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010388 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010389
10390 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010391 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10392 if (clist == null) {
10393 clist = new ArrayList<ConnectionRecord>();
10394 s.connections.put(binder, clist);
10395 }
10396 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010397 b.connections.add(c);
10398 if (activity != null) {
10399 if (activity.connections == null) {
10400 activity.connections = new HashSet<ConnectionRecord>();
10401 }
10402 activity.connections.add(c);
10403 }
10404 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010405 clist = mServiceConnections.get(binder);
10406 if (clist == null) {
10407 clist = new ArrayList<ConnectionRecord>();
10408 mServiceConnections.put(binder, clist);
10409 }
10410 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010411
10412 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10413 s.lastActivity = SystemClock.uptimeMillis();
10414 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10415 return 0;
10416 }
10417 }
10418
10419 if (s.app != null) {
10420 // This could have made the service more important.
10421 updateOomAdjLocked(s.app);
10422 }
10423
Joe Onorato8a9b2202010-02-26 18:56:32 -080010424 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010425 + ": received=" + b.intent.received
10426 + " apps=" + b.intent.apps.size()
10427 + " doRebind=" + b.intent.doRebind);
10428
10429 if (s.app != null && b.intent.received) {
10430 // Service is already running, so we can immediately
10431 // publish the connection.
10432 try {
10433 c.conn.connected(s.name, b.intent.binder);
10434 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010435 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010436 + " to connection " + c.conn.asBinder()
10437 + " (in " + c.binding.client.processName + ")", e);
10438 }
10439
10440 // If this is the first app connected back to this binding,
10441 // and the service had previously asked to be told when
10442 // rebound, then do so.
10443 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10444 requestServiceBindingLocked(s, b.intent, true);
10445 }
10446 } else if (!b.intent.requested) {
10447 requestServiceBindingLocked(s, b.intent, false);
10448 }
10449
10450 Binder.restoreCallingIdentity(origId);
10451 }
10452
10453 return 1;
10454 }
10455
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010456 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010457 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010458 IBinder binder = c.conn.asBinder();
10459 AppBindRecord b = c.binding;
10460 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010461 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10462 if (clist != null) {
10463 clist.remove(c);
10464 if (clist.size() == 0) {
10465 s.connections.remove(binder);
10466 }
10467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010468 b.connections.remove(c);
10469 if (c.activity != null && c.activity != skipAct) {
10470 if (c.activity.connections != null) {
10471 c.activity.connections.remove(c);
10472 }
10473 }
10474 if (b.client != skipApp) {
10475 b.client.connections.remove(c);
10476 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010477 clist = mServiceConnections.get(binder);
10478 if (clist != null) {
10479 clist.remove(c);
10480 if (clist.size() == 0) {
10481 mServiceConnections.remove(binder);
10482 }
10483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010484
10485 if (b.connections.size() == 0) {
10486 b.intent.apps.remove(b.client);
10487 }
10488
Joe Onorato8a9b2202010-02-26 18:56:32 -080010489 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010490 + ": shouldUnbind=" + b.intent.hasBound);
10491 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10492 && b.intent.hasBound) {
10493 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010494 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010495 updateOomAdjLocked(s.app);
10496 b.intent.hasBound = false;
10497 // Assume the client doesn't want to know about a rebind;
10498 // we will deal with that later if it asks for one.
10499 b.intent.doRebind = false;
10500 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10501 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010502 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010503 serviceDoneExecutingLocked(s, true);
10504 }
10505 }
10506
10507 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10508 bringDownServiceLocked(s, false);
10509 }
10510 }
10511
10512 public boolean unbindService(IServiceConnection connection) {
10513 synchronized (this) {
10514 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010515 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010516 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10517 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010518 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010519 + connection.asBinder());
10520 return false;
10521 }
10522
10523 final long origId = Binder.clearCallingIdentity();
10524
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010525 while (clist.size() > 0) {
10526 ConnectionRecord r = clist.get(0);
10527 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010529 if (r.binding.service.app != null) {
10530 // This could have made the service less important.
10531 updateOomAdjLocked(r.binding.service.app);
10532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010533 }
10534
10535 Binder.restoreCallingIdentity(origId);
10536 }
10537
10538 return true;
10539 }
10540
10541 public void publishService(IBinder token, Intent intent, IBinder service) {
10542 // Refuse possible leaked file descriptors
10543 if (intent != null && intent.hasFileDescriptors() == true) {
10544 throw new IllegalArgumentException("File descriptors passed in Intent");
10545 }
10546
10547 synchronized(this) {
10548 if (!(token instanceof ServiceRecord)) {
10549 throw new IllegalArgumentException("Invalid service token");
10550 }
10551 ServiceRecord r = (ServiceRecord)token;
10552
10553 final long origId = Binder.clearCallingIdentity();
10554
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010555 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010556 + " " + intent + ": " + service);
10557 if (r != null) {
10558 Intent.FilterComparison filter
10559 = new Intent.FilterComparison(intent);
10560 IntentBindRecord b = r.bindings.get(filter);
10561 if (b != null && !b.received) {
10562 b.binder = service;
10563 b.requested = true;
10564 b.received = true;
10565 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010566 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010567 = r.connections.values().iterator();
10568 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010569 ArrayList<ConnectionRecord> clist = it.next();
10570 for (int i=0; i<clist.size(); i++) {
10571 ConnectionRecord c = clist.get(i);
10572 if (!filter.equals(c.binding.intent.intent)) {
10573 if (DEBUG_SERVICE) Slog.v(
10574 TAG, "Not publishing to: " + c);
10575 if (DEBUG_SERVICE) Slog.v(
10576 TAG, "Bound intent: " + c.binding.intent.intent);
10577 if (DEBUG_SERVICE) Slog.v(
10578 TAG, "Published intent: " + intent);
10579 continue;
10580 }
10581 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10582 try {
10583 c.conn.connected(r.name, service);
10584 } catch (Exception e) {
10585 Slog.w(TAG, "Failure sending service " + r.name +
10586 " to connection " + c.conn.asBinder() +
10587 " (in " + c.binding.client.processName + ")", e);
10588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010589 }
10590 }
10591 }
10592 }
10593
10594 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10595
10596 Binder.restoreCallingIdentity(origId);
10597 }
10598 }
10599 }
10600
10601 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10602 // Refuse possible leaked file descriptors
10603 if (intent != null && intent.hasFileDescriptors() == true) {
10604 throw new IllegalArgumentException("File descriptors passed in Intent");
10605 }
10606
10607 synchronized(this) {
10608 if (!(token instanceof ServiceRecord)) {
10609 throw new IllegalArgumentException("Invalid service token");
10610 }
10611 ServiceRecord r = (ServiceRecord)token;
10612
10613 final long origId = Binder.clearCallingIdentity();
10614
10615 if (r != null) {
10616 Intent.FilterComparison filter
10617 = new Intent.FilterComparison(intent);
10618 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010619 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010620 + " at " + b + ": apps="
10621 + (b != null ? b.apps.size() : 0));
10622 if (b != null) {
10623 if (b.apps.size() > 0) {
10624 // Applications have already bound since the last
10625 // unbind, so just rebind right here.
10626 requestServiceBindingLocked(r, b, true);
10627 } else {
10628 // Note to tell the service the next time there is
10629 // a new client.
10630 b.doRebind = true;
10631 }
10632 }
10633
10634 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10635
10636 Binder.restoreCallingIdentity(origId);
10637 }
10638 }
10639 }
10640
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010641 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010642 synchronized(this) {
10643 if (!(token instanceof ServiceRecord)) {
10644 throw new IllegalArgumentException("Invalid service token");
10645 }
10646 ServiceRecord r = (ServiceRecord)token;
10647 boolean inStopping = mStoppingServices.contains(token);
10648 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010649 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010650 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010651 + " with incorrect token: given " + token
10652 + ", expected " + r);
10653 return;
10654 }
10655
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010656 if (type == 1) {
10657 // This is a call from a service start... take care of
10658 // book-keeping.
10659 r.callStart = true;
10660 switch (res) {
10661 case Service.START_STICKY_COMPATIBILITY:
10662 case Service.START_STICKY: {
10663 // We are done with the associated start arguments.
10664 r.findDeliveredStart(startId, true);
10665 // Don't stop if killed.
10666 r.stopIfKilled = false;
10667 break;
10668 }
10669 case Service.START_NOT_STICKY: {
10670 // We are done with the associated start arguments.
10671 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010672 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010673 // There is no more work, and this service
10674 // doesn't want to hang around if killed.
10675 r.stopIfKilled = true;
10676 }
10677 break;
10678 }
10679 case Service.START_REDELIVER_INTENT: {
10680 // We'll keep this item until they explicitly
10681 // call stop for it, but keep track of the fact
10682 // that it was delivered.
10683 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10684 if (si != null) {
10685 si.deliveryCount = 0;
10686 si.doneExecutingCount++;
10687 // Don't stop if killed.
10688 r.stopIfKilled = true;
10689 }
10690 break;
10691 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010692 case Service.START_TASK_REMOVED_COMPLETE: {
10693 // Special processing for onTaskRemoved(). Don't
10694 // impact normal onStartCommand() processing.
10695 r.findDeliveredStart(startId, true);
10696 break;
10697 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010698 default:
10699 throw new IllegalArgumentException(
10700 "Unknown service start result: " + res);
10701 }
10702 if (res == Service.START_STICKY_COMPATIBILITY) {
10703 r.callStart = false;
10704 }
10705 }
10706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010707 final long origId = Binder.clearCallingIdentity();
10708 serviceDoneExecutingLocked(r, inStopping);
10709 Binder.restoreCallingIdentity(origId);
10710 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010711 Slog.w(TAG, "Done executing unknown service from pid "
10712 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010713 }
10714 }
10715 }
10716
10717 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010718 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10719 + ": nesting=" + r.executeNesting
10720 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010721 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010722 r.executeNesting--;
10723 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010724 if (DEBUG_SERVICE) Slog.v(TAG,
10725 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010726 r.app.executingServices.remove(r);
10727 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010728 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10729 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010730 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10731 }
10732 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010733 if (DEBUG_SERVICE) Slog.v(TAG,
10734 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010735 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010736 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010737 }
10738 updateOomAdjLocked(r.app);
10739 }
10740 }
10741
10742 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010743 String anrMessage = null;
10744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010745 synchronized(this) {
10746 if (proc.executingServices.size() == 0 || proc.thread == null) {
10747 return;
10748 }
10749 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10750 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10751 ServiceRecord timeout = null;
10752 long nextTime = 0;
10753 while (it.hasNext()) {
10754 ServiceRecord sr = it.next();
10755 if (sr.executingStart < maxTime) {
10756 timeout = sr;
10757 break;
10758 }
10759 if (sr.executingStart > nextTime) {
10760 nextTime = sr.executingStart;
10761 }
10762 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010763 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010764 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010765 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010766 } else {
10767 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10768 msg.obj = proc;
10769 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10770 }
10771 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010772
10773 if (anrMessage != null) {
10774 appNotResponding(proc, null, null, anrMessage);
10775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010776 }
10777
10778 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010779 // BACKUP AND RESTORE
10780 // =========================================================
10781
10782 // Cause the target app to be launched if necessary and its backup agent
10783 // instantiated. The backup agent will invoke backupAgentCreated() on the
10784 // activity manager to announce its creation.
10785 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010786 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010787 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10788
10789 synchronized(this) {
10790 // !!! TODO: currently no check here that we're already bound
10791 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10792 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10793 synchronized (stats) {
10794 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10795 }
10796
Dianne Hackborne7f97212011-02-24 14:40:20 -080010797 // Backup agent is now in use, its package can't be stopped.
10798 try {
10799 AppGlobals.getPackageManager().setPackageStoppedState(
10800 app.packageName, false);
10801 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010802 } catch (IllegalArgumentException e) {
10803 Slog.w(TAG, "Failed trying to unstop package "
10804 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010805 }
10806
Christopher Tate181fafa2009-05-14 11:12:14 -070010807 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070010808 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
10809 ? new ComponentName(app.packageName, app.backupAgentName)
10810 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070010811 // startProcessLocked() returns existing proc's record if it's already running
10812 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010813 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010814 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010815 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010816 return false;
10817 }
10818
10819 r.app = proc;
10820 mBackupTarget = r;
10821 mBackupAppName = app.packageName;
10822
Christopher Tate6fa95972009-06-05 18:43:55 -070010823 // Try not to kill the process during backup
10824 updateOomAdjLocked(proc);
10825
Christopher Tate181fafa2009-05-14 11:12:14 -070010826 // If the process is already attached, schedule the creation of the backup agent now.
10827 // If it is not yet live, this will be done when it attaches to the framework.
10828 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010829 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010830 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010831 proc.thread.scheduleCreateBackupAgent(app,
10832 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010833 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010834 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010835 }
10836 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010837 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010838 }
10839 // Invariants: at this point, the target app process exists and the application
10840 // is either already running or in the process of coming up. mBackupTarget and
10841 // mBackupAppName describe the app, so that when it binds back to the AM we
10842 // know that it's scheduled for a backup-agent operation.
10843 }
10844
10845 return true;
10846 }
10847
10848 // A backup agent has just come up
10849 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010850 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010851 + " = " + agent);
10852
10853 synchronized(this) {
10854 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010855 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010856 return;
10857 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010858 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010859
Dianne Hackborn06740692010-09-22 22:46:21 -070010860 long oldIdent = Binder.clearCallingIdentity();
10861 try {
10862 IBackupManager bm = IBackupManager.Stub.asInterface(
10863 ServiceManager.getService(Context.BACKUP_SERVICE));
10864 bm.agentConnected(agentPackageName, agent);
10865 } catch (RemoteException e) {
10866 // can't happen; the backup manager service is local
10867 } catch (Exception e) {
10868 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10869 e.printStackTrace();
10870 } finally {
10871 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010872 }
10873 }
10874
10875 // done with this agent
10876 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010877 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010878 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010879 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010880 return;
10881 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010882
10883 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010884 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010885 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010886 return;
10887 }
10888
Christopher Tate181fafa2009-05-14 11:12:14 -070010889 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010890 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010891 return;
10892 }
10893
Christopher Tate6fa95972009-06-05 18:43:55 -070010894 ProcessRecord proc = mBackupTarget.app;
10895 mBackupTarget = null;
10896 mBackupAppName = null;
10897
10898 // Not backing this app up any more; reset its OOM adjustment
10899 updateOomAdjLocked(proc);
10900
Christopher Tatec7b31e32009-06-10 15:49:30 -070010901 // If the app crashed during backup, 'thread' will be null here
10902 if (proc.thread != null) {
10903 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010904 proc.thread.scheduleDestroyBackupAgent(appInfo,
10905 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070010906 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010907 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010908 e.printStackTrace();
10909 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010910 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010911 }
10912 }
10913 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010914 // BROADCASTS
10915 // =========================================================
10916
Josh Bartel7f208742010-02-25 11:01:44 -060010917 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010918 List cur) {
10919 final ContentResolver resolver = mContext.getContentResolver();
10920 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10921 if (list == null) {
10922 return cur;
10923 }
10924 int N = list.size();
10925 for (int i=0; i<N; i++) {
10926 Intent intent = list.get(i);
10927 if (filter.match(resolver, intent, true, TAG) >= 0) {
10928 if (cur == null) {
10929 cur = new ArrayList<Intent>();
10930 }
10931 cur.add(intent);
10932 }
10933 }
10934 return cur;
10935 }
10936
10937 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010938 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010939 + mBroadcastsScheduled);
10940
10941 if (mBroadcastsScheduled) {
10942 return;
10943 }
10944 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10945 mBroadcastsScheduled = true;
10946 }
10947
10948 public Intent registerReceiver(IApplicationThread caller,
10949 IIntentReceiver receiver, IntentFilter filter, String permission) {
10950 synchronized(this) {
10951 ProcessRecord callerApp = null;
10952 if (caller != null) {
10953 callerApp = getRecordForAppLocked(caller);
10954 if (callerApp == null) {
10955 throw new SecurityException(
10956 "Unable to find app for caller " + caller
10957 + " (pid=" + Binder.getCallingPid()
10958 + ") when registering receiver " + receiver);
10959 }
10960 }
10961
10962 List allSticky = null;
10963
10964 // Look for any matching sticky broadcasts...
10965 Iterator actions = filter.actionsIterator();
10966 if (actions != null) {
10967 while (actions.hasNext()) {
10968 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010969 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010970 }
10971 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010972 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 }
10974
10975 // The first sticky in the list is returned directly back to
10976 // the client.
10977 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10978
Joe Onorato8a9b2202010-02-26 18:56:32 -080010979 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980 + ": " + sticky);
10981
10982 if (receiver == null) {
10983 return sticky;
10984 }
10985
10986 ReceiverList rl
10987 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10988 if (rl == null) {
10989 rl = new ReceiverList(this, callerApp,
10990 Binder.getCallingPid(),
10991 Binder.getCallingUid(), receiver);
10992 if (rl.app != null) {
10993 rl.app.receivers.add(rl);
10994 } else {
10995 try {
10996 receiver.asBinder().linkToDeath(rl, 0);
10997 } catch (RemoteException e) {
10998 return sticky;
10999 }
11000 rl.linkedToDeath = true;
11001 }
11002 mRegisteredReceivers.put(receiver.asBinder(), rl);
11003 }
11004 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
11005 rl.add(bf);
11006 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011007 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 }
11009 mReceiverResolver.addFilter(bf);
11010
11011 // Enqueue broadcasts for all existing stickies that match
11012 // this filter.
11013 if (allSticky != null) {
11014 ArrayList receivers = new ArrayList();
11015 receivers.add(bf);
11016
11017 int N = allSticky.size();
11018 for (int i=0; i<N; i++) {
11019 Intent intent = (Intent)allSticky.get(i);
11020 BroadcastRecord r = new BroadcastRecord(intent, null,
11021 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011022 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 if (mParallelBroadcasts.size() == 0) {
11024 scheduleBroadcastsLocked();
11025 }
11026 mParallelBroadcasts.add(r);
11027 }
11028 }
11029
11030 return sticky;
11031 }
11032 }
11033
11034 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011035 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036
11037 boolean doNext = false;
11038
11039 synchronized(this) {
11040 ReceiverList rl
11041 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11042 if (rl != null) {
11043 if (rl.curBroadcast != null) {
11044 BroadcastRecord r = rl.curBroadcast;
11045 doNext = finishReceiverLocked(
11046 receiver.asBinder(), r.resultCode, r.resultData,
11047 r.resultExtras, r.resultAbort, true);
11048 }
11049
11050 if (rl.app != null) {
11051 rl.app.receivers.remove(rl);
11052 }
11053 removeReceiverLocked(rl);
11054 if (rl.linkedToDeath) {
11055 rl.linkedToDeath = false;
11056 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11057 }
11058 }
11059 }
11060
11061 if (!doNext) {
11062 return;
11063 }
11064
11065 final long origId = Binder.clearCallingIdentity();
11066 processNextBroadcast(false);
11067 trimApplications();
11068 Binder.restoreCallingIdentity(origId);
11069 }
11070
11071 void removeReceiverLocked(ReceiverList rl) {
11072 mRegisteredReceivers.remove(rl.receiver.asBinder());
11073 int N = rl.size();
11074 for (int i=0; i<N; i++) {
11075 mReceiverResolver.removeFilter(rl.get(i));
11076 }
11077 }
11078
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011079 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
11080 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11081 ProcessRecord r = mLruProcesses.get(i);
11082 if (r.thread != null) {
11083 try {
11084 r.thread.dispatchPackageBroadcast(cmd, packages);
11085 } catch (RemoteException ex) {
11086 }
11087 }
11088 }
11089 }
11090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 private final int broadcastIntentLocked(ProcessRecord callerApp,
11092 String callerPackage, Intent intent, String resolvedType,
11093 IIntentReceiver resultTo, int resultCode, String resultData,
11094 Bundle map, String requiredPermission,
11095 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11096 intent = new Intent(intent);
11097
Dianne Hackborne7f97212011-02-24 14:40:20 -080011098 // By default broadcasts do not go to stopped apps.
11099 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
11100
Joe Onorato8a9b2202010-02-26 18:56:32 -080011101 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011102 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11103 + " ordered=" + ordered);
11104 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011105 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011106 }
11107
11108 // Handle special intents: if this broadcast is from the package
11109 // manager about a package being removed, we need to remove all of
11110 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011111 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011112 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011113 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11114 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011115 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011116 || uidRemoved) {
11117 if (checkComponentPermission(
11118 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011119 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011120 == PackageManager.PERMISSION_GRANTED) {
11121 if (uidRemoved) {
11122 final Bundle intentExtras = intent.getExtras();
11123 final int uid = intentExtras != null
11124 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11125 if (uid >= 0) {
11126 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11127 synchronized (bs) {
11128 bs.removeUidStatsLocked(uid);
11129 }
11130 }
11131 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011132 // If resources are unvailble just force stop all
11133 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011134 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011135 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11136 if (list != null && (list.length > 0)) {
11137 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011138 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011139 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011140 sendPackageBroadcastLocked(
11141 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011142 }
11143 } else {
11144 Uri data = intent.getData();
11145 String ssp;
11146 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11147 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11148 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011149 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011150 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011151 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011152 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
11153 new String[] {ssp});
11154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011155 }
11156 }
11157 }
11158 } else {
11159 String msg = "Permission Denial: " + intent.getAction()
11160 + " broadcast from " + callerPackage + " (pid=" + callingPid
11161 + ", uid=" + callingUid + ")"
11162 + " requires "
11163 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011164 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011165 throw new SecurityException(msg);
11166 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011167
11168 // Special case for adding a package: by default turn on compatibility
11169 // mode.
11170 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070011171 Uri data = intent.getData();
11172 String ssp;
11173 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11174 mCompatModePackages.handlePackageAddedLocked(ssp,
11175 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011177 }
11178
11179 /*
11180 * If this is the time zone changed action, queue up a message that will reset the timezone
11181 * of all currently running processes. This message will get queued up before the broadcast
11182 * happens.
11183 */
11184 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11185 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11186 }
11187
Robert Greenwalt03595d02010-11-02 14:08:23 -070011188 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
11189 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
11190 }
11191
Robert Greenwalt434203a2010-10-11 16:00:27 -070011192 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
11193 ProxyProperties proxy = intent.getParcelableExtra("proxy");
11194 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
11195 }
11196
Dianne Hackborn854060af2009-07-09 18:14:31 -070011197 /*
11198 * Prevent non-system code (defined here to be non-persistent
11199 * processes) from sending protected broadcasts.
11200 */
11201 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11202 || callingUid == Process.SHELL_UID || callingUid == 0) {
11203 // Always okay.
11204 } else if (callerApp == null || !callerApp.persistent) {
11205 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011206 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070011207 intent.getAction())) {
11208 String msg = "Permission Denial: not allowed to send broadcast "
11209 + intent.getAction() + " from pid="
11210 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011211 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011212 throw new SecurityException(msg);
11213 }
11214 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011215 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011216 return BROADCAST_SUCCESS;
11217 }
11218 }
11219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 // Add to the sticky list if requested.
11221 if (sticky) {
11222 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11223 callingPid, callingUid)
11224 != PackageManager.PERMISSION_GRANTED) {
11225 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11226 + callingPid + ", uid=" + callingUid
11227 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011228 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011229 throw new SecurityException(msg);
11230 }
11231 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011232 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 + " and enforce permission " + requiredPermission);
11234 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11235 }
11236 if (intent.getComponent() != null) {
11237 throw new SecurityException(
11238 "Sticky broadcasts can't target a specific component");
11239 }
11240 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11241 if (list == null) {
11242 list = new ArrayList<Intent>();
11243 mStickyBroadcasts.put(intent.getAction(), list);
11244 }
11245 int N = list.size();
11246 int i;
11247 for (i=0; i<N; i++) {
11248 if (intent.filterEquals(list.get(i))) {
11249 // This sticky already exists, replace it.
11250 list.set(i, new Intent(intent));
11251 break;
11252 }
11253 }
11254 if (i >= N) {
11255 list.add(new Intent(intent));
11256 }
11257 }
11258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011259 // Figure out who all will receive this broadcast.
11260 List receivers = null;
11261 List<BroadcastFilter> registeredReceivers = null;
11262 try {
11263 if (intent.getComponent() != null) {
11264 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011265 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011266 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 if (ai != null) {
11268 receivers = new ArrayList();
11269 ResolveInfo ri = new ResolveInfo();
11270 ri.activityInfo = ai;
11271 receivers.add(ri);
11272 }
11273 } else {
11274 // Need to resolve the intent to interested receivers...
11275 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11276 == 0) {
11277 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011278 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011279 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011280 }
Mihai Preda074edef2009-05-18 17:13:31 +020011281 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282 }
11283 } catch (RemoteException ex) {
11284 // pm is in same process, this will never happen.
11285 }
11286
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011287 final boolean replacePending =
11288 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11289
Joe Onorato8a9b2202010-02-26 18:56:32 -080011290 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011291 + " replacePending=" + replacePending);
11292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011293 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11294 if (!ordered && NR > 0) {
11295 // If we are not serializing this broadcast, then send the
11296 // registered receivers separately so they don't wait for the
11297 // components to be launched.
11298 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11299 callerPackage, callingPid, callingUid, requiredPermission,
11300 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011301 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011302 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011303 TAG, "Enqueueing parallel broadcast " + r
11304 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011305 boolean replaced = false;
11306 if (replacePending) {
11307 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11308 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011309 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011310 "***** DROPPING PARALLEL: " + intent);
11311 mParallelBroadcasts.set(i, r);
11312 replaced = true;
11313 break;
11314 }
11315 }
11316 }
11317 if (!replaced) {
11318 mParallelBroadcasts.add(r);
11319 scheduleBroadcastsLocked();
11320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011321 registeredReceivers = null;
11322 NR = 0;
11323 }
11324
11325 // Merge into one list.
11326 int ir = 0;
11327 if (receivers != null) {
11328 // A special case for PACKAGE_ADDED: do not allow the package
11329 // being added to see this broadcast. This prevents them from
11330 // using this as a back door to get run as soon as they are
11331 // installed. Maybe in the future we want to have a special install
11332 // broadcast or such for apps, but we'd like to deliberately make
11333 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011334 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011335 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11336 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11337 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011338 Uri data = intent.getData();
11339 if (data != null) {
11340 String pkgName = data.getSchemeSpecificPart();
11341 if (pkgName != null) {
11342 skipPackages = new String[] { pkgName };
11343 }
11344 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011345 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011346 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011347 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011348 if (skipPackages != null && (skipPackages.length > 0)) {
11349 for (String skipPackage : skipPackages) {
11350 if (skipPackage != null) {
11351 int NT = receivers.size();
11352 for (int it=0; it<NT; it++) {
11353 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11354 if (curt.activityInfo.packageName.equals(skipPackage)) {
11355 receivers.remove(it);
11356 it--;
11357 NT--;
11358 }
11359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 }
11361 }
11362 }
11363
11364 int NT = receivers != null ? receivers.size() : 0;
11365 int it = 0;
11366 ResolveInfo curt = null;
11367 BroadcastFilter curr = null;
11368 while (it < NT && ir < NR) {
11369 if (curt == null) {
11370 curt = (ResolveInfo)receivers.get(it);
11371 }
11372 if (curr == null) {
11373 curr = registeredReceivers.get(ir);
11374 }
11375 if (curr.getPriority() >= curt.priority) {
11376 // Insert this broadcast record into the final list.
11377 receivers.add(it, curr);
11378 ir++;
11379 curr = null;
11380 it++;
11381 NT++;
11382 } else {
11383 // Skip to the next ResolveInfo in the final list.
11384 it++;
11385 curt = null;
11386 }
11387 }
11388 }
11389 while (ir < NR) {
11390 if (receivers == null) {
11391 receivers = new ArrayList();
11392 }
11393 receivers.add(registeredReceivers.get(ir));
11394 ir++;
11395 }
11396
11397 if ((receivers != null && receivers.size() > 0)
11398 || resultTo != null) {
11399 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11400 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011401 receivers, resultTo, resultCode, resultData, map, ordered,
11402 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011403 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011404 TAG, "Enqueueing ordered broadcast " + r
11405 + ": prev had " + mOrderedBroadcasts.size());
11406 if (DEBUG_BROADCAST) {
11407 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011408 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011409 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011410 boolean replaced = false;
11411 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011412 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011413 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011414 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011415 "***** DROPPING ORDERED: " + intent);
11416 mOrderedBroadcasts.set(i, r);
11417 replaced = true;
11418 break;
11419 }
11420 }
11421 }
11422 if (!replaced) {
11423 mOrderedBroadcasts.add(r);
11424 scheduleBroadcastsLocked();
11425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426 }
11427
11428 return BROADCAST_SUCCESS;
11429 }
11430
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011431 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432 // Refuse possible leaked file descriptors
11433 if (intent != null && intent.hasFileDescriptors() == true) {
11434 throw new IllegalArgumentException("File descriptors passed in Intent");
11435 }
11436
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011437 int flags = intent.getFlags();
11438
11439 if (!mProcessesReady) {
11440 // if the caller really truly claims to know what they're doing, go
11441 // ahead and allow the broadcast without launching any receivers
11442 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11443 intent = new Intent(intent);
11444 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11445 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11446 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11447 + " before boot completion");
11448 throw new IllegalStateException("Cannot broadcast before boot completed");
11449 }
11450 }
11451
11452 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11453 throw new IllegalArgumentException(
11454 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11455 }
11456
11457 return intent;
11458 }
11459
11460 public final int broadcastIntent(IApplicationThread caller,
11461 Intent intent, String resolvedType, IIntentReceiver resultTo,
11462 int resultCode, String resultData, Bundle map,
11463 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011464 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011465 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11468 final int callingPid = Binder.getCallingPid();
11469 final int callingUid = Binder.getCallingUid();
11470 final long origId = Binder.clearCallingIdentity();
11471 int res = broadcastIntentLocked(callerApp,
11472 callerApp != null ? callerApp.info.packageName : null,
11473 intent, resolvedType, resultTo,
11474 resultCode, resultData, map, requiredPermission, serialized,
11475 sticky, callingPid, callingUid);
11476 Binder.restoreCallingIdentity(origId);
11477 return res;
11478 }
11479 }
11480
11481 int broadcastIntentInPackage(String packageName, int uid,
11482 Intent intent, String resolvedType, IIntentReceiver resultTo,
11483 int resultCode, String resultData, Bundle map,
11484 String requiredPermission, boolean serialized, boolean sticky) {
11485 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011486 intent = verifyBroadcastLocked(intent);
11487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011488 final long origId = Binder.clearCallingIdentity();
11489 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11490 resultTo, resultCode, resultData, map, requiredPermission,
11491 serialized, sticky, -1, uid);
11492 Binder.restoreCallingIdentity(origId);
11493 return res;
11494 }
11495 }
11496
11497 public final void unbroadcastIntent(IApplicationThread caller,
11498 Intent intent) {
11499 // Refuse possible leaked file descriptors
11500 if (intent != null && intent.hasFileDescriptors() == true) {
11501 throw new IllegalArgumentException("File descriptors passed in Intent");
11502 }
11503
11504 synchronized(this) {
11505 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11506 != PackageManager.PERMISSION_GRANTED) {
11507 String msg = "Permission Denial: unbroadcastIntent() from pid="
11508 + Binder.getCallingPid()
11509 + ", uid=" + Binder.getCallingUid()
11510 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011511 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011512 throw new SecurityException(msg);
11513 }
11514 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11515 if (list != null) {
11516 int N = list.size();
11517 int i;
11518 for (i=0; i<N; i++) {
11519 if (intent.filterEquals(list.get(i))) {
11520 list.remove(i);
11521 break;
11522 }
11523 }
11524 }
11525 }
11526 }
11527
11528 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11529 String resultData, Bundle resultExtras, boolean resultAbort,
11530 boolean explicit) {
11531 if (mOrderedBroadcasts.size() == 0) {
11532 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011533 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011534 }
11535 return false;
11536 }
11537 BroadcastRecord r = mOrderedBroadcasts.get(0);
11538 if (r.receiver == null) {
11539 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011540 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541 }
11542 return false;
11543 }
11544 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011545 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011546 return false;
11547 }
11548 int state = r.state;
11549 r.state = r.IDLE;
11550 if (state == r.IDLE) {
11551 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011552 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011553 }
11554 }
11555 r.receiver = null;
11556 r.intent.setComponent(null);
11557 if (r.curApp != null) {
11558 r.curApp.curReceiver = null;
11559 }
11560 if (r.curFilter != null) {
11561 r.curFilter.receiverList.curBroadcast = null;
11562 }
11563 r.curFilter = null;
11564 r.curApp = null;
11565 r.curComponent = null;
11566 r.curReceiver = null;
11567 mPendingBroadcast = null;
11568
11569 r.resultCode = resultCode;
11570 r.resultData = resultData;
11571 r.resultExtras = resultExtras;
11572 r.resultAbort = resultAbort;
11573
11574 // We will process the next receiver right now if this is finishing
11575 // an app receiver (which is always asynchronous) or after we have
11576 // come back from calling a receiver.
11577 return state == BroadcastRecord.APP_RECEIVE
11578 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11579 }
11580
11581 public void finishReceiver(IBinder who, int resultCode, String resultData,
11582 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011583 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011584
11585 // Refuse possible leaked file descriptors
11586 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11587 throw new IllegalArgumentException("File descriptors passed in Bundle");
11588 }
11589
11590 boolean doNext;
11591
11592 final long origId = Binder.clearCallingIdentity();
11593
11594 synchronized(this) {
11595 doNext = finishReceiverLocked(
11596 who, resultCode, resultData, resultExtras, resultAbort, true);
11597 }
11598
11599 if (doNext) {
11600 processNextBroadcast(false);
11601 }
11602 trimApplications();
11603
11604 Binder.restoreCallingIdentity(origId);
11605 }
11606
Jeff Brown4d94a762010-09-23 11:33:28 -070011607 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011608 if (r.nextReceiver > 0) {
11609 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11610 if (curReceiver instanceof BroadcastFilter) {
11611 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011612 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011613 System.identityHashCode(r),
11614 r.intent.getAction(),
11615 r.nextReceiver - 1,
11616 System.identityHashCode(bf));
11617 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011618 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011619 System.identityHashCode(r),
11620 r.intent.getAction(),
11621 r.nextReceiver - 1,
11622 ((ResolveInfo)curReceiver).toString());
11623 }
11624 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011625 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011626 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011627 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628 System.identityHashCode(r),
11629 r.intent.getAction(),
11630 r.nextReceiver,
11631 "NONE");
11632 }
11633 }
11634
Jeff Brown4d94a762010-09-23 11:33:28 -070011635 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11636 if (! mPendingBroadcastTimeoutMessage) {
11637 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11638 mHandler.sendMessageAtTime(msg, timeoutTime);
11639 mPendingBroadcastTimeoutMessage = true;
11640 }
11641 }
11642
11643 private final void cancelBroadcastTimeoutLocked() {
11644 if (mPendingBroadcastTimeoutMessage) {
11645 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11646 mPendingBroadcastTimeoutMessage = false;
11647 }
11648 }
11649
11650 private final void broadcastTimeoutLocked(boolean fromMsg) {
11651 if (fromMsg) {
11652 mPendingBroadcastTimeoutMessage = false;
11653 }
11654
11655 if (mOrderedBroadcasts.size() == 0) {
11656 return;
11657 }
11658
11659 long now = SystemClock.uptimeMillis();
11660 BroadcastRecord r = mOrderedBroadcasts.get(0);
11661 if (fromMsg) {
11662 if (mDidDexOpt) {
11663 // Delay timeouts until dexopt finishes.
11664 mDidDexOpt = false;
11665 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11666 setBroadcastTimeoutLocked(timeoutTime);
11667 return;
11668 }
11669 if (! mProcessesReady) {
11670 // Only process broadcast timeouts if the system is ready. That way
11671 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11672 // to do heavy lifting for system up.
11673 return;
11674 }
11675
11676 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11677 if (timeoutTime > now) {
11678 // We can observe premature timeouts because we do not cancel and reset the
11679 // broadcast timeout message after each receiver finishes. Instead, we set up
11680 // an initial timeout then kick it down the road a little further as needed
11681 // when it expires.
11682 if (DEBUG_BROADCAST) Slog.v(TAG,
11683 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11684 + timeoutTime);
11685 setBroadcastTimeoutLocked(timeoutTime);
11686 return;
11687 }
11688 }
11689
11690 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11691 + ", started " + (now - r.receiverTime) + "ms ago");
11692 r.receiverTime = now;
11693 r.anrCount++;
11694
11695 // Current receiver has passed its expiration date.
11696 if (r.nextReceiver <= 0) {
11697 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11698 return;
11699 }
11700
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011701 ProcessRecord app = null;
11702 String anrMessage = null;
11703
Jeff Brown4d94a762010-09-23 11:33:28 -070011704 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11705 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11706 logBroadcastReceiverDiscardLocked(r);
11707 if (curReceiver instanceof BroadcastFilter) {
11708 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11709 if (bf.receiverList.pid != 0
11710 && bf.receiverList.pid != MY_PID) {
11711 synchronized (this.mPidsSelfLocked) {
11712 app = this.mPidsSelfLocked.get(
11713 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011715 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011716 } else {
11717 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011718 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011719
Jeff Brown4d94a762010-09-23 11:33:28 -070011720 if (app != null) {
11721 anrMessage = "Broadcast of " + r.intent.toString();
11722 }
11723
11724 if (mPendingBroadcast == r) {
11725 mPendingBroadcast = null;
11726 }
11727
11728 // Move on to the next receiver.
11729 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11730 r.resultExtras, r.resultAbort, true);
11731 scheduleBroadcastsLocked();
11732
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011733 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011734 // Post the ANR to the handler since we do not want to process ANRs while
11735 // potentially holding our lock.
11736 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011738 }
11739
11740 private final void processCurBroadcastLocked(BroadcastRecord r,
11741 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011742 if (DEBUG_BROADCAST) Slog.v(TAG,
11743 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011744 if (app.thread == null) {
11745 throw new RemoteException();
11746 }
11747 r.receiver = app.thread.asBinder();
11748 r.curApp = app;
11749 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011750 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011751
11752 // Tell the application to launch this receiver.
11753 r.intent.setComponent(r.curComponent);
11754
11755 boolean started = false;
11756 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011757 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011758 "Delivering to component " + r.curComponent
11759 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011760 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011761 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011762 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011764 if (DEBUG_BROADCAST) Slog.v(TAG,
11765 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011766 started = true;
11767 } finally {
11768 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011769 if (DEBUG_BROADCAST) Slog.v(TAG,
11770 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 r.receiver = null;
11772 r.curApp = null;
11773 app.curReceiver = null;
11774 }
11775 }
11776
11777 }
11778
Jeff Brown4d94a762010-09-23 11:33:28 -070011779 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011780 Intent intent, int resultCode, String data, Bundle extras,
11781 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011782 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011783 if (app != null && app.thread != null) {
11784 // If we have an app thread, do the call through that so it is
11785 // correctly ordered with other one-way calls.
11786 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011787 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011788 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011789 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011790 }
11791 }
11792
Jeff Brown4d94a762010-09-23 11:33:28 -070011793 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011794 BroadcastFilter filter, boolean ordered) {
11795 boolean skip = false;
11796 if (filter.requiredPermission != null) {
11797 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011798 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011799 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011800 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011801 + r.intent.toString()
11802 + " from " + r.callerPackage + " (pid="
11803 + r.callingPid + ", uid=" + r.callingUid + ")"
11804 + " requires " + filter.requiredPermission
11805 + " due to registered receiver " + filter);
11806 skip = true;
11807 }
11808 }
11809 if (r.requiredPermission != null) {
11810 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011811 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011812 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011813 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011814 + r.intent.toString()
11815 + " to " + filter.receiverList.app
11816 + " (pid=" + filter.receiverList.pid
11817 + ", uid=" + filter.receiverList.uid + ")"
11818 + " requires " + r.requiredPermission
11819 + " due to sender " + r.callerPackage
11820 + " (uid " + r.callingUid + ")");
11821 skip = true;
11822 }
11823 }
11824
11825 if (!skip) {
11826 // If this is not being sent as an ordered broadcast, then we
11827 // don't want to touch the fields that keep track of the current
11828 // state of ordered broadcasts.
11829 if (ordered) {
11830 r.receiver = filter.receiverList.receiver.asBinder();
11831 r.curFilter = filter;
11832 filter.receiverList.curBroadcast = r;
11833 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011834 if (filter.receiverList.app != null) {
11835 // Bump hosting application to no longer be in background
11836 // scheduling class. Note that we can't do that if there
11837 // isn't an app... but we can only be in that case for
11838 // things that directly call the IActivityManager API, which
11839 // are already core system stuff so don't matter for this.
11840 r.curApp = filter.receiverList.app;
11841 filter.receiverList.app.curReceiver = r;
11842 updateOomAdjLocked();
11843 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011844 }
11845 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011846 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011847 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011848 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011849 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011850 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011851 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011852 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011853 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011854 if (ordered) {
11855 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11856 }
11857 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011858 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011859 if (ordered) {
11860 r.receiver = null;
11861 r.curFilter = null;
11862 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011863 if (filter.receiverList.app != null) {
11864 filter.receiverList.app.curReceiver = null;
11865 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011866 }
11867 }
11868 }
11869 }
11870
Dianne Hackborn12527f92009-11-11 17:39:50 -080011871 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11872 if (r.callingUid < 0) {
11873 // This was from a registerReceiver() call; ignore it.
11874 return;
11875 }
11876 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11877 MAX_BROADCAST_HISTORY-1);
11878 r.finishTime = SystemClock.uptimeMillis();
11879 mBroadcastHistory[0] = r;
11880 }
11881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011882 private final void processNextBroadcast(boolean fromMsg) {
11883 synchronized(this) {
11884 BroadcastRecord r;
11885
Joe Onorato8a9b2202010-02-26 18:56:32 -080011886 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011887 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011888 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011889
11890 updateCpuStats();
11891
11892 if (fromMsg) {
11893 mBroadcastsScheduled = false;
11894 }
11895
11896 // First, deliver any non-serialized broadcasts right away.
11897 while (mParallelBroadcasts.size() > 0) {
11898 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011899 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011900 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011901 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011902 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 for (int i=0; i<N; i++) {
11904 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011905 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011906 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011907 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011908 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011909 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011910 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011911 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011912 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011913 }
11914
11915 // Now take care of the next serialized one...
11916
11917 // If we are waiting for a process to come up to handle the next
11918 // broadcast, then do nothing at this point. Just in case, we
11919 // check that the process we're waiting for still exists.
11920 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011921 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011922 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011923 + mPendingBroadcast.curApp);
11924 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011925
11926 boolean isDead;
11927 synchronized (mPidsSelfLocked) {
11928 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11929 }
11930 if (!isDead) {
11931 // It's still alive, so keep waiting
11932 return;
11933 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011934 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011935 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011936 mPendingBroadcast.state = BroadcastRecord.IDLE;
11937 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011938 mPendingBroadcast = null;
11939 }
11940 }
11941
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011942 boolean looped = false;
11943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011944 do {
11945 if (mOrderedBroadcasts.size() == 0) {
11946 // No more broadcasts pending, so all done!
11947 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011948 if (looped) {
11949 // If we had finished the last ordered broadcast, then
11950 // make sure all processes have correct oom and sched
11951 // adjustments.
11952 updateOomAdjLocked();
11953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011954 return;
11955 }
11956 r = mOrderedBroadcasts.get(0);
11957 boolean forceReceive = false;
11958
11959 // Ensure that even if something goes awry with the timeout
11960 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011961 // and continue to make progress.
11962 //
11963 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011964 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011965 // one time heavy lifting after system upgrades and can take
11966 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011967 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011968 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011969 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011970 if ((numReceivers > 0) &&
11971 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011972 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011973 + " now=" + now
11974 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011975 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011976 + " intent=" + r.intent
11977 + " numReceivers=" + numReceivers
11978 + " nextReceiver=" + r.nextReceiver
11979 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011980 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011981 forceReceive = true;
11982 r.state = BroadcastRecord.IDLE;
11983 }
11984 }
11985
11986 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011987 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011988 "processNextBroadcast() called when not idle (state="
11989 + r.state + ")");
11990 return;
11991 }
11992
11993 if (r.receivers == null || r.nextReceiver >= numReceivers
11994 || r.resultAbort || forceReceive) {
11995 // No more receivers for this broadcast! Send the final
11996 // result if requested...
11997 if (r.resultTo != null) {
11998 try {
11999 if (DEBUG_BROADCAST) {
12000 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012001 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012002 + " seq=" + seq + " app=" + r.callerApp);
12003 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012004 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012005 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012006 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020012007 // Set this to null so that the reference
12008 // (local and remote) isnt kept in the mBroadcastHistory.
12009 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012010 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012011 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012012 }
12013 }
12014
Joe Onorato8a9b2202010-02-26 18:56:32 -080012015 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070012016 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017
Joe Onorato8a9b2202010-02-26 18:56:32 -080012018 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012019 + r);
12020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012021 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012022 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012023 mOrderedBroadcasts.remove(0);
12024 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012025 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012026 continue;
12027 }
12028 } while (r == null);
12029
12030 // Get the next receiver...
12031 int recIdx = r.nextReceiver++;
12032
12033 // Keep track of when this receiver started, and make sure there
12034 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012035 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012036 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012037 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012038
Joe Onorato8a9b2202010-02-26 18:56:32 -080012039 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012040 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012041 }
12042 if (! mPendingBroadcastTimeoutMessage) {
12043 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012044 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070012045 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
12046 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012047 }
12048
12049 Object nextReceiver = r.receivers.get(recIdx);
12050 if (nextReceiver instanceof BroadcastFilter) {
12051 // Simple case: this is a registered receiver who gets
12052 // a direct call.
12053 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012054 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012055 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012056 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012057 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012058 if (r.receiver == null || !r.ordered) {
12059 // The receiver has already finished, so schedule to
12060 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012061 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
12062 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012063 r.state = BroadcastRecord.IDLE;
12064 scheduleBroadcastsLocked();
12065 }
12066 return;
12067 }
12068
12069 // Hard case: need to instantiate the receiver, possibly
12070 // starting its application process to host it.
12071
12072 ResolveInfo info =
12073 (ResolveInfo)nextReceiver;
12074
12075 boolean skip = false;
12076 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012077 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
12078 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012079 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012080 if (!info.activityInfo.exported) {
12081 Slog.w(TAG, "Permission Denial: broadcasting "
12082 + r.intent.toString()
12083 + " from " + r.callerPackage + " (pid=" + r.callingPid
12084 + ", uid=" + r.callingUid + ")"
12085 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
12086 + " due to receiver " + info.activityInfo.packageName
12087 + "/" + info.activityInfo.name);
12088 } else {
12089 Slog.w(TAG, "Permission Denial: broadcasting "
12090 + r.intent.toString()
12091 + " from " + r.callerPackage + " (pid=" + r.callingPid
12092 + ", uid=" + r.callingUid + ")"
12093 + " requires " + info.activityInfo.permission
12094 + " due to receiver " + info.activityInfo.packageName
12095 + "/" + info.activityInfo.name);
12096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012097 skip = true;
12098 }
12099 if (r.callingUid != Process.SYSTEM_UID &&
12100 r.requiredPermission != null) {
12101 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012102 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012103 checkPermission(r.requiredPermission,
12104 info.activityInfo.applicationInfo.packageName);
12105 } catch (RemoteException e) {
12106 perm = PackageManager.PERMISSION_DENIED;
12107 }
12108 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012109 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012110 + r.intent + " to "
12111 + info.activityInfo.applicationInfo.packageName
12112 + " requires " + r.requiredPermission
12113 + " due to sender " + r.callerPackage
12114 + " (uid " + r.callingUid + ")");
12115 skip = true;
12116 }
12117 }
12118 if (r.curApp != null && r.curApp.crashing) {
12119 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012120 if (DEBUG_BROADCAST) Slog.v(TAG,
12121 "Skipping deliver ordered " + r + " to " + r.curApp
12122 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012123 skip = true;
12124 }
12125
12126 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012127 if (DEBUG_BROADCAST) Slog.v(TAG,
12128 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012129 r.receiver = null;
12130 r.curFilter = null;
12131 r.state = BroadcastRecord.IDLE;
12132 scheduleBroadcastsLocked();
12133 return;
12134 }
12135
12136 r.state = BroadcastRecord.APP_RECEIVE;
12137 String targetProcess = info.activityInfo.processName;
12138 r.curComponent = new ComponentName(
12139 info.activityInfo.applicationInfo.packageName,
12140 info.activityInfo.name);
12141 r.curReceiver = info.activityInfo;
12142
Dianne Hackborne7f97212011-02-24 14:40:20 -080012143 // Broadcast is being executed, its package can't be stopped.
12144 try {
12145 AppGlobals.getPackageManager().setPackageStoppedState(
12146 r.curComponent.getPackageName(), false);
12147 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012148 } catch (IllegalArgumentException e) {
12149 Slog.w(TAG, "Failed trying to unstop package "
12150 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012151 }
12152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012153 // Is this receiver's application already running?
12154 ProcessRecord app = getProcessRecordLocked(targetProcess,
12155 info.activityInfo.applicationInfo.uid);
12156 if (app != null && app.thread != null) {
12157 try {
12158 processCurBroadcastLocked(r, app);
12159 return;
12160 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012161 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012162 + r.curComponent, e);
12163 }
12164
12165 // If a dead object exception was thrown -- fall through to
12166 // restart the application.
12167 }
12168
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012169 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012170 if (DEBUG_BROADCAST) Slog.v(TAG,
12171 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012172 if ((r.curApp=startProcessLocked(targetProcess,
12173 info.activityInfo.applicationInfo, true,
12174 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012175 "broadcast", r.curComponent,
12176 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12177 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012178 // Ah, this recipient is unavailable. Finish it if necessary,
12179 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012180 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012181 + info.activityInfo.applicationInfo.packageName + "/"
12182 + info.activityInfo.applicationInfo.uid + " for broadcast "
12183 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070012184 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012185 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12186 r.resultExtras, r.resultAbort, true);
12187 scheduleBroadcastsLocked();
12188 r.state = BroadcastRecord.IDLE;
12189 return;
12190 }
12191
12192 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012193 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012194 }
12195 }
12196
12197 // =========================================================
12198 // INSTRUMENTATION
12199 // =========================================================
12200
12201 public boolean startInstrumentation(ComponentName className,
12202 String profileFile, int flags, Bundle arguments,
12203 IInstrumentationWatcher watcher) {
12204 // Refuse possible leaked file descriptors
12205 if (arguments != null && arguments.hasFileDescriptors()) {
12206 throw new IllegalArgumentException("File descriptors passed in Bundle");
12207 }
12208
12209 synchronized(this) {
12210 InstrumentationInfo ii = null;
12211 ApplicationInfo ai = null;
12212 try {
12213 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012214 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012215 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012216 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012217 } catch (PackageManager.NameNotFoundException e) {
12218 }
12219 if (ii == null) {
12220 reportStartInstrumentationFailure(watcher, className,
12221 "Unable to find instrumentation info for: " + className);
12222 return false;
12223 }
12224 if (ai == null) {
12225 reportStartInstrumentationFailure(watcher, className,
12226 "Unable to find instrumentation target package: " + ii.targetPackage);
12227 return false;
12228 }
12229
12230 int match = mContext.getPackageManager().checkSignatures(
12231 ii.targetPackage, ii.packageName);
12232 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12233 String msg = "Permission Denial: starting instrumentation "
12234 + className + " from pid="
12235 + Binder.getCallingPid()
12236 + ", uid=" + Binder.getCallingPid()
12237 + " not allowed because package " + ii.packageName
12238 + " does not have a signature matching the target "
12239 + ii.targetPackage;
12240 reportStartInstrumentationFailure(watcher, className, msg);
12241 throw new SecurityException(msg);
12242 }
12243
12244 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012245 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012246 ProcessRecord app = addAppLocked(ai);
12247 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012248 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012249 app.instrumentationProfileFile = profileFile;
12250 app.instrumentationArguments = arguments;
12251 app.instrumentationWatcher = watcher;
12252 app.instrumentationResultClass = className;
12253 Binder.restoreCallingIdentity(origId);
12254 }
12255
12256 return true;
12257 }
12258
12259 /**
12260 * Report errors that occur while attempting to start Instrumentation. Always writes the
12261 * error to the logs, but if somebody is watching, send the report there too. This enables
12262 * the "am" command to report errors with more information.
12263 *
12264 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12265 * @param cn The component name of the instrumentation.
12266 * @param report The error report.
12267 */
12268 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12269 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012270 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012271 try {
12272 if (watcher != null) {
12273 Bundle results = new Bundle();
12274 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12275 results.putString("Error", report);
12276 watcher.instrumentationStatus(cn, -1, results);
12277 }
12278 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012279 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012280 }
12281 }
12282
12283 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12284 if (app.instrumentationWatcher != null) {
12285 try {
12286 // NOTE: IInstrumentationWatcher *must* be oneway here
12287 app.instrumentationWatcher.instrumentationFinished(
12288 app.instrumentationClass,
12289 resultCode,
12290 results);
12291 } catch (RemoteException e) {
12292 }
12293 }
12294 app.instrumentationWatcher = null;
12295 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012296 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012297 app.instrumentationProfileFile = null;
12298 app.instrumentationArguments = null;
12299
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012300 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012301 }
12302
12303 public void finishInstrumentation(IApplicationThread target,
12304 int resultCode, Bundle results) {
12305 // Refuse possible leaked file descriptors
12306 if (results != null && results.hasFileDescriptors()) {
12307 throw new IllegalArgumentException("File descriptors passed in Intent");
12308 }
12309
12310 synchronized(this) {
12311 ProcessRecord app = getRecordForAppLocked(target);
12312 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012313 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012314 return;
12315 }
12316 final long origId = Binder.clearCallingIdentity();
12317 finishInstrumentationLocked(app, resultCode, results);
12318 Binder.restoreCallingIdentity(origId);
12319 }
12320 }
12321
12322 // =========================================================
12323 // CONFIGURATION
12324 // =========================================================
12325
12326 public ConfigurationInfo getDeviceConfigurationInfo() {
12327 ConfigurationInfo config = new ConfigurationInfo();
12328 synchronized (this) {
12329 config.reqTouchScreen = mConfiguration.touchscreen;
12330 config.reqKeyboardType = mConfiguration.keyboard;
12331 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012332 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12333 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012334 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12335 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012336 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12337 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012338 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12339 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012340 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012341 }
12342 return config;
12343 }
12344
12345 public Configuration getConfiguration() {
12346 Configuration ci;
12347 synchronized(this) {
12348 ci = new Configuration(mConfiguration);
12349 }
12350 return ci;
12351 }
12352
12353 public void updateConfiguration(Configuration values) {
12354 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12355 "updateConfiguration()");
12356
12357 synchronized(this) {
12358 if (values == null && mWindowManager != null) {
12359 // sentinel: fetch the current configuration from the window manager
12360 values = mWindowManager.computeNewConfiguration();
12361 }
12362
12363 final long origId = Binder.clearCallingIdentity();
12364 updateConfigurationLocked(values, null);
12365 Binder.restoreCallingIdentity(origId);
12366 }
12367 }
12368
12369 /**
12370 * Do either or both things: (1) change the current configuration, and (2)
12371 * make sure the given activity is running with the (now) current
12372 * configuration. Returns true if the activity has been left running, or
12373 * false if <var>starting</var> is being destroyed to match the new
12374 * configuration.
12375 */
12376 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012377 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012378 int changes = 0;
12379
12380 boolean kept = true;
12381
12382 if (values != null) {
12383 Configuration newConfig = new Configuration(mConfiguration);
12384 changes = newConfig.updateFrom(values);
12385 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012386 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012387 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012388 }
12389
Doug Zongker2bec3d42009-12-04 12:52:44 -080012390 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012391
12392 if (values.locale != null) {
12393 saveLocaleLocked(values.locale,
12394 !values.locale.equals(mConfiguration.locale),
12395 values.userSetLocale);
12396 }
12397
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012398 mConfigurationSeq++;
12399 if (mConfigurationSeq <= 0) {
12400 mConfigurationSeq = 1;
12401 }
12402 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012403 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012404 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012405
12406 AttributeCache ac = AttributeCache.instance();
12407 if (ac != null) {
12408 ac.updateConfiguration(mConfiguration);
12409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012410
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070012411 // Make sure all resources in our process are updated
12412 // right now, so that anyone who is going to retrieve
12413 // resource values after we return will be sure to get
12414 // the new ones. This is especially important during
12415 // boot, where the first config change needs to guarantee
12416 // all resources have that config before following boot
12417 // code is executed.
12418 mSystemThread.applyConfigurationToResources(newConfig);
12419
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012420 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
12421 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12422 msg.obj = new Configuration(mConfiguration);
12423 mHandler.sendMessage(msg);
12424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012425
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012426 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12427 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012428 try {
12429 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012430 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012431 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012432 app.thread.scheduleConfigurationChanged(mConfiguration);
12433 }
12434 } catch (Exception e) {
12435 }
12436 }
12437 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012438 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12439 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012440 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12441 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012442 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12443 broadcastIntentLocked(null, null,
12444 new Intent(Intent.ACTION_LOCALE_CHANGED),
12445 null, null, 0, null, null,
12446 null, false, false, MY_PID, Process.SYSTEM_UID);
12447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012448 }
12449 }
12450
12451 if (changes != 0 && starting == null) {
12452 // If the configuration changed, and the caller is not already
12453 // in the process of starting an activity, then find the top
12454 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012455 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012456 }
12457
12458 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012459 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012460 // And we need to make sure at this point that all other activities
12461 // are made visible with the correct configuration.
12462 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012463 }
12464
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012465 if (values != null && mWindowManager != null) {
12466 mWindowManager.setNewConfiguration(mConfiguration);
12467 }
12468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012469 return kept;
12470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012471
12472 /**
12473 * Save the locale. You must be inside a synchronized (this) block.
12474 */
12475 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12476 if(isDiff) {
12477 SystemProperties.set("user.language", l.getLanguage());
12478 SystemProperties.set("user.region", l.getCountry());
12479 }
12480
12481 if(isPersist) {
12482 SystemProperties.set("persist.sys.language", l.getLanguage());
12483 SystemProperties.set("persist.sys.country", l.getCountry());
12484 SystemProperties.set("persist.sys.localevar", l.getVariant());
12485 }
12486 }
12487
12488 // =========================================================
12489 // LIFETIME MANAGEMENT
12490 // =========================================================
12491
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012492 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12493 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012494 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012495 // This adjustment has already been computed. If we are calling
12496 // from the top, we may have already computed our adjustment with
12497 // an earlier hidden adjustment that isn't really for us... if
12498 // so, use the new hidden adjustment.
12499 if (!recursed && app.hidden) {
12500 app.curAdj = hiddenAdj;
12501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012502 return app.curAdj;
12503 }
12504
12505 if (app.thread == null) {
12506 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012507 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012508 return (app.curAdj=EMPTY_APP_ADJ);
12509 }
12510
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012511 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12512 // The max adjustment doesn't allow this app to be anything
12513 // below foreground, so it is not worth doing work for it.
12514 app.adjType = "fixed";
12515 app.adjSeq = mAdjSeq;
12516 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012517 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012518 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12519 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012520 }
12521
12522 final boolean hadForegroundActivities = app.foregroundActivities;
12523
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012524 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012525 app.adjSource = null;
12526 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012527 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012528 app.empty = false;
12529 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012530 app.foregroundActivities = false;
12531
12532 final int activitiesSize = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012533
The Android Open Source Project4df24232009-03-05 14:34:35 -080012534 // Determine the importance of the process, starting with most
12535 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012536 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012537 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012538 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012539 // The last app on the list is the foreground app.
12540 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012541 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012542 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012543 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012544 } else if (app.instrumentationClass != null) {
12545 // Don't want to kill running instrumentation.
12546 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012547 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012548 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012549 } else if (app.curReceiver != null ||
12550 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12551 // An app that is currently receiving a broadcast also
12552 // counts as being in the foreground.
12553 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012554 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012555 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012556 } else if (app.executingServices.size() > 0) {
12557 // An app that is currently executing a service callback also
12558 // counts as being in the foreground.
12559 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012560 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012561 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012562 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012563 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012564 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012565 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012566 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012567 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012568 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012569 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012570 // A very not-needed process. If this is lower in the lru list,
12571 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012572 adj = hiddenAdj;
12573 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012574 app.hidden = true;
12575 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012576 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012577 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012578
12579 // Examine all activities if not already foreground.
12580 if (!app.foregroundActivities && activitiesSize > 0) {
12581 for (int j = 0; j < activitiesSize; j++) {
12582 final ActivityRecord r = app.activities.get(j);
12583 if (r.visible) {
12584 // App has a visible activity; only upgrade adjustment.
12585 if (adj > VISIBLE_APP_ADJ) {
12586 adj = VISIBLE_APP_ADJ;
12587 app.adjType = "visible";
12588 }
12589 schedGroup = Process.THREAD_GROUP_DEFAULT;
12590 app.hidden = false;
12591 app.foregroundActivities = true;
12592 break;
12593 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
12594 || r.state == ActivityState.STOPPING) {
12595 // Only upgrade adjustment.
12596 if (adj > PERCEPTIBLE_APP_ADJ) {
12597 adj = PERCEPTIBLE_APP_ADJ;
12598 app.adjType = "stopping";
12599 }
12600 app.foregroundActivities = true;
12601 }
12602 }
12603 }
12604
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012605 if (adj > PERCEPTIBLE_APP_ADJ) {
12606 if (app.foregroundServices) {
12607 // The user is aware of this app, so make it visible.
12608 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012609 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012610 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012611 } else if (app.forcingToForeground != null) {
12612 // The user is aware of this app, so make it visible.
12613 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012614 app.adjType = "force-foreground";
12615 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012616 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012617 }
12618 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012619
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012620 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12621 // We don't want to kill the current heavy-weight process.
12622 adj = HEAVY_WEIGHT_APP_ADJ;
12623 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12624 app.adjType = "heavy";
12625 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012626
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012627 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12628 // This process is hosting what we currently consider to be the
12629 // home app, so we don't want to let it go into the background.
12630 adj = HOME_APP_ADJ;
12631 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12632 app.adjType = "home";
12633 }
12634
Joe Onorato8a9b2202010-02-26 18:56:32 -080012635 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012636
The Android Open Source Project4df24232009-03-05 14:34:35 -080012637 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012638 // there are applications dependent on our services or providers, but
12639 // this gives us a baseline and makes sure we don't get into an
12640 // infinite recursion.
12641 app.adjSeq = mAdjSeq;
12642 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012643
Christopher Tate6fa95972009-06-05 18:43:55 -070012644 if (mBackupTarget != null && app == mBackupTarget.app) {
12645 // If possible we want to avoid killing apps while they're being backed up
12646 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012647 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012648 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012649 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012650 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012651 }
12652 }
12653
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012654 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12655 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012656 final long now = SystemClock.uptimeMillis();
12657 // This process is more important if the top activity is
12658 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012659 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012660 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012661 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012662 if (s.startRequested) {
12663 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12664 // This service has seen some activity within
12665 // recent memory, so we will keep its process ahead
12666 // of the background processes.
12667 if (adj > SECONDARY_SERVER_ADJ) {
12668 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012669 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012670 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012671 }
12672 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012673 // If we have let the service slide into the background
12674 // state, still have some text describing what it is doing
12675 // even though the service no longer has an impact.
12676 if (adj > SECONDARY_SERVER_ADJ) {
12677 app.adjType = "started-bg-services";
12678 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012679 // Don't kill this process because it is doing work; it
12680 // has said it is doing work.
12681 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012682 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012683 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12684 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012685 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012686 = s.connections.values().iterator();
12687 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012688 ArrayList<ConnectionRecord> clist = kt.next();
12689 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12690 // XXX should compute this based on the max of
12691 // all connected clients.
12692 ConnectionRecord cr = clist.get(i);
12693 if (cr.binding.client == app) {
12694 // Binding to ourself is not interesting.
12695 continue;
12696 }
12697 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12698 ProcessRecord client = cr.binding.client;
12699 int myHiddenAdj = hiddenAdj;
12700 if (myHiddenAdj > client.hiddenAdj) {
12701 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12702 myHiddenAdj = client.hiddenAdj;
12703 } else {
12704 myHiddenAdj = VISIBLE_APP_ADJ;
12705 }
12706 }
12707 int clientAdj = computeOomAdjLocked(
12708 client, myHiddenAdj, TOP_APP, true);
12709 if (adj > clientAdj) {
12710 adj = clientAdj >= VISIBLE_APP_ADJ
12711 ? clientAdj : VISIBLE_APP_ADJ;
12712 if (!client.hidden) {
12713 app.hidden = false;
12714 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012715 if (client.keeping) {
12716 app.keeping = true;
12717 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012718 app.adjType = "service";
12719 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12720 .REASON_SERVICE_IN_USE;
12721 app.adjSource = cr.binding.client;
12722 app.adjTarget = s.name;
12723 }
12724 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12725 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12726 schedGroup = Process.THREAD_GROUP_DEFAULT;
12727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012728 }
12729 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012730 ActivityRecord a = cr.activity;
12731 //if (a != null) {
12732 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12733 //}
12734 if (a != null && adj > FOREGROUND_APP_ADJ &&
12735 (a.state == ActivityState.RESUMED
12736 || a.state == ActivityState.PAUSING)) {
12737 adj = FOREGROUND_APP_ADJ;
12738 schedGroup = Process.THREAD_GROUP_DEFAULT;
12739 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012740 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012741 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12742 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012743 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012744 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012745 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012746 }
12747 }
12748 }
12749 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012750
Dianne Hackborn287952c2010-09-22 22:34:31 -070012751 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012752 // would like to avoid killing it unless it would prevent the current
12753 // application from running. By default we put the process in
12754 // with the rest of the background processes; as we scan through
12755 // its services we may bump it up from there.
12756 if (adj > hiddenAdj) {
12757 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012758 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012759 app.adjType = "bg-services";
12760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012761 }
12762
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012763 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12764 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012765 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012766 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12767 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012768 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012769 if (cpr.clients.size() != 0) {
12770 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12771 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12772 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012773 if (client == app) {
12774 // Being our own client is not interesting.
12775 continue;
12776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012777 int myHiddenAdj = hiddenAdj;
12778 if (myHiddenAdj > client.hiddenAdj) {
12779 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12780 myHiddenAdj = client.hiddenAdj;
12781 } else {
12782 myHiddenAdj = FOREGROUND_APP_ADJ;
12783 }
12784 }
12785 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012786 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012787 if (adj > clientAdj) {
12788 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012789 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012790 if (!client.hidden) {
12791 app.hidden = false;
12792 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012793 if (client.keeping) {
12794 app.keeping = true;
12795 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012796 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012797 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12798 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012799 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012800 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012801 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012802 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12803 schedGroup = Process.THREAD_GROUP_DEFAULT;
12804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012805 }
12806 }
12807 // If the provider has external (non-framework) process
12808 // dependencies, ensure that its adjustment is at least
12809 // FOREGROUND_APP_ADJ.
12810 if (cpr.externals != 0) {
12811 if (adj > FOREGROUND_APP_ADJ) {
12812 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012813 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012814 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012815 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012816 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012817 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012818 }
12819 }
12820 }
12821 }
12822
12823 app.curRawAdj = adj;
12824
Joe Onorato8a9b2202010-02-26 18:56:32 -080012825 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012826 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12827 if (adj > app.maxAdj) {
12828 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012829 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012830 schedGroup = Process.THREAD_GROUP_DEFAULT;
12831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012832 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012833 if (adj < HIDDEN_APP_MIN_ADJ) {
12834 app.keeping = true;
12835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012836
12837 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012838 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012839
12840 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070012841 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
12842 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012843 }
12844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012845 return adj;
12846 }
12847
12848 /**
12849 * Ask a given process to GC right now.
12850 */
12851 final void performAppGcLocked(ProcessRecord app) {
12852 try {
12853 app.lastRequestedGc = SystemClock.uptimeMillis();
12854 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012855 if (app.reportLowMemory) {
12856 app.reportLowMemory = false;
12857 app.thread.scheduleLowMemory();
12858 } else {
12859 app.thread.processInBackground();
12860 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012861 }
12862 } catch (Exception e) {
12863 // whatever.
12864 }
12865 }
12866
12867 /**
12868 * Returns true if things are idle enough to perform GCs.
12869 */
Josh Bartel7f208742010-02-25 11:01:44 -060012870 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012871 return mParallelBroadcasts.size() == 0
12872 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012873 && (mSleeping || (mMainStack.mResumedActivity != null &&
12874 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012875 }
12876
12877 /**
12878 * Perform GCs on all processes that are waiting for it, but only
12879 * if things are idle.
12880 */
12881 final void performAppGcsLocked() {
12882 final int N = mProcessesToGc.size();
12883 if (N <= 0) {
12884 return;
12885 }
Josh Bartel7f208742010-02-25 11:01:44 -060012886 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012887 while (mProcessesToGc.size() > 0) {
12888 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012889 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012890 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12891 <= SystemClock.uptimeMillis()) {
12892 // To avoid spamming the system, we will GC processes one
12893 // at a time, waiting a few seconds between each.
12894 performAppGcLocked(proc);
12895 scheduleAppGcsLocked();
12896 return;
12897 } else {
12898 // It hasn't been long enough since we last GCed this
12899 // process... put it in the list to wait for its time.
12900 addProcessToGcListLocked(proc);
12901 break;
12902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012903 }
12904 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012905
12906 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012907 }
12908 }
12909
12910 /**
12911 * If all looks good, perform GCs on all processes waiting for them.
12912 */
12913 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012914 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012915 performAppGcsLocked();
12916 return;
12917 }
12918 // Still not idle, wait some more.
12919 scheduleAppGcsLocked();
12920 }
12921
12922 /**
12923 * Schedule the execution of all pending app GCs.
12924 */
12925 final void scheduleAppGcsLocked() {
12926 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012927
12928 if (mProcessesToGc.size() > 0) {
12929 // Schedule a GC for the time to the next process.
12930 ProcessRecord proc = mProcessesToGc.get(0);
12931 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12932
12933 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12934 long now = SystemClock.uptimeMillis();
12935 if (when < (now+GC_TIMEOUT)) {
12936 when = now + GC_TIMEOUT;
12937 }
12938 mHandler.sendMessageAtTime(msg, when);
12939 }
12940 }
12941
12942 /**
12943 * Add a process to the array of processes waiting to be GCed. Keeps the
12944 * list in sorted order by the last GC time. The process can't already be
12945 * on the list.
12946 */
12947 final void addProcessToGcListLocked(ProcessRecord proc) {
12948 boolean added = false;
12949 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12950 if (mProcessesToGc.get(i).lastRequestedGc <
12951 proc.lastRequestedGc) {
12952 added = true;
12953 mProcessesToGc.add(i+1, proc);
12954 break;
12955 }
12956 }
12957 if (!added) {
12958 mProcessesToGc.add(0, proc);
12959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012960 }
12961
12962 /**
12963 * Set up to ask a process to GC itself. This will either do it
12964 * immediately, or put it on the list of processes to gc the next
12965 * time things are idle.
12966 */
12967 final void scheduleAppGcLocked(ProcessRecord app) {
12968 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012969 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012970 return;
12971 }
12972 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012973 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012974 scheduleAppGcsLocked();
12975 }
12976 }
12977
Dianne Hackborn287952c2010-09-22 22:34:31 -070012978 final void checkExcessivePowerUsageLocked(boolean doKills) {
12979 updateCpuStatsNow();
12980
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012981 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012982 boolean doWakeKills = doKills;
12983 boolean doCpuKills = doKills;
12984 if (mLastPowerCheckRealtime == 0) {
12985 doWakeKills = false;
12986 }
12987 if (mLastPowerCheckUptime == 0) {
12988 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012989 }
12990 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012991 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012992 }
12993 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012994 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12995 final long curUptime = SystemClock.uptimeMillis();
12996 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12997 mLastPowerCheckRealtime = curRealtime;
12998 mLastPowerCheckUptime = curUptime;
12999 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
13000 doWakeKills = false;
13001 }
13002 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
13003 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013004 }
13005 int i = mLruProcesses.size();
13006 while (i > 0) {
13007 i--;
13008 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013009 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013010 long wtime;
13011 synchronized (stats) {
13012 wtime = stats.getProcessWakeTime(app.info.uid,
13013 app.pid, curRealtime);
13014 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013015 long wtimeUsed = wtime - app.lastWakeTime;
13016 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
13017 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013018 StringBuilder sb = new StringBuilder(128);
13019 sb.append("Wake for ");
13020 app.toShortString(sb);
13021 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013022 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013023 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013024 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013025 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013026 sb.append((wtimeUsed*100)/realtimeSince);
13027 sb.append("%)");
13028 Slog.i(TAG, sb.toString());
13029 sb.setLength(0);
13030 sb.append("CPU for ");
13031 app.toShortString(sb);
13032 sb.append(": over ");
13033 TimeUtils.formatDuration(uptimeSince, sb);
13034 sb.append(" used ");
13035 TimeUtils.formatDuration(cputimeUsed, sb);
13036 sb.append(" (");
13037 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013038 sb.append("%)");
13039 Slog.i(TAG, sb.toString());
13040 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013041 // If a process has held a wake lock for more
13042 // than 50% of the time during this period,
13043 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070013044 if (doWakeKills && realtimeSince > 0
13045 && ((wtimeUsed*100)/realtimeSince) >= 50) {
13046 synchronized (stats) {
13047 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
13048 realtimeSince, wtimeUsed);
13049 }
13050 Slog.w(TAG, "Excessive wake lock in " + app.processName
13051 + " (pid " + app.pid + "): held " + wtimeUsed
13052 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013053 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13054 app.processName, app.setAdj, "excessive wake lock");
13055 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013056 } else if (doCpuKills && uptimeSince > 0
13057 && ((cputimeUsed*100)/uptimeSince) >= 50) {
13058 synchronized (stats) {
13059 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
13060 uptimeSince, cputimeUsed);
13061 }
13062 Slog.w(TAG, "Excessive CPU in " + app.processName
13063 + " (pid " + app.pid + "): used " + cputimeUsed
13064 + " during " + uptimeSince);
13065 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13066 app.processName, app.setAdj, "excessive cpu");
13067 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013068 } else {
13069 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013070 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013071 }
13072 }
13073 }
13074 }
13075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013076 private final boolean updateOomAdjLocked(
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013077 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013078 app.hiddenAdj = hiddenAdj;
13079
13080 if (app.thread == null) {
13081 return true;
13082 }
13083
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013084 boolean success = true;
13085
Dianne Hackborn287952c2010-09-22 22:34:31 -070013086 final boolean wasKeeping = app.keeping;
13087
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013088 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013089
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013090 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013091 if (app.curRawAdj != app.setRawAdj) {
13092 if (app.curRawAdj > FOREGROUND_APP_ADJ
13093 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13094 // If this app is transitioning from foreground to
13095 // non-foreground, have it do a gc.
13096 scheduleAppGcLocked(app);
13097 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13098 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13099 // Likewise do a gc when an app is moving in to the
13100 // background (such as a service stopping).
13101 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013102 }
13103
13104 if (wasKeeping && !app.keeping) {
13105 // This app is no longer something we want to keep. Note
13106 // its current wake lock time to later know to kill it if
13107 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013108 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
13109 synchronized (stats) {
13110 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
13111 app.pid, SystemClock.elapsedRealtime());
13112 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013113 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013114 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013116 app.setRawAdj = app.curRawAdj;
13117 }
13118 if (adj != app.setAdj) {
13119 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013120 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013121 TAG, "Set app " + app.processName +
13122 " oom adj to " + adj);
13123 app.setAdj = adj;
13124 } else {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013125 success = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013126 }
13127 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013128 if (app.setSchedGroup != app.curSchedGroup) {
13129 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013130 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013131 "Setting process group of " + app.processName
13132 + " to " + app.curSchedGroup);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013133 if (app.waitingToKill != null &&
13134 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
13135 Slog.i(TAG, "Killing " + app + ": " + app.waitingToKill);
13136 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13137 app.processName, app.setAdj, app.waitingToKill);
13138 Process.killProcessQuiet(app.pid);
13139 } else {
13140 if (true) {
13141 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013142 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013143 Process.setProcessGroup(app.pid, app.curSchedGroup);
13144 } catch (Exception e) {
13145 Slog.w(TAG, "Failed setting process group of " + app.pid
13146 + " to " + app.curSchedGroup);
13147 e.printStackTrace();
13148 } finally {
13149 Binder.restoreCallingIdentity(oldId);
13150 }
13151 }
13152 if (false) {
13153 if (app.thread != null) {
13154 try {
13155 app.thread.setSchedulingGroup(app.curSchedGroup);
13156 } catch (RemoteException e) {
13157 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013158 }
13159 }
13160 }
13161 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013162 }
13163
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013164 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013165 }
13166
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013167 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013168 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013169 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013170 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013171 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013172 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013173 }
13174 }
13175 return resumedActivity;
13176 }
13177
13178 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013179 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013180 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13181 int curAdj = app.curAdj;
13182 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13183 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13184
13185 mAdjSeq++;
13186
13187 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13188 if (res) {
13189 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13190 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13191 if (nowHidden != wasHidden) {
13192 // Changed to/from hidden state, so apps after it in the LRU
13193 // list may also be changed.
13194 updateOomAdjLocked();
13195 }
13196 }
13197 return res;
13198 }
13199
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013200 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013201 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013202 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013203 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13204
13205 if (false) {
13206 RuntimeException e = new RuntimeException();
13207 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013208 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013209 }
13210
13211 mAdjSeq++;
13212
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013213 // Let's determine how many processes we have running vs.
13214 // how many slots we have for background processes; we may want
13215 // to put multiple processes in a slot of there are enough of
13216 // them.
13217 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13218 int factor = (mLruProcesses.size()-4)/numSlots;
13219 if (factor < 1) factor = 1;
13220 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013221 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013223 // First try updating the OOM adjustment for each of the
13224 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013225 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013226 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
13227 while (i > 0) {
13228 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013229 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013230 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013231 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013232 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013233 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013234 step++;
13235 if (step >= factor) {
13236 step = 0;
13237 curHiddenAdj++;
13238 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013239 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013240 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070013241 if (!app.killedBackground) {
13242 numHidden++;
13243 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070013244 Slog.i(TAG, "No longer want " + app.processName
13245 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013246 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13247 app.processName, app.setAdj, "too many background");
13248 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070013249 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013250 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013251 }
13252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013253 } else {
13254 didOomAdj = false;
13255 }
13256 }
13257
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013258 // If we return false, we will fall back on killing processes to
13259 // have a fixed limit. Do this if a limit has been requested; else
13260 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013261 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13262 }
13263
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013264 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013265 synchronized (this) {
13266 int i;
13267
13268 // First remove any unused application processes whose package
13269 // has been removed.
13270 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13271 final ProcessRecord app = mRemovedProcesses.get(i);
13272 if (app.activities.size() == 0
13273 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013274 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013275 TAG, "Exiting empty application process "
13276 + app.processName + " ("
13277 + (app.thread != null ? app.thread.asBinder() : null)
13278 + ")\n");
13279 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013280 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13281 app.processName, app.setAdj, "empty");
13282 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013283 } else {
13284 try {
13285 app.thread.scheduleExit();
13286 } catch (Exception e) {
13287 // Ignore exceptions.
13288 }
13289 }
13290 cleanUpApplicationRecordLocked(app, false, -1);
13291 mRemovedProcesses.remove(i);
13292
13293 if (app.persistent) {
13294 if (app.persistent) {
13295 addAppLocked(app.info);
13296 }
13297 }
13298 }
13299 }
13300
13301 // Now try updating the OOM adjustment for each of the
13302 // application processes based on their current state.
13303 // If the setOomAdj() API is not supported, then go with our
13304 // back-up plan...
13305 if (!updateOomAdjLocked()) {
13306
13307 // Count how many processes are running services.
13308 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013309 for (i=mLruProcesses.size()-1; i>=0; i--) {
13310 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013311
13312 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013313 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013314 // Don't count processes holding services against our
13315 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013316 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013317 TAG, "Not trimming app " + app + " with services: "
13318 + app.services);
13319 numServiceProcs++;
13320 }
13321 }
13322
13323 int curMaxProcs = mProcessLimit;
13324 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13325 if (mAlwaysFinishActivities) {
13326 curMaxProcs = 1;
13327 }
13328 curMaxProcs += numServiceProcs;
13329
13330 // Quit as many processes as we can to get down to the desired
13331 // process count. First remove any processes that no longer
13332 // have activites running in them.
13333 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013334 i<mLruProcesses.size()
13335 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013336 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013337 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013338 // Quit an application only if it is not currently
13339 // running any activities.
13340 if (!app.persistent && app.activities.size() == 0
13341 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013342 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013343 TAG, "Exiting empty application process "
13344 + app.processName + " ("
13345 + (app.thread != null ? app.thread.asBinder() : null)
13346 + ")\n");
13347 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013348 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13349 app.processName, app.setAdj, "empty");
13350 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013351 } else {
13352 try {
13353 app.thread.scheduleExit();
13354 } catch (Exception e) {
13355 // Ignore exceptions.
13356 }
13357 }
13358 // todo: For now we assume the application is not buggy
13359 // or evil, and will quit as a result of our request.
13360 // Eventually we need to drive this off of the death
13361 // notification, and kill the process if it takes too long.
13362 cleanUpApplicationRecordLocked(app, false, i);
13363 i--;
13364 }
13365 }
13366
13367 // If we still have too many processes, now from the least
13368 // recently used process we start finishing activities.
Joe Onorato43a17652011-04-06 19:22:23 -070013369 if (false) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013370 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013371 " of " + curMaxProcs + " processes");
13372 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013373 i<mLruProcesses.size()
13374 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013375 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013376 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013377 // Quit the application only if we have a state saved for
13378 // all of its activities.
13379 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013380 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381 int NUMA = app.activities.size();
13382 int j;
Joe Onorato43a17652011-04-06 19:22:23 -070013383 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013384 TAG, "Looking to quit " + app.processName);
13385 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013386 ActivityRecord r = app.activities.get(j);
Joe Onorato43a17652011-04-06 19:22:23 -070013387 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013388 TAG, " " + r.intent.getComponent().flattenToShortString()
13389 + ": frozen=" + r.haveState + ", visible=" + r.visible);
13390 canQuit = (r.haveState || !r.stateNotNeeded)
13391 && !r.visible && r.stopped;
13392 }
13393 if (canQuit) {
13394 // Finish all of the activities, and then the app itself.
13395 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013396 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013397 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013398 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013399 }
13400 r.resultTo = null;
13401 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013402 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013403 + app.processName + " ("
13404 + (app.thread != null ? app.thread.asBinder() : null)
13405 + ")\n");
13406 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013407 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13408 app.processName, app.setAdj, "old background");
13409 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013410 } else {
13411 try {
13412 app.thread.scheduleExit();
13413 } catch (Exception e) {
13414 // Ignore exceptions.
13415 }
13416 }
13417 // todo: For now we assume the application is not buggy
13418 // or evil, and will quit as a result of our request.
13419 // Eventually we need to drive this off of the death
13420 // notification, and kill the process if it takes too long.
13421 cleanUpApplicationRecordLocked(app, false, i);
13422 i--;
13423 //dump();
13424 }
13425 }
13426
13427 }
13428
13429 int curMaxActivities = MAX_ACTIVITIES;
13430 if (mAlwaysFinishActivities) {
13431 curMaxActivities = 1;
13432 }
13433
13434 // Finally, if there are too many activities now running, try to
13435 // finish as many as we can to get back down to the limit.
13436 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013437 i<mMainStack.mLRUActivities.size()
13438 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013439 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013440 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013441 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013442
13443 // We can finish this one if we have its icicle saved and
13444 // it is not persistent.
13445 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013446 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013447 final int origSize = mMainStack.mLRUActivities.size();
13448 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013449
13450 // This will remove it from the LRU list, so keep
13451 // our index at the same value. Note that this check to
13452 // see if the size changes is just paranoia -- if
13453 // something unexpected happens, we don't want to end up
13454 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013455 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013456 i--;
13457 }
13458 }
13459 }
13460 }
13461 }
13462
13463 /** This method sends the specified signal to each of the persistent apps */
13464 public void signalPersistentProcesses(int sig) throws RemoteException {
13465 if (sig != Process.SIGNAL_USR1) {
13466 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13467 }
13468
13469 synchronized (this) {
13470 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13471 != PackageManager.PERMISSION_GRANTED) {
13472 throw new SecurityException("Requires permission "
13473 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13474 }
13475
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013476 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13477 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013478 if (r.thread != null && r.persistent) {
13479 Process.sendSignal(r.pid, sig);
13480 }
13481 }
13482 }
13483 }
13484
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013485 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013486 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013487
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013488 try {
13489 synchronized (this) {
13490 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13491 // its own permission.
13492 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13493 != PackageManager.PERMISSION_GRANTED) {
13494 throw new SecurityException("Requires permission "
13495 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013496 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013497
13498 if (start && fd == null) {
13499 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013500 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013501
13502 ProcessRecord proc = null;
13503 try {
13504 int pid = Integer.parseInt(process);
13505 synchronized (mPidsSelfLocked) {
13506 proc = mPidsSelfLocked.get(pid);
13507 }
13508 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013509 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013510
13511 if (proc == null) {
13512 HashMap<String, SparseArray<ProcessRecord>> all
13513 = mProcessNames.getMap();
13514 SparseArray<ProcessRecord> procs = all.get(process);
13515 if (procs != null && procs.size() > 0) {
13516 proc = procs.valueAt(0);
13517 }
13518 }
13519
13520 if (proc == null || proc.thread == null) {
13521 throw new IllegalArgumentException("Unknown process: " + process);
13522 }
13523
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013524 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13525 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013526 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13527 throw new SecurityException("Process not debuggable: " + proc);
13528 }
13529 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013530
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013531 proc.thread.profilerControl(start, path, fd);
13532 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013533 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013534 }
13535 } catch (RemoteException e) {
13536 throw new IllegalStateException("Process disappeared");
13537 } finally {
13538 if (fd != null) {
13539 try {
13540 fd.close();
13541 } catch (IOException e) {
13542 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013543 }
13544 }
13545 }
Andy McFadden824c5102010-07-09 16:26:57 -070013546
13547 public boolean dumpHeap(String process, boolean managed,
13548 String path, ParcelFileDescriptor fd) throws RemoteException {
13549
13550 try {
13551 synchronized (this) {
13552 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13553 // its own permission (same as profileControl).
13554 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13555 != PackageManager.PERMISSION_GRANTED) {
13556 throw new SecurityException("Requires permission "
13557 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13558 }
13559
13560 if (fd == null) {
13561 throw new IllegalArgumentException("null fd");
13562 }
13563
13564 ProcessRecord proc = null;
13565 try {
13566 int pid = Integer.parseInt(process);
13567 synchronized (mPidsSelfLocked) {
13568 proc = mPidsSelfLocked.get(pid);
13569 }
13570 } catch (NumberFormatException e) {
13571 }
13572
13573 if (proc == null) {
13574 HashMap<String, SparseArray<ProcessRecord>> all
13575 = mProcessNames.getMap();
13576 SparseArray<ProcessRecord> procs = all.get(process);
13577 if (procs != null && procs.size() > 0) {
13578 proc = procs.valueAt(0);
13579 }
13580 }
13581
13582 if (proc == null || proc.thread == null) {
13583 throw new IllegalArgumentException("Unknown process: " + process);
13584 }
13585
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013586 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13587 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013588 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13589 throw new SecurityException("Process not debuggable: " + proc);
13590 }
13591 }
13592
13593 proc.thread.dumpHeap(managed, path, fd);
13594 fd = null;
13595 return true;
13596 }
13597 } catch (RemoteException e) {
13598 throw new IllegalStateException("Process disappeared");
13599 } finally {
13600 if (fd != null) {
13601 try {
13602 fd.close();
13603 } catch (IOException e) {
13604 }
13605 }
13606 }
13607 }
13608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013609 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13610 public void monitor() {
13611 synchronized (this) { }
13612 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013613
13614 public void onCoreSettingsChange(Bundle settings) {
13615 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13616 ProcessRecord processRecord = mLruProcesses.get(i);
13617 try {
13618 if (processRecord.thread != null) {
13619 processRecord.thread.setCoreSettings(settings);
13620 }
13621 } catch (RemoteException re) {
13622 /* ignore */
13623 }
13624 }
13625 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070013626
13627 // Multi-user methods
13628
13629 public boolean switchUser(int userid) {
13630 // TODO
13631 return true;
13632 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013633}