blob: 48b0b667c2f81e5638d0935b0942f74dd15f7beb [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 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700625
626 @Override
627 protected String packageForFilter(BroadcastFilter filter) {
628 return filter.packageName;
629 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 };
631
632 /**
633 * State of all active sticky broadcasts. Keys are the action of the
634 * sticky Intent, values are an ArrayList of all broadcasted intents with
635 * that action (which should usually be one).
636 */
637 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
638 new HashMap<String, ArrayList<Intent>>();
639
640 /**
641 * All currently running services.
642 */
643 final HashMap<ComponentName, ServiceRecord> mServices =
644 new HashMap<ComponentName, ServiceRecord>();
645
646 /**
647 * All currently running services indexed by the Intent used to start them.
648 */
649 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
650 new HashMap<Intent.FilterComparison, ServiceRecord>();
651
652 /**
653 * All currently bound service connections. Keys are the IBinder of
654 * the client's IServiceConnection.
655 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700656 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
657 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658
659 /**
660 * List of services that we have been asked to start,
661 * but haven't yet been able to. It is used to hold start requests
662 * while waiting for their corresponding application thread to get
663 * going.
664 */
665 final ArrayList<ServiceRecord> mPendingServices
666 = new ArrayList<ServiceRecord>();
667
668 /**
669 * List of services that are scheduled to restart following a crash.
670 */
671 final ArrayList<ServiceRecord> mRestartingServices
672 = new ArrayList<ServiceRecord>();
673
674 /**
675 * List of services that are in the process of being stopped.
676 */
677 final ArrayList<ServiceRecord> mStoppingServices
678 = new ArrayList<ServiceRecord>();
679
680 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700681 * Backup/restore process management
682 */
683 String mBackupAppName = null;
684 BackupRecord mBackupTarget = null;
685
686 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 * List of PendingThumbnailsRecord objects of clients who are still
688 * waiting to receive all of the thumbnails for a task.
689 */
690 final ArrayList mPendingThumbnails = new ArrayList();
691
692 /**
693 * List of HistoryRecord objects that have been finished and must
694 * still report back to a pending thumbnail receiver.
695 */
696 final ArrayList mCancelledThumbnails = new ArrayList();
697
698 /**
699 * All of the currently running global content providers. Keys are a
700 * string containing the provider name and values are a
701 * ContentProviderRecord object containing the data about it. Note
702 * that a single provider may be published under multiple names, so
703 * there may be multiple entries here for a single one in mProvidersByClass.
704 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700705 final HashMap<String, ContentProviderRecord> mProvidersByName
706 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707
708 /**
709 * All of the currently running global content providers. Keys are a
710 * string containing the provider's implementation class and values are a
711 * ContentProviderRecord object containing the data about it.
712 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700713 final HashMap<String, ContentProviderRecord> mProvidersByClass
714 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715
716 /**
717 * List of content providers who have clients waiting for them. The
718 * application is currently being launched and the provider will be
719 * removed from this list once it is published.
720 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700721 final ArrayList<ContentProviderRecord> mLaunchingProviders
722 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723
724 /**
725 * Global set of specific Uri permissions that have been granted.
726 */
727 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
728 = new SparseArray<HashMap<Uri, UriPermission>>();
729
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800730 CoreSettingsObserver mCoreSettingsObserver;
731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 /**
733 * Thread-local storage used to carry caller permissions over through
734 * indirect content-provider access.
735 * @see #ActivityManagerService.openContentUri()
736 */
737 private class Identity {
738 public int pid;
739 public int uid;
740
741 Identity(int _pid, int _uid) {
742 pid = _pid;
743 uid = _uid;
744 }
745 }
746 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
747
748 /**
749 * All information we have collected about the runtime performance of
750 * any user id that can impact battery performance.
751 */
752 final BatteryStatsService mBatteryStatsService;
753
754 /**
755 * information about component usage
756 */
757 final UsageStatsService mUsageStatsService;
758
759 /**
760 * Current configuration information. HistoryRecord objects are given
761 * a reference to this object to indicate which configuration they are
762 * currently running in, so this object must be kept immutable.
763 */
764 Configuration mConfiguration = new Configuration();
765
766 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800767 * Current sequencing integer of the configuration, for skipping old
768 * configurations.
769 */
770 int mConfigurationSeq = 0;
771
772 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700773 * Hardware-reported OpenGLES version.
774 */
775 final int GL_ES_VERSION;
776
777 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 * List of initialization arguments to pass to all processes when binding applications to them.
779 * For example, references to the commonly used services.
780 */
781 HashMap<String, IBinder> mAppBindArgs;
782
783 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700784 * Temporary to avoid allocations. Protected by main lock.
785 */
786 final StringBuilder mStringBuilder = new StringBuilder(256);
787
788 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 * Used to control how we initialize the service.
790 */
791 boolean mStartRunning = false;
792 ComponentName mTopComponent;
793 String mTopAction;
794 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700795 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 boolean mSystemReady = false;
797 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700798 boolean mWaitingUpdate = false;
799 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700800 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700801 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802
803 Context mContext;
804
805 int mFactoryTest;
806
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700807 boolean mCheckedForSetup;
808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700810 * The time at which we will allow normal application switches again,
811 * after a call to {@link #stopAppSwitches()}.
812 */
813 long mAppSwitchesAllowedTime;
814
815 /**
816 * This is set to true after the first switch after mAppSwitchesAllowedTime
817 * is set; any switches after that will clear the time.
818 */
819 boolean mDidAppSwitch;
820
821 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700822 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700823 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700824 long mLastPowerCheckRealtime;
825
826 /**
827 * Last time (in uptime) at which we checked for power usage.
828 */
829 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700830
831 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 * Set while we are wanting to sleep, to prevent any
833 * activities from being started/resumed.
834 */
835 boolean mSleeping = false;
836
837 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700838 * Set if we are shutting down the system, similar to sleeping.
839 */
840 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841
842 /**
843 * Task identifier that activities are currently being started
844 * in. Incremented each time a new task is created.
845 * todo: Replace this with a TokenSpace class that generates non-repeating
846 * integers that won't wrap.
847 */
848 int mCurTask = 1;
849
850 /**
851 * Current sequence id for oom_adj computation traversal.
852 */
853 int mAdjSeq = 0;
854
855 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700856 * Current sequence id for process LRU updating.
857 */
858 int mLruSeq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859
860 /**
861 * System monitoring: number of processes that died since the last
862 * N procs were started.
863 */
864 int[] mProcDeaths = new int[20];
865
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700866 /**
867 * This is set if we had to do a delayed dexopt of an app before launching
868 * it, to increasing the ANR timeouts in that case.
869 */
870 boolean mDidDexOpt;
871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 String mDebugApp = null;
873 boolean mWaitForDebugger = false;
874 boolean mDebugTransient = false;
875 String mOrigDebugApp = null;
876 boolean mOrigWaitForDebugger = false;
877 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700878 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700880 final RemoteCallbackList<IActivityWatcher> mWatchers
881 = new RemoteCallbackList<IActivityWatcher>();
Jeff Sharkeya4620792011-05-20 15:29:23 -0700882
883 final RemoteCallbackList<IProcessObserver> mProcessObservers
884 = new RemoteCallbackList<IProcessObserver>();
885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 /**
887 * Callback of last caller to {@link #requestPss}.
888 */
889 Runnable mRequestPssCallback;
890
891 /**
892 * Remaining processes for which we are waiting results from the last
893 * call to {@link #requestPss}.
894 */
895 final ArrayList<ProcessRecord> mRequestPssList
896 = new ArrayList<ProcessRecord>();
897
898 /**
899 * Runtime statistics collection thread. This object's lock is used to
900 * protect all related state.
901 */
902 final Thread mProcessStatsThread;
903
904 /**
905 * Used to collect process stats when showing not responding dialog.
906 * Protected by mProcessStatsThread.
907 */
908 final ProcessStats mProcessStats = new ProcessStats(
909 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700910 final AtomicLong mLastCpuTime = new AtomicLong(0);
911 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 long mLastWriteTime = 0;
914
915 /**
916 * Set to true after the system has finished booting.
917 */
918 boolean mBooted = false;
919
920 int mProcessLimit = 0;
921
922 WindowManagerService mWindowManager;
923
924 static ActivityManagerService mSelf;
925 static ActivityThread mSystemThread;
926
927 private final class AppDeathRecipient implements IBinder.DeathRecipient {
928 final ProcessRecord mApp;
929 final int mPid;
930 final IApplicationThread mAppThread;
931
932 AppDeathRecipient(ProcessRecord app, int pid,
933 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800934 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 TAG, "New death recipient " + this
936 + " for thread " + thread.asBinder());
937 mApp = app;
938 mPid = pid;
939 mAppThread = thread;
940 }
941
942 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800943 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 TAG, "Death received in " + this
945 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 synchronized(ActivityManagerService.this) {
947 appDiedLocked(mApp, mPid, mAppThread);
948 }
949 }
950 }
951
952 static final int SHOW_ERROR_MSG = 1;
953 static final int SHOW_NOT_RESPONDING_MSG = 2;
954 static final int SHOW_FACTORY_ERROR_MSG = 3;
955 static final int UPDATE_CONFIGURATION_MSG = 4;
956 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
957 static final int WAIT_FOR_DEBUGGER_MSG = 6;
958 static final int BROADCAST_INTENT_MSG = 7;
959 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 static final int SERVICE_TIMEOUT_MSG = 12;
961 static final int UPDATE_TIME_ZONE = 13;
962 static final int SHOW_UID_ERROR_MSG = 14;
963 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700965 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700966 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800967 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700968 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
969 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700970 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700971 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700972 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700973 static final int UPDATE_HTTP_PROXY = 29;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700974 static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
Dianne Hackborn36f80f32011-05-31 18:26:45 -0700975 static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
976 static final int DISPATCH_PROCESS_DIED = 32;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977
978 AlertDialog mUidAlert;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700979 CompatModeDialog mCompatModeDialog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980
981 final Handler mHandler = new Handler() {
982 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800983 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 //}
985
986 public void handleMessage(Message msg) {
987 switch (msg.what) {
988 case SHOW_ERROR_MSG: {
989 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 synchronized (ActivityManagerService.this) {
991 ProcessRecord proc = (ProcessRecord)data.get("app");
992 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800993 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 return;
995 }
996 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700997 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800998 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 d.show();
1000 proc.crashDialog = d;
1001 } else {
1002 // The device is asleep, so just pretend that the user
1003 // saw a crash dialog and hit "force quit".
1004 res.set(0);
1005 }
1006 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001007
1008 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 } break;
1010 case SHOW_NOT_RESPONDING_MSG: {
1011 synchronized (ActivityManagerService.this) {
1012 HashMap data = (HashMap) msg.obj;
1013 ProcessRecord proc = (ProcessRecord)data.get("app");
1014 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001015 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 return;
1017 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001018
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001019 Intent intent = new Intent("android.intent.action.ANR");
1020 if (!mProcessesReady) {
1021 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1022 }
1023 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001024 null, null, 0, null, null, null,
1025 false, false, MY_PID, Process.SYSTEM_UID);
1026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001028 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 d.show();
1030 proc.anrDialog = d;
1031 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001032
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001033 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001035 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1036 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1037 synchronized (ActivityManagerService.this) {
1038 ProcessRecord proc = (ProcessRecord) data.get("app");
1039 if (proc == null) {
1040 Slog.e(TAG, "App not found when showing strict mode dialog.");
1041 break;
1042 }
1043 if (proc.crashDialog != null) {
1044 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1045 return;
1046 }
1047 AppErrorResult res = (AppErrorResult) data.get("result");
1048 if (!mSleeping && !mShuttingDown) {
1049 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1050 d.show();
1051 proc.crashDialog = d;
1052 } else {
1053 // The device is asleep, so just pretend that the user
1054 // saw a crash dialog and hit "force quit".
1055 res.set(0);
1056 }
1057 }
1058 ensureBootCompleted();
1059 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 case SHOW_FACTORY_ERROR_MSG: {
1061 Dialog d = new FactoryErrorDialog(
1062 mContext, msg.getData().getCharSequence("msg"));
1063 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001064 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 } break;
1066 case UPDATE_CONFIGURATION_MSG: {
1067 final ContentResolver resolver = mContext.getContentResolver();
1068 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1069 } break;
1070 case GC_BACKGROUND_PROCESSES_MSG: {
1071 synchronized (ActivityManagerService.this) {
1072 performAppGcsIfAppropriateLocked();
1073 }
1074 } break;
1075 case WAIT_FOR_DEBUGGER_MSG: {
1076 synchronized (ActivityManagerService.this) {
1077 ProcessRecord app = (ProcessRecord)msg.obj;
1078 if (msg.arg1 != 0) {
1079 if (!app.waitedForDebugger) {
1080 Dialog d = new AppWaitingForDebuggerDialog(
1081 ActivityManagerService.this,
1082 mContext, app);
1083 app.waitDialog = d;
1084 app.waitedForDebugger = true;
1085 d.show();
1086 }
1087 } else {
1088 if (app.waitDialog != null) {
1089 app.waitDialog.dismiss();
1090 app.waitDialog = null;
1091 }
1092 }
1093 }
1094 } break;
1095 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001096 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 TAG, "Received BROADCAST_INTENT_MSG");
1098 processNextBroadcast(true);
1099 } break;
1100 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001101 synchronized (ActivityManagerService.this) {
1102 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001106 if (mDidDexOpt) {
1107 mDidDexOpt = false;
1108 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1109 nmsg.obj = msg.obj;
1110 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1111 return;
1112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 serviceTimeout((ProcessRecord)msg.obj);
1114 } break;
1115 case UPDATE_TIME_ZONE: {
1116 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001117 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1118 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 if (r.thread != null) {
1120 try {
1121 r.thread.updateTimeZone();
1122 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001123 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 }
1125 }
1126 }
1127 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001128 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001129 case CLEAR_DNS_CACHE: {
1130 synchronized (ActivityManagerService.this) {
1131 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1132 ProcessRecord r = mLruProcesses.get(i);
1133 if (r.thread != null) {
1134 try {
1135 r.thread.clearDnsCache();
1136 } catch (RemoteException ex) {
1137 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1138 }
1139 }
1140 }
1141 }
1142 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001143 case UPDATE_HTTP_PROXY: {
1144 ProxyProperties proxy = (ProxyProperties)msg.obj;
1145 String host = "";
1146 String port = "";
1147 String exclList = "";
1148 if (proxy != null) {
1149 host = proxy.getHost();
1150 port = Integer.toString(proxy.getPort());
1151 exclList = proxy.getExclusionList();
1152 }
1153 synchronized (ActivityManagerService.this) {
1154 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1155 ProcessRecord r = mLruProcesses.get(i);
1156 if (r.thread != null) {
1157 try {
1158 r.thread.setHttpProxy(host, port, exclList);
1159 } catch (RemoteException ex) {
1160 Slog.w(TAG, "Failed to update http proxy for: " +
1161 r.info.processName);
1162 }
1163 }
1164 }
1165 }
1166 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 case SHOW_UID_ERROR_MSG: {
1168 // XXX This is a temporary dialog, no need to localize.
1169 AlertDialog d = new BaseErrorDialog(mContext);
1170 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1171 d.setCancelable(false);
1172 d.setTitle("System UIDs Inconsistent");
1173 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 +02001174 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1176 mUidAlert = d;
1177 d.show();
1178 } break;
1179 case IM_FEELING_LUCKY_MSG: {
1180 if (mUidAlert != null) {
1181 mUidAlert.dismiss();
1182 mUidAlert = null;
1183 }
1184 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001186 if (mDidDexOpt) {
1187 mDidDexOpt = false;
1188 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1189 nmsg.obj = msg.obj;
1190 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1191 return;
1192 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001193 ProcessRecord app = (ProcessRecord)msg.obj;
1194 synchronized (ActivityManagerService.this) {
1195 processStartTimedOutLocked(app);
1196 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001197 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001198 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1199 synchronized (ActivityManagerService.this) {
1200 doPendingActivityLaunchesLocked(true);
1201 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001202 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001203 case KILL_APPLICATION_MSG: {
1204 synchronized (ActivityManagerService.this) {
1205 int uid = msg.arg1;
1206 boolean restart = (msg.arg2 == 1);
1207 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001208 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001209 }
1210 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001211 case FINALIZE_PENDING_INTENT_MSG: {
1212 ((PendingIntentRecord)msg.obj).completeFinalize();
1213 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001214 case POST_HEAVY_NOTIFICATION_MSG: {
1215 INotificationManager inm = NotificationManager.getService();
1216 if (inm == null) {
1217 return;
1218 }
1219
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001220 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001221 ProcessRecord process = root.app;
1222 if (process == null) {
1223 return;
1224 }
1225
1226 try {
1227 Context context = mContext.createPackageContext(process.info.packageName, 0);
1228 String text = mContext.getString(R.string.heavy_weight_notification,
1229 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1230 Notification notification = new Notification();
1231 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1232 notification.when = 0;
1233 notification.flags = Notification.FLAG_ONGOING_EVENT;
1234 notification.tickerText = text;
1235 notification.defaults = 0; // please be quiet
1236 notification.sound = null;
1237 notification.vibrate = null;
1238 notification.setLatestEventInfo(context, text,
1239 mContext.getText(R.string.heavy_weight_notification_detail),
1240 PendingIntent.getActivity(mContext, 0, root.intent,
1241 PendingIntent.FLAG_CANCEL_CURRENT));
1242
1243 try {
1244 int[] outId = new int[1];
1245 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1246 notification, outId);
1247 } catch (RuntimeException e) {
1248 Slog.w(ActivityManagerService.TAG,
1249 "Error showing notification for heavy-weight app", e);
1250 } catch (RemoteException e) {
1251 }
1252 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001253 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001254 }
1255 } break;
1256 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1257 INotificationManager inm = NotificationManager.getService();
1258 if (inm == null) {
1259 return;
1260 }
1261 try {
1262 inm.cancelNotification("android",
1263 R.string.heavy_weight_notification);
1264 } catch (RuntimeException e) {
1265 Slog.w(ActivityManagerService.TAG,
1266 "Error canceling notification for service", e);
1267 } catch (RemoteException e) {
1268 }
1269 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001270 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1271 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001272 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001273 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001274 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1275 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001276 }
1277 } break;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001278 case SHOW_COMPAT_MODE_DIALOG_MSG: {
1279 synchronized (ActivityManagerService.this) {
1280 ActivityRecord ar = (ActivityRecord)msg.obj;
1281 if (mCompatModeDialog != null) {
1282 if (mCompatModeDialog.mAppInfo.packageName.equals(
1283 ar.info.applicationInfo.packageName)) {
1284 return;
1285 }
1286 mCompatModeDialog.dismiss();
1287 mCompatModeDialog = null;
1288 }
Dianne Hackborn29478262011-06-07 15:44:22 -07001289 if (ar != null && false) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001290 if (mCompatModePackages.getPackageAskCompatModeLocked(
1291 ar.packageName)) {
1292 int mode = mCompatModePackages.computeCompatModeLocked(
1293 ar.info.applicationInfo);
1294 if (mode == ActivityManager.COMPAT_MODE_DISABLED
1295 || mode == ActivityManager.COMPAT_MODE_ENABLED) {
1296 mCompatModeDialog = new CompatModeDialog(
1297 ActivityManagerService.this, mContext,
1298 ar.info.applicationInfo);
1299 mCompatModeDialog.show();
1300 }
1301 }
1302 }
1303 }
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001304 break;
1305 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001306 case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001307 final int pid = msg.arg1;
1308 final int uid = msg.arg2;
1309 final boolean foregroundActivities = (Boolean) msg.obj;
1310 dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001311 break;
1312 }
1313 case DISPATCH_PROCESS_DIED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001314 final int pid = msg.arg1;
1315 final int uid = msg.arg2;
1316 dispatchProcessDied(pid, uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001317 break;
1318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 }
1320 }
1321 };
1322
1323 public static void setSystemProcess() {
1324 try {
1325 ActivityManagerService m = mSelf;
1326
1327 ServiceManager.addService("activity", m);
1328 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07001329 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 if (MONITOR_CPU_USAGE) {
1331 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333 ServiceManager.addService("permission", new PermissionController(m));
1334
1335 ApplicationInfo info =
1336 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001337 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001338 mSystemThread.installSystemApplicationInfo(info);
1339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 synchronized (mSelf) {
1341 ProcessRecord app = mSelf.newProcessRecordLocked(
1342 mSystemThread.getApplicationThread(), info,
1343 info.processName);
1344 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001345 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 app.maxAdj = SYSTEM_ADJ;
1347 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1348 synchronized (mSelf.mPidsSelfLocked) {
1349 mSelf.mPidsSelfLocked.put(app.pid, app);
1350 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001351 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 }
1353 } catch (PackageManager.NameNotFoundException e) {
1354 throw new RuntimeException(
1355 "Unable to find android system package", e);
1356 }
1357 }
1358
1359 public void setWindowManager(WindowManagerService wm) {
1360 mWindowManager = wm;
1361 }
1362
1363 public static final Context main(int factoryTest) {
1364 AThread thr = new AThread();
1365 thr.start();
1366
1367 synchronized (thr) {
1368 while (thr.mService == null) {
1369 try {
1370 thr.wait();
1371 } catch (InterruptedException e) {
1372 }
1373 }
1374 }
1375
1376 ActivityManagerService m = thr.mService;
1377 mSelf = m;
1378 ActivityThread at = ActivityThread.systemMain();
1379 mSystemThread = at;
1380 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001381 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 m.mContext = context;
1383 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001384 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385
1386 m.mBatteryStatsService.publish(context);
1387 m.mUsageStatsService.publish(context);
1388
1389 synchronized (thr) {
1390 thr.mReady = true;
1391 thr.notifyAll();
1392 }
1393
1394 m.startRunning(null, null, null, null);
1395
1396 return context;
1397 }
1398
1399 public static ActivityManagerService self() {
1400 return mSelf;
1401 }
1402
1403 static class AThread extends Thread {
1404 ActivityManagerService mService;
1405 boolean mReady = false;
1406
1407 public AThread() {
1408 super("ActivityManager");
1409 }
1410
1411 public void run() {
1412 Looper.prepare();
1413
1414 android.os.Process.setThreadPriority(
1415 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001416 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417
1418 ActivityManagerService m = new ActivityManagerService();
1419
1420 synchronized (this) {
1421 mService = m;
1422 notifyAll();
1423 }
1424
1425 synchronized (this) {
1426 while (!mReady) {
1427 try {
1428 wait();
1429 } catch (InterruptedException e) {
1430 }
1431 }
1432 }
1433
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001434 // For debug builds, log event loop stalls to dropbox for analysis.
1435 if (StrictMode.conditionallyEnableDebugLogging()) {
1436 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1437 }
1438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 Looper.loop();
1440 }
1441 }
1442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 static class MemBinder extends Binder {
1444 ActivityManagerService mActivityManagerService;
1445 MemBinder(ActivityManagerService activityManagerService) {
1446 mActivityManagerService = activityManagerService;
1447 }
1448
1449 @Override
1450 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001451 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 }
1453 }
1454
Chet Haase9c1e23b2011-03-24 10:51:31 -07001455 static class GraphicsBinder extends Binder {
1456 ActivityManagerService mActivityManagerService;
1457 GraphicsBinder(ActivityManagerService activityManagerService) {
1458 mActivityManagerService = activityManagerService;
1459 }
1460
1461 @Override
1462 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001463 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07001464 }
1465 }
1466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 static class CpuBinder extends Binder {
1468 ActivityManagerService mActivityManagerService;
1469 CpuBinder(ActivityManagerService activityManagerService) {
1470 mActivityManagerService = activityManagerService;
1471 }
1472
1473 @Override
1474 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1475 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001476 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1477 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1478 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 }
1480 }
1481 }
1482
1483 private ActivityManagerService() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001484 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 File dataDir = Environment.getDataDirectory();
1487 File systemDir = new File(dataDir, "system");
1488 systemDir.mkdirs();
1489 mBatteryStatsService = new BatteryStatsService(new File(
1490 systemDir, "batterystats.bin").toString());
1491 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001492 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001493 mOnBattery = DEBUG_POWER ? true
1494 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001495 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001497 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001498 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499
Jack Palevichb90d28c2009-07-22 15:35:24 -07001500 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1501 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1502
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001503 mConfiguration.setToDefaults();
1504 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 mProcessStats.init();
1506
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07001507 mCompatModePackages = new CompatModePackages(this, systemDir);
1508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 // Add ourself to the Watchdog monitors.
1510 Watchdog.getInstance().addMonitor(this);
1511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 mProcessStatsThread = new Thread("ProcessStats") {
1513 public void run() {
1514 while (true) {
1515 try {
1516 try {
1517 synchronized(this) {
1518 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001519 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001521 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 // + ", write delay=" + nextWriteDelay);
1523 if (nextWriteDelay < nextCpuDelay) {
1524 nextCpuDelay = nextWriteDelay;
1525 }
1526 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001527 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 this.wait(nextCpuDelay);
1529 }
1530 }
1531 } catch (InterruptedException e) {
1532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 updateCpuStatsNow();
1534 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001535 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 }
1537 }
1538 }
1539 };
1540 mProcessStatsThread.start();
1541 }
1542
1543 @Override
1544 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1545 throws RemoteException {
1546 try {
1547 return super.onTransact(code, data, reply, flags);
1548 } catch (RuntimeException e) {
1549 // The activity manager only throws security exceptions, so let's
1550 // log all others.
1551 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001552 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 }
1554 throw e;
1555 }
1556 }
1557
1558 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001559 final long now = SystemClock.uptimeMillis();
1560 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1561 return;
1562 }
1563 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1564 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 mProcessStatsThread.notify();
1566 }
1567 }
1568 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 void updateCpuStatsNow() {
1571 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001572 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 final long now = SystemClock.uptimeMillis();
1574 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001577 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1578 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 haveNewCpuStats = true;
1580 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001581 //Slog.i(TAG, mProcessStats.printCurrentState());
1582 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 // + mProcessStats.getTotalCpuPercent() + "%");
1584
Joe Onorato8a9b2202010-02-26 18:56:32 -08001585 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 if ("true".equals(SystemProperties.get("events.cpu"))) {
1587 int user = mProcessStats.getLastUserTime();
1588 int system = mProcessStats.getLastSystemTime();
1589 int iowait = mProcessStats.getLastIoWaitTime();
1590 int irq = mProcessStats.getLastIrqTime();
1591 int softIrq = mProcessStats.getLastSoftIrqTime();
1592 int idle = mProcessStats.getLastIdleTime();
1593
1594 int total = user + system + iowait + irq + softIrq + idle;
1595 if (total == 0) total = 1;
1596
Doug Zongker2bec3d42009-12-04 12:52:44 -08001597 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 ((user+system+iowait+irq+softIrq) * 100) / total,
1599 (user * 100) / total,
1600 (system * 100) / total,
1601 (iowait * 100) / total,
1602 (irq * 100) / total,
1603 (softIrq * 100) / total);
1604 }
1605 }
1606
Amith Yamasanie43530a2009-08-21 13:11:37 -07001607 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001608 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001609 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 synchronized(mPidsSelfLocked) {
1611 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001612 if (mOnBattery) {
1613 int perc = bstats.startAddingCpuLocked();
1614 int totalUTime = 0;
1615 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001616 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001618 ProcessStats.Stats st = mProcessStats.getStats(i);
1619 if (!st.working) {
1620 continue;
1621 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001623 int otherUTime = (st.rel_utime*perc)/100;
1624 int otherSTime = (st.rel_stime*perc)/100;
1625 totalUTime += otherUTime;
1626 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627 if (pr != null) {
1628 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001629 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1630 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001631 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001632 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001633 } else {
1634 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001635 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001636 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001637 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1638 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001639 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001640 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 }
1642 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001643 bstats.finishAddingCpuLocked(perc, totalUTime,
1644 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 }
1646 }
1647 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1650 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001651 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 }
1653 }
1654 }
1655 }
1656
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001657 @Override
1658 public void batteryNeedsCpuUpdate() {
1659 updateCpuStatsNow();
1660 }
1661
1662 @Override
1663 public void batteryPowerChanged(boolean onBattery) {
1664 // When plugging in, update the CPU stats first before changing
1665 // the plug state.
1666 updateCpuStatsNow();
1667 synchronized (this) {
1668 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001669 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001670 }
1671 }
1672 }
1673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 /**
1675 * Initialize the application bind args. These are passed to each
1676 * process when the bindApplication() IPC is sent to the process. They're
1677 * lazily setup to make sure the services are running when they're asked for.
1678 */
1679 private HashMap<String, IBinder> getCommonServicesLocked() {
1680 if (mAppBindArgs == null) {
1681 mAppBindArgs = new HashMap<String, IBinder>();
1682
1683 // Setup the application init args
1684 mAppBindArgs.put("package", ServiceManager.getService("package"));
1685 mAppBindArgs.put("window", ServiceManager.getService("window"));
1686 mAppBindArgs.put(Context.ALARM_SERVICE,
1687 ServiceManager.getService(Context.ALARM_SERVICE));
1688 }
1689 return mAppBindArgs;
1690 }
1691
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001692 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 if (mFocusedActivity != r) {
1694 mFocusedActivity = r;
1695 mWindowManager.setFocusedApp(r, true);
1696 }
1697 }
1698
Dianne Hackborn906497c2010-05-10 15:57:38 -07001699 private final void updateLruProcessInternalLocked(ProcessRecord app,
1700 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001702 int lrui = mLruProcesses.indexOf(app);
1703 if (lrui >= 0) mLruProcesses.remove(lrui);
1704
1705 int i = mLruProcesses.size()-1;
1706 int skipTop = 0;
1707
Dianne Hackborn906497c2010-05-10 15:57:38 -07001708 app.lruSeq = mLruSeq;
1709
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001710 // compute the new weight for this process.
1711 if (updateActivityTime) {
1712 app.lastActivityTime = SystemClock.uptimeMillis();
1713 }
1714 if (app.activities.size() > 0) {
1715 // If this process has activities, we more strongly want to keep
1716 // it around.
1717 app.lruWeight = app.lastActivityTime;
1718 } else if (app.pubProviders.size() > 0) {
1719 // If this process contains content providers, we want to keep
1720 // it a little more strongly.
1721 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1722 // Also don't let it kick out the first few "real" hidden processes.
1723 skipTop = MIN_HIDDEN_APPS;
1724 } else {
1725 // If this process doesn't have activities, we less strongly
1726 // want to keep it around, and generally want to avoid getting
1727 // in front of any very recently used activities.
1728 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1729 // Also don't let it kick out the first few "real" hidden processes.
1730 skipTop = MIN_HIDDEN_APPS;
1731 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001732
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001733 while (i >= 0) {
1734 ProcessRecord p = mLruProcesses.get(i);
1735 // If this app shouldn't be in front of the first N background
1736 // apps, then skip over that many that are currently hidden.
1737 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1738 skipTop--;
1739 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001740 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001741 mLruProcesses.add(i+1, app);
1742 break;
1743 }
1744 i--;
1745 }
1746 if (i < 0) {
1747 mLruProcesses.add(0, app);
1748 }
1749
Dianne Hackborn906497c2010-05-10 15:57:38 -07001750 // If the app is currently using a content provider or service,
1751 // bump those processes as well.
1752 if (app.connections.size() > 0) {
1753 for (ConnectionRecord cr : app.connections) {
1754 if (cr.binding != null && cr.binding.service != null
1755 && cr.binding.service.app != null
1756 && cr.binding.service.app.lruSeq != mLruSeq) {
1757 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1758 updateActivityTime, i+1);
1759 }
1760 }
1761 }
1762 if (app.conProviders.size() > 0) {
1763 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1764 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1765 updateLruProcessInternalLocked(cpr.app, oomAdj,
1766 updateActivityTime, i+1);
1767 }
1768 }
1769 }
1770
Joe Onorato8a9b2202010-02-26 18:56:32 -08001771 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 if (oomAdj) {
1773 updateOomAdjLocked();
1774 }
1775 }
1776
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001777 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001778 boolean oomAdj, boolean updateActivityTime) {
1779 mLruSeq++;
1780 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1781 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001782
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001783 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 String processName, int uid) {
1785 if (uid == Process.SYSTEM_UID) {
1786 // The system gets to run in any process. If there are multiple
1787 // processes with the same uid, just pick the first (this
1788 // should never happen).
1789 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1790 processName);
1791 return procs != null ? procs.valueAt(0) : null;
1792 }
1793 ProcessRecord proc = mProcessNames.get(processName, uid);
1794 return proc;
1795 }
1796
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001797 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001798 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001799 try {
1800 if (pm.performDexOpt(packageName)) {
1801 mDidDexOpt = true;
1802 }
1803 } catch (RemoteException e) {
1804 }
1805 }
1806
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001807 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808 int transit = mWindowManager.getPendingAppTransition();
1809 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1810 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1811 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1812 }
1813
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001814 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001816 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1818 // We don't have to do anything more if:
1819 // (1) There is an existing application record; and
1820 // (2) The caller doesn't think it is dead, OR there is no thread
1821 // object attached to it so we know it couldn't have crashed; and
1822 // (3) There is a pid assigned to it, so it is either starting or
1823 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001824 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 + " app=" + app + " knownToBeDead=" + knownToBeDead
1826 + " thread=" + (app != null ? app.thread : null)
1827 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001828 if (app != null && app.pid > 0) {
1829 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001830 // We already have the app running, or are waiting for it to
1831 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001832 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001833 // If this is a new package in the process, add the package to the list
1834 app.addPackage(info.packageName);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001835 return app;
1836 } else {
1837 // An application record is attached to a previous process,
1838 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001839 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001840 handleAppDiedLocked(app, true);
1841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001842 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 String hostingNameStr = hostingName != null
1845 ? hostingName.flattenToShortString() : null;
1846
1847 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1848 // If we are in the background, then check to see if this process
1849 // is bad. If so, we will just silently fail.
1850 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001851 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1852 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 return null;
1854 }
1855 } else {
1856 // When the user is explicitly starting a process, then clear its
1857 // crash count so that we won't make it bad until they see at
1858 // least one crash dialog again, and make the process good again
1859 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001860 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1861 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 mProcessCrashTimes.remove(info.processName, info.uid);
1863 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001864 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001865 info.processName);
1866 mBadProcesses.remove(info.processName, info.uid);
1867 if (app != null) {
1868 app.bad = false;
1869 }
1870 }
1871 }
1872
1873 if (app == null) {
1874 app = newProcessRecordLocked(null, info, processName);
1875 mProcessNames.put(processName, info.uid, app);
1876 } else {
1877 // If this is a new package in the process, add the package to the list
1878 app.addPackage(info.packageName);
1879 }
1880
1881 // If the system is not ready yet, then hold off on starting this
1882 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001883 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001884 && !isAllowedWhileBooting(info)
1885 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 if (!mProcessesOnHold.contains(app)) {
1887 mProcessesOnHold.add(app);
1888 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001889 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 return app;
1891 }
1892
1893 startProcessLocked(app, hostingType, hostingNameStr);
1894 return (app.pid != 0) ? app : null;
1895 }
1896
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001897 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1898 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1899 }
1900
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 private final void startProcessLocked(ProcessRecord app,
1902 String hostingType, String hostingNameStr) {
1903 if (app.pid > 0 && app.pid != MY_PID) {
1904 synchronized (mPidsSelfLocked) {
1905 mPidsSelfLocked.remove(app.pid);
1906 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1907 }
1908 app.pid = 0;
1909 }
1910
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001911 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1912 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 mProcessesOnHold.remove(app);
1914
1915 updateCpuStats();
1916
1917 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1918 mProcDeaths[0] = 0;
1919
1920 try {
1921 int uid = app.info.uid;
1922 int[] gids = null;
1923 try {
1924 gids = mContext.getPackageManager().getPackageGids(
1925 app.info.packageName);
1926 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001927 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001928 }
1929 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1930 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1931 && mTopComponent != null
1932 && app.processName.equals(mTopComponent.getPackageName())) {
1933 uid = 0;
1934 }
1935 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1936 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1937 uid = 0;
1938 }
1939 }
1940 int debugFlags = 0;
1941 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1942 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
Elliott Hughesfa36aee2011-06-17 14:39:41 -07001943 // Also turn on CheckJNI for debuggable apps. It's quite
1944 // awkward to turn on otherwise.
1945 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001947 // Run the app in safe mode if its manifest requests so or the
1948 // system is booted in safe mode.
1949 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1950 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001951 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1952 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001953 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1954 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1955 }
1956 if ("1".equals(SystemProperties.get("debug.assert"))) {
1957 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1958 }
1959 int pid = Process.start("android.app.ActivityThread",
Jeff Brownebed7d62011-05-16 17:08:42 -07001960 app.processName, uid, uid, gids, debugFlags, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001961 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1962 synchronized (bs) {
1963 if (bs.isOnBattery()) {
1964 app.batteryStats.incStartsLocked();
1965 }
1966 }
1967
Doug Zongker2bec3d42009-12-04 12:52:44 -08001968 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001969 app.processName, hostingType,
1970 hostingNameStr != null ? hostingNameStr : "");
1971
1972 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001973 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001974 }
1975
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001976 StringBuilder buf = mStringBuilder;
1977 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001978 buf.append("Start proc ");
1979 buf.append(app.processName);
1980 buf.append(" for ");
1981 buf.append(hostingType);
1982 if (hostingNameStr != null) {
1983 buf.append(" ");
1984 buf.append(hostingNameStr);
1985 }
1986 buf.append(": pid=");
1987 buf.append(pid);
1988 buf.append(" uid=");
1989 buf.append(uid);
1990 buf.append(" gids={");
1991 if (gids != null) {
1992 for (int gi=0; gi<gids.length; gi++) {
1993 if (gi != 0) buf.append(", ");
1994 buf.append(gids[gi]);
1995
1996 }
1997 }
1998 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001999 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 if (pid == 0 || pid == MY_PID) {
2001 // Processes are being emulated with threads.
2002 app.pid = MY_PID;
2003 app.removed = false;
2004 mStartingProcesses.add(app);
2005 } else if (pid > 0) {
2006 app.pid = pid;
2007 app.removed = false;
2008 synchronized (mPidsSelfLocked) {
2009 this.mPidsSelfLocked.put(pid, app);
2010 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2011 msg.obj = app;
2012 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2013 }
2014 } else {
2015 app.pid = 0;
2016 RuntimeException e = new RuntimeException(
2017 "Failure starting process " + app.processName
2018 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002019 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 }
2021 } catch (RuntimeException e) {
2022 // XXX do better error recovery.
2023 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002024 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 }
2026 }
2027
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002028 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029 if (resumed) {
2030 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2031 } else {
2032 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2033 }
2034 }
2035
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002036 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002037 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2038 && mTopAction == null) {
2039 // We are running in factory test mode, but unable to find
2040 // the factory test app, so just sit around displaying the
2041 // error message and don't try to start anything.
2042 return false;
2043 }
2044 Intent intent = new Intent(
2045 mTopAction,
2046 mTopData != null ? Uri.parse(mTopData) : null);
2047 intent.setComponent(mTopComponent);
2048 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2049 intent.addCategory(Intent.CATEGORY_HOME);
2050 }
2051 ActivityInfo aInfo =
2052 intent.resolveActivityInfo(mContext.getPackageManager(),
2053 STOCK_PM_FLAGS);
2054 if (aInfo != null) {
2055 intent.setComponent(new ComponentName(
2056 aInfo.applicationInfo.packageName, aInfo.name));
2057 // Don't do this if the home app is currently being
2058 // instrumented.
2059 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2060 aInfo.applicationInfo.uid);
2061 if (app == null || app.instrumentationClass == null) {
2062 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002063 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002064 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002065 }
2066 }
2067
2068
2069 return true;
2070 }
2071
2072 /**
2073 * Starts the "new version setup screen" if appropriate.
2074 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002075 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002076 // Only do this once per boot.
2077 if (mCheckedForSetup) {
2078 return;
2079 }
2080
2081 // We will show this screen if the current one is a different
2082 // version than the last one shown, and we are not running in
2083 // low-level factory test mode.
2084 final ContentResolver resolver = mContext.getContentResolver();
2085 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2086 Settings.Secure.getInt(resolver,
2087 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2088 mCheckedForSetup = true;
2089
2090 // See if we should be showing the platform update setup UI.
2091 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2092 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2093 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2094
2095 // We don't allow third party apps to replace this.
2096 ResolveInfo ri = null;
2097 for (int i=0; ris != null && i<ris.size(); i++) {
2098 if ((ris.get(i).activityInfo.applicationInfo.flags
2099 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2100 ri = ris.get(i);
2101 break;
2102 }
2103 }
2104
2105 if (ri != null) {
2106 String vers = ri.activityInfo.metaData != null
2107 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2108 : null;
2109 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2110 vers = ri.activityInfo.applicationInfo.metaData.getString(
2111 Intent.METADATA_SETUP_VERSION);
2112 }
2113 String lastVers = Settings.Secure.getString(
2114 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2115 if (vers != null && !vers.equals(lastVers)) {
2116 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2117 intent.setComponent(new ComponentName(
2118 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002119 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002120 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002121 }
2122 }
2123 }
2124 }
2125
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002126 CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002127 return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002128 }
2129
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002130 public int getFrontActivityScreenCompatMode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002131 synchronized (this) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002132 return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
2133 }
2134 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002135
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002136 public void setFrontActivityScreenCompatMode(int mode) {
2137 synchronized (this) {
2138 mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
2139 }
2140 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002141
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002142 public int getPackageScreenCompatMode(String packageName) {
2143 synchronized (this) {
2144 return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
2145 }
2146 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002147
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002148 public void setPackageScreenCompatMode(String packageName, int mode) {
2149 synchronized (this) {
2150 mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002151 }
2152 }
2153
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002154 public boolean getPackageAskScreenCompat(String packageName) {
2155 synchronized (this) {
2156 return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
2157 }
2158 }
2159
2160 public void setPackageAskScreenCompat(String packageName, boolean ask) {
2161 synchronized (this) {
2162 mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
2163 }
2164 }
2165
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002166 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002167 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002168
2169 final int identHash = System.identityHashCode(r);
2170 updateUsageStats(r, true);
2171
2172 int i = mWatchers.beginBroadcast();
2173 while (i > 0) {
2174 i--;
2175 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2176 if (w != null) {
2177 try {
2178 w.activityResuming(identHash);
2179 } catch (RemoteException e) {
2180 }
2181 }
2182 }
2183 mWatchers.finishBroadcast();
2184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185
Jeff Sharkeya4620792011-05-20 15:29:23 -07002186 private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2187 int i = mProcessObservers.beginBroadcast();
2188 while (i > 0) {
2189 i--;
2190 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2191 if (observer != null) {
2192 try {
2193 observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
2194 } catch (RemoteException e) {
2195 }
2196 }
2197 }
2198 mProcessObservers.finishBroadcast();
2199 }
2200
2201 private void dispatchProcessDied(int pid, int uid) {
2202 int i = mProcessObservers.beginBroadcast();
2203 while (i > 0) {
2204 i--;
2205 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2206 if (observer != null) {
2207 try {
2208 observer.onProcessDied(pid, uid);
2209 } catch (RemoteException e) {
2210 }
2211 }
2212 }
2213 mProcessObservers.finishBroadcast();
2214 }
2215
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002216 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002217 final int N = mPendingActivityLaunches.size();
2218 if (N <= 0) {
2219 return;
2220 }
2221 for (int i=0; i<N; i++) {
2222 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002223 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002224 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2225 doResume && i == (N-1));
2226 }
2227 mPendingActivityLaunches.clear();
2228 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002229
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002230 public final int startActivity(IApplicationThread caller,
2231 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2232 int grantedMode, IBinder resultTo,
2233 String resultWho, int requestCode, boolean onlyIfNeeded,
2234 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002235 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002236 grantedUriPermissions, grantedMode, resultTo, resultWho,
2237 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002238 }
2239
2240 public final WaitResult startActivityAndWait(IApplicationThread caller,
2241 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2242 int grantedMode, IBinder resultTo,
2243 String resultWho, int requestCode, boolean onlyIfNeeded,
2244 boolean debug) {
2245 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002246 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002247 grantedUriPermissions, grantedMode, resultTo, resultWho,
2248 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002249 return res;
2250 }
2251
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002252 public final int startActivityWithConfig(IApplicationThread caller,
2253 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2254 int grantedMode, IBinder resultTo,
2255 String resultWho, int requestCode, boolean onlyIfNeeded,
2256 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002257 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002258 grantedUriPermissions, grantedMode, resultTo, resultWho,
2259 requestCode, onlyIfNeeded, debug, null, config);
2260 }
2261
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002262 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002263 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002264 IBinder resultTo, String resultWho, int requestCode,
2265 int flagsMask, int flagsValues) {
2266 // Refuse possible leaked file descriptors
2267 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2268 throw new IllegalArgumentException("File descriptors passed in Intent");
2269 }
2270
2271 IIntentSender sender = intent.getTarget();
2272 if (!(sender instanceof PendingIntentRecord)) {
2273 throw new IllegalArgumentException("Bad PendingIntent object");
2274 }
2275
2276 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002277
2278 synchronized (this) {
2279 // If this is coming from the currently resumed activity, it is
2280 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002281 if (mMainStack.mResumedActivity != null
2282 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002283 Binder.getCallingUid()) {
2284 mAppSwitchesAllowedTime = 0;
2285 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002286 }
2287
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002288 return pir.sendInner(0, fillInIntent, resolvedType, null,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002289 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2290 }
2291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292 public boolean startNextMatchingActivity(IBinder callingActivity,
2293 Intent intent) {
2294 // Refuse possible leaked file descriptors
2295 if (intent != null && intent.hasFileDescriptors() == true) {
2296 throw new IllegalArgumentException("File descriptors passed in Intent");
2297 }
2298
2299 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002300 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002301 if (index < 0) {
2302 return false;
2303 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002304 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 if (r.app == null || r.app.thread == null) {
2306 // The caller is not running... d'oh!
2307 return false;
2308 }
2309 intent = new Intent(intent);
2310 // The caller is not allowed to change the data.
2311 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2312 // And we are resetting to find the next component...
2313 intent.setComponent(null);
2314
2315 ActivityInfo aInfo = null;
2316 try {
2317 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002318 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002319 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002320 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002321
2322 // Look for the original activity in the list...
2323 final int N = resolves != null ? resolves.size() : 0;
2324 for (int i=0; i<N; i++) {
2325 ResolveInfo rInfo = resolves.get(i);
2326 if (rInfo.activityInfo.packageName.equals(r.packageName)
2327 && rInfo.activityInfo.name.equals(r.info.name)) {
2328 // We found the current one... the next matching is
2329 // after it.
2330 i++;
2331 if (i<N) {
2332 aInfo = resolves.get(i).activityInfo;
2333 }
2334 break;
2335 }
2336 }
2337 } catch (RemoteException e) {
2338 }
2339
2340 if (aInfo == null) {
2341 // Nobody who is next!
2342 return false;
2343 }
2344
2345 intent.setComponent(new ComponentName(
2346 aInfo.applicationInfo.packageName, aInfo.name));
2347 intent.setFlags(intent.getFlags()&~(
2348 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2349 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2350 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2351 Intent.FLAG_ACTIVITY_NEW_TASK));
2352
2353 // Okay now we need to start the new activity, replacing the
2354 // currently running activity. This is a little tricky because
2355 // we want to start the new one as if the current one is finished,
2356 // but not finish the current one first so that there is no flicker.
2357 // And thus...
2358 final boolean wasFinishing = r.finishing;
2359 r.finishing = true;
2360
2361 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002362 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 final String resultWho = r.resultWho;
2364 final int requestCode = r.requestCode;
2365 r.resultTo = null;
2366 if (resultTo != null) {
2367 resultTo.removeResultsLocked(r, resultWho, requestCode);
2368 }
2369
2370 final long origId = Binder.clearCallingIdentity();
2371 // XXX we are not dealing with propagating grantedUriPermissions...
2372 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002373 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002375 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 Binder.restoreCallingIdentity(origId);
2377
2378 r.finishing = wasFinishing;
2379 if (res != START_SUCCESS) {
2380 return false;
2381 }
2382 return true;
2383 }
2384 }
2385
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002386 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 Intent intent, String resolvedType, IBinder resultTo,
2388 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002389
2390 // This is so super not safe, that only the system (or okay root)
2391 // can do it.
2392 final int callingUid = Binder.getCallingUid();
2393 if (callingUid != 0 && callingUid != Process.myUid()) {
2394 throw new SecurityException(
2395 "startActivityInPackage only available to the system");
2396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002398 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2399 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2400 }
2401
2402 public final int startActivities(IApplicationThread caller,
2403 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2404 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2405 }
2406
2407 public final int startActivitiesInPackage(int uid,
2408 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2409
2410 // This is so super not safe, that only the system (or okay root)
2411 // can do it.
2412 final int callingUid = Binder.getCallingUid();
2413 if (callingUid != 0 && callingUid != Process.myUid()) {
2414 throw new SecurityException(
2415 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002416 }
2417
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002418 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002419 }
2420
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002421 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002422 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002423 // Quick case: check if the top-most recent task is the same.
2424 if (N > 0 && mRecentTasks.get(0) == task) {
2425 return;
2426 }
2427 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002428 for (int i=0; i<N; i++) {
2429 TaskRecord tr = mRecentTasks.get(i);
2430 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2431 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2432 mRecentTasks.remove(i);
2433 i--;
2434 N--;
2435 if (task.intent == null) {
2436 // If the new recent task we are adding is not fully
2437 // specified, then replace it with the existing recent task.
2438 task = tr;
2439 }
2440 }
2441 }
2442 if (N >= MAX_RECENT_TASKS) {
2443 mRecentTasks.remove(N-1);
2444 }
2445 mRecentTasks.add(0, task);
2446 }
2447
2448 public void setRequestedOrientation(IBinder token,
2449 int requestedOrientation) {
2450 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002451 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002452 if (index < 0) {
2453 return;
2454 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002455 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002456 final long origId = Binder.clearCallingIdentity();
2457 mWindowManager.setAppOrientation(r, requestedOrientation);
2458 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002459 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 r.mayFreezeScreenLocked(r.app) ? r : null);
2461 if (config != null) {
2462 r.frozenBeforeDestroy = true;
2463 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002464 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002465 }
2466 }
2467 Binder.restoreCallingIdentity(origId);
2468 }
2469 }
2470
2471 public int getRequestedOrientation(IBinder token) {
2472 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002473 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002474 if (index < 0) {
2475 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2476 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002477 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002478 return mWindowManager.getAppOrientation(r);
2479 }
2480 }
2481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 /**
2483 * This is the internal entry point for handling Activity.finish().
2484 *
2485 * @param token The Binder token referencing the Activity we want to finish.
2486 * @param resultCode Result code, if any, from this Activity.
2487 * @param resultData Result data (Intent), if any, from this Activity.
2488 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002489 * @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 -08002490 */
2491 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2492 // Refuse possible leaked file descriptors
2493 if (resultData != null && resultData.hasFileDescriptors() == true) {
2494 throw new IllegalArgumentException("File descriptors passed in Intent");
2495 }
2496
2497 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002498 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002499 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002500 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 if (next != null) {
2502 // ask watcher if this is allowed
2503 boolean resumeOK = true;
2504 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002505 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002507 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002508 }
2509
2510 if (!resumeOK) {
2511 return false;
2512 }
2513 }
2514 }
2515 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002516 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 resultData, "app-request");
2518 Binder.restoreCallingIdentity(origId);
2519 return res;
2520 }
2521 }
2522
Dianne Hackborn860755f2010-06-03 18:47:52 -07002523 public final void finishHeavyWeightApp() {
2524 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2525 != PackageManager.PERMISSION_GRANTED) {
2526 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2527 + Binder.getCallingPid()
2528 + ", uid=" + Binder.getCallingUid()
2529 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2530 Slog.w(TAG, msg);
2531 throw new SecurityException(msg);
2532 }
2533
2534 synchronized(this) {
2535 if (mHeavyWeightProcess == null) {
2536 return;
2537 }
2538
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002539 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002540 mHeavyWeightProcess.activities);
2541 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002542 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002543 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002544 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002545 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002546 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002547 null, "finish-heavy");
2548 }
2549 }
2550 }
2551
2552 mHeavyWeightProcess = null;
2553 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2554 }
2555 }
2556
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002557 public void crashApplication(int uid, int initialPid, String packageName,
2558 String message) {
2559 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2560 != PackageManager.PERMISSION_GRANTED) {
2561 String msg = "Permission Denial: crashApplication() from pid="
2562 + Binder.getCallingPid()
2563 + ", uid=" + Binder.getCallingUid()
2564 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2565 Slog.w(TAG, msg);
2566 throw new SecurityException(msg);
2567 }
2568
2569 synchronized(this) {
2570 ProcessRecord proc = null;
2571
2572 // Figure out which process to kill. We don't trust that initialPid
2573 // still has any relation to current pids, so must scan through the
2574 // list.
2575 synchronized (mPidsSelfLocked) {
2576 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2577 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2578 if (p.info.uid != uid) {
2579 continue;
2580 }
2581 if (p.pid == initialPid) {
2582 proc = p;
2583 break;
2584 }
2585 for (String str : p.pkgList) {
2586 if (str.equals(packageName)) {
2587 proc = p;
2588 }
2589 }
2590 }
2591 }
2592
2593 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002594 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002595 + " initialPid=" + initialPid
2596 + " packageName=" + packageName);
2597 return;
2598 }
2599
2600 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002601 if (proc.pid == Process.myPid()) {
2602 Log.w(TAG, "crashApplication: trying to crash self!");
2603 return;
2604 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002605 long ident = Binder.clearCallingIdentity();
2606 try {
2607 proc.thread.scheduleCrash(message);
2608 } catch (RemoteException e) {
2609 }
2610 Binder.restoreCallingIdentity(ident);
2611 }
2612 }
2613 }
2614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 public final void finishSubActivity(IBinder token, String resultWho,
2616 int requestCode) {
2617 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002618 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619 if (index < 0) {
2620 return;
2621 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002622 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623
2624 final long origId = Binder.clearCallingIdentity();
2625
2626 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002627 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2628 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 if (r.resultTo == self && r.requestCode == requestCode) {
2630 if ((r.resultWho == null && resultWho == null) ||
2631 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002632 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002633 Activity.RESULT_CANCELED, null, "request-sub");
2634 }
2635 }
2636 }
2637
2638 Binder.restoreCallingIdentity(origId);
2639 }
2640 }
2641
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002642 public boolean willActivityBeVisible(IBinder token) {
2643 synchronized(this) {
2644 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002645 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2646 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002647 if (r == token) {
2648 return true;
2649 }
2650 if (r.fullscreen && !r.finishing) {
2651 return false;
2652 }
2653 }
2654 return true;
2655 }
2656 }
2657
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002658 public void overridePendingTransition(IBinder token, String packageName,
2659 int enterAnim, int exitAnim) {
2660 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002661 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002662 if (index < 0) {
2663 return;
2664 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002665 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002666
2667 final long origId = Binder.clearCallingIdentity();
2668
2669 if (self.state == ActivityState.RESUMED
2670 || self.state == ActivityState.PAUSING) {
2671 mWindowManager.overridePendingAppTransition(packageName,
2672 enterAnim, exitAnim);
2673 }
2674
2675 Binder.restoreCallingIdentity(origId);
2676 }
2677 }
2678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680 * Main function for removing an existing process from the activity manager
2681 * as a result of that process going away. Clears out all connections
2682 * to the process.
2683 */
2684 private final void handleAppDiedLocked(ProcessRecord app,
2685 boolean restarting) {
2686 cleanUpApplicationRecordLocked(app, restarting, -1);
2687 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002688 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 }
2690
2691 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002692 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2693 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2694 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002695 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002696 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2697 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002698 }
2699
2700 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002701 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702
2703 boolean atTop = true;
2704 boolean hasVisibleActivities = false;
2705
2706 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002707 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002708 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002709 TAG, "Removing app " + app + " from history with " + i + " entries");
2710 while (i > 0) {
2711 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002712 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002713 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2715 if (r.app == app) {
2716 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002717 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002718 TAG, "Removing this entry! frozen=" + r.haveState
2719 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002720 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002721 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002722 r.takeFromHistory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723 mWindowManager.removeAppToken(r);
2724 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002725 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002727 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002728
2729 } else {
2730 // We have the current state for this activity, so
2731 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002732 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002733 TAG, "Keeping entry, setting app to null");
2734 if (r.visible) {
2735 hasVisibleActivities = true;
2736 }
2737 r.app = null;
2738 r.nowVisible = false;
2739 if (!r.haveState) {
2740 r.icicle = null;
2741 }
2742 }
2743
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002744 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 r.state = ActivityState.STOPPED;
2746 }
2747 atTop = false;
2748 }
2749
2750 app.activities.clear();
2751
2752 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002753 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002754 + " running instrumentation " + app.instrumentationClass);
2755 Bundle info = new Bundle();
2756 info.putString("shortMsg", "Process crashed.");
2757 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2758 }
2759
2760 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002761 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002762 // If there was nothing to resume, and we are not already
2763 // restarting this process, but there is a visible activity that
2764 // is hosted by the process... then make sure all visible
2765 // activities are running, taking care of restarting this
2766 // process.
2767 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002768 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002769 }
2770 }
2771 }
2772 }
2773
2774 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2775 IBinder threadBinder = thread.asBinder();
2776
2777 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002778 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2779 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002780 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2781 return i;
2782 }
2783 }
2784 return -1;
2785 }
2786
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002787 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002788 IApplicationThread thread) {
2789 if (thread == null) {
2790 return null;
2791 }
2792
2793 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002794 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 }
2796
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002797 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002798 IApplicationThread thread) {
2799
2800 mProcDeaths[0]++;
2801
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002802 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2803 synchronized (stats) {
2804 stats.noteProcessDiedLocked(app.info.uid, pid);
2805 }
2806
Magnus Edlund7bb25812010-02-24 15:45:06 +01002807 // Clean up already done if the process has been re-started.
2808 if (app.pid == pid && app.thread != null &&
2809 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002810 if (!app.killedBackground) {
2811 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2812 + ") has died.");
2813 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002814 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002815 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002816 TAG, "Dying app: " + app + ", pid: " + pid
2817 + ", thread: " + thread.asBinder());
2818 boolean doLowMem = app.instrumentationClass == null;
2819 handleAppDiedLocked(app, false);
2820
2821 if (doLowMem) {
2822 // If there are no longer any background processes running,
2823 // and the app that died was not running instrumentation,
2824 // then tell everyone we are now low on memory.
2825 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002826 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2827 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2829 haveBg = true;
2830 break;
2831 }
2832 }
2833
2834 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002835 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002836 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002837 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002838 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2839 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002840 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002841 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2842 // The low memory report is overriding any current
2843 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002844 // heavy/important/visible/foreground processes first.
2845 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002846 rec.lastRequestedGc = 0;
2847 } else {
2848 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002849 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002850 rec.reportLowMemory = true;
2851 rec.lastLowMemory = now;
2852 mProcessesToGc.remove(rec);
2853 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002854 }
2855 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002856 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002857 }
2858 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002859 } else if (app.pid != pid) {
2860 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002861 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002862 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002863 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002864 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002865 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002866 + thread.asBinder());
2867 }
2868 }
2869
Dan Egnor42471dd2010-01-07 17:25:22 -08002870 /**
2871 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002872 * @param clearTraces causes the dump file to be erased prior to the new
2873 * traces being written, if true; when false, the new traces will be
2874 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002875 * @param firstPids of dalvik VM processes to dump stack traces for first
2876 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002877 * @return file containing stack traces, or null if no dump file is configured
2878 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002879 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2880 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002881 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2882 if (tracesPath == null || tracesPath.length() == 0) {
2883 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002885
2886 File tracesFile = new File(tracesPath);
2887 try {
2888 File tracesDir = tracesFile.getParentFile();
2889 if (!tracesDir.exists()) tracesFile.mkdirs();
2890 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2891
Christopher Tate6ee412d2010-05-28 12:01:56 -07002892 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002893 tracesFile.createNewFile();
2894 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2895 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002896 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002897 return null;
2898 }
2899
2900 // Use a FileObserver to detect when traces finish writing.
2901 // The order of traces is considered important to maintain for legibility.
2902 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2903 public synchronized void onEvent(int event, String path) { notify(); }
2904 };
2905
2906 try {
2907 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002908
2909 // First collect all of the stacks of the most important pids.
2910 try {
2911 int num = firstPids.size();
2912 for (int i = 0; i < num; i++) {
2913 synchronized (observer) {
2914 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2915 observer.wait(200); // Wait for write-close, give up after 200msec
2916 }
2917 }
2918 } catch (InterruptedException e) {
2919 Log.wtf(TAG, e);
2920 }
2921
2922 // Next measure CPU usage.
2923 if (processStats != null) {
2924 processStats.init();
2925 System.gc();
2926 processStats.update();
2927 try {
2928 synchronized (processStats) {
2929 processStats.wait(500); // measure over 1/2 second.
2930 }
2931 } catch (InterruptedException e) {
2932 }
2933 processStats.update();
2934
2935 // We'll take the stack crawls of just the top apps using CPU.
2936 final int N = processStats.countWorkingStats();
2937 int numProcs = 0;
2938 for (int i=0; i<N && numProcs<5; i++) {
2939 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2940 if (lastPids.indexOfKey(stats.pid) >= 0) {
2941 numProcs++;
2942 try {
2943 synchronized (observer) {
2944 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2945 observer.wait(200); // Wait for write-close, give up after 200msec
2946 }
2947 } catch (InterruptedException e) {
2948 Log.wtf(TAG, e);
2949 }
2950
2951 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002952 }
2953 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002954
2955 return tracesFile;
2956
Dan Egnor42471dd2010-01-07 17:25:22 -08002957 } finally {
2958 observer.stopWatching();
2959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 }
2961
Jeff Brown4d94a762010-09-23 11:33:28 -07002962 private final class AppNotResponding implements Runnable {
2963 private final ProcessRecord mApp;
2964 private final String mAnnotation;
2965
2966 public AppNotResponding(ProcessRecord app, String annotation) {
2967 mApp = app;
2968 mAnnotation = annotation;
2969 }
2970
2971 @Override
2972 public void run() {
2973 appNotResponding(mApp, null, null, mAnnotation);
2974 }
2975 }
2976
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002977 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2978 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002979 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2980 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2981
Dianne Hackborn287952c2010-09-22 22:34:31 -07002982 if (mController != null) {
2983 try {
2984 // 0 == continue, -1 = kill process immediately
2985 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2986 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2987 } catch (RemoteException e) {
2988 mController = null;
2989 }
2990 }
2991
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002992 long anrTime = SystemClock.uptimeMillis();
2993 if (MONITOR_CPU_USAGE) {
2994 updateCpuStatsNow();
2995 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002996
2997 synchronized (this) {
2998 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2999 if (mShuttingDown) {
3000 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
3001 return;
3002 } else if (app.notResponding) {
3003 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
3004 return;
3005 } else if (app.crashing) {
3006 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
3007 return;
3008 }
3009
3010 // In case we come through here for the same app before completing
3011 // this one, mark as anring now so we will bail out.
3012 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08003013
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003014 // Log the ANR to the event log.
3015 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
3016 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08003017
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003018 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003019 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003020
3021 int parentPid = app.pid;
3022 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003023 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003024
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003025 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08003026
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003027 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
3028 ProcessRecord r = mLruProcesses.get(i);
3029 if (r != null && r.thread != null) {
3030 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003031 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
3032 if (r.persistent) {
3033 firstPids.add(pid);
3034 } else {
3035 lastPids.put(pid, Boolean.TRUE);
3036 }
3037 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003038 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003039 }
3040 }
3041
Dan Egnor42471dd2010-01-07 17:25:22 -08003042 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003043 StringBuilder info = mStringBuilder;
3044 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08003045 info.append("ANR in ").append(app.processName);
3046 if (activity != null && activity.shortComponentName != null) {
3047 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07003048 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08003049 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003050 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003051 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003053 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003054 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003056
Dianne Hackborn287952c2010-09-22 22:34:31 -07003057 final ProcessStats processStats = new ProcessStats(true);
3058
3059 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
3060
Dan Egnor42471dd2010-01-07 17:25:22 -08003061 String cpuInfo = null;
3062 if (MONITOR_CPU_USAGE) {
3063 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003064 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003065 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003066 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003067 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08003068 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 }
3070
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003071 info.append(processStats.printCurrentState(anrTime));
3072
Joe Onorato8a9b2202010-02-26 18:56:32 -08003073 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08003074 if (tracesFile == null) {
3075 // There is no trace file, so dump (only) the alleged culprit's threads to the log
3076 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
3077 }
3078
3079 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
3080
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003081 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08003083 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
3084 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003085 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003086 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3087 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003088 }
3089 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003090 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003091 }
3092 }
3093
Dan Egnor42471dd2010-01-07 17:25:22 -08003094 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
3095 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
3096 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003097
3098 synchronized (this) {
3099 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003100 Slog.w(TAG, "Killing " + app + ": background ANR");
3101 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
3102 app.processName, app.setAdj, "background ANR");
3103 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003104 return;
3105 }
3106
3107 // Set the app's notResponding state, and look up the errorReportReceiver
3108 makeAppNotRespondingLocked(app,
3109 activity != null ? activity.shortComponentName : null,
3110 annotation != null ? "ANR " + annotation : "ANR",
3111 info.toString());
3112
3113 // Bring up the infamous App Not Responding dialog
3114 Message msg = Message.obtain();
3115 HashMap map = new HashMap();
3116 msg.what = SHOW_NOT_RESPONDING_MSG;
3117 msg.obj = map;
3118 map.put("app", app);
3119 if (activity != null) {
3120 map.put("activity", activity);
3121 }
3122
3123 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003125 }
3126
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003127 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3128 if (!mLaunchWarningShown) {
3129 mLaunchWarningShown = true;
3130 mHandler.post(new Runnable() {
3131 @Override
3132 public void run() {
3133 synchronized (ActivityManagerService.this) {
3134 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3135 d.show();
3136 mHandler.postDelayed(new Runnable() {
3137 @Override
3138 public void run() {
3139 synchronized (ActivityManagerService.this) {
3140 d.dismiss();
3141 mLaunchWarningShown = false;
3142 }
3143 }
3144 }, 4000);
3145 }
3146 }
3147 });
3148 }
3149 }
3150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003151 public boolean clearApplicationUserData(final String packageName,
3152 final IPackageDataObserver observer) {
3153 int uid = Binder.getCallingUid();
3154 int pid = Binder.getCallingPid();
3155 long callingId = Binder.clearCallingIdentity();
3156 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003157 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003158 int pkgUid = -1;
3159 synchronized(this) {
3160 try {
3161 pkgUid = pm.getPackageUid(packageName);
3162 } catch (RemoteException e) {
3163 }
3164 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003165 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 return false;
3167 }
3168 if (uid == pkgUid || checkComponentPermission(
3169 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003170 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003171 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003172 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003173 } else {
3174 throw new SecurityException(pid+" does not have permission:"+
3175 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3176 "for process:"+packageName);
3177 }
3178 }
3179
3180 try {
3181 //clear application user data
3182 pm.clearApplicationUserData(packageName, observer);
3183 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3184 Uri.fromParts("package", packageName, null));
3185 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003186 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3187 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003188 } catch (RemoteException e) {
3189 }
3190 } finally {
3191 Binder.restoreCallingIdentity(callingId);
3192 }
3193 return true;
3194 }
3195
Dianne Hackborn03abb812010-01-04 18:43:19 -08003196 public void killBackgroundProcesses(final String packageName) {
3197 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3198 != PackageManager.PERMISSION_GRANTED &&
3199 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3200 != PackageManager.PERMISSION_GRANTED) {
3201 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003202 + Binder.getCallingPid()
3203 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003204 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003205 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 throw new SecurityException(msg);
3207 }
3208
3209 long callingId = Binder.clearCallingIdentity();
3210 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003211 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212 int pkgUid = -1;
3213 synchronized(this) {
3214 try {
3215 pkgUid = pm.getPackageUid(packageName);
3216 } catch (RemoteException e) {
3217 }
3218 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003219 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003220 return;
3221 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003222 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003223 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003224 }
3225 } finally {
3226 Binder.restoreCallingIdentity(callingId);
3227 }
3228 }
3229
3230 public void forceStopPackage(final String packageName) {
3231 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3232 != PackageManager.PERMISSION_GRANTED) {
3233 String msg = "Permission Denial: forceStopPackage() from pid="
3234 + Binder.getCallingPid()
3235 + ", uid=" + Binder.getCallingUid()
3236 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003237 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003238 throw new SecurityException(msg);
3239 }
3240
3241 long callingId = Binder.clearCallingIdentity();
3242 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003243 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003244 int pkgUid = -1;
3245 synchronized(this) {
3246 try {
3247 pkgUid = pm.getPackageUid(packageName);
3248 } catch (RemoteException e) {
3249 }
3250 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003251 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003252 return;
3253 }
3254 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003255 try {
3256 pm.setPackageStoppedState(packageName, true);
3257 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003258 } catch (IllegalArgumentException e) {
3259 Slog.w(TAG, "Failed trying to unstop package "
3260 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003261 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 }
3263 } finally {
3264 Binder.restoreCallingIdentity(callingId);
3265 }
3266 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003267
3268 /*
3269 * The pkg name and uid have to be specified.
3270 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3271 */
3272 public void killApplicationWithUid(String pkg, int uid) {
3273 if (pkg == null) {
3274 return;
3275 }
3276 // Make sure the uid is valid.
3277 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003278 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003279 return;
3280 }
3281 int callerUid = Binder.getCallingUid();
3282 // Only the system server can kill an application
3283 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003284 // Post an aysnc message to kill the application
3285 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3286 msg.arg1 = uid;
3287 msg.arg2 = 0;
3288 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003289 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003290 } else {
3291 throw new SecurityException(callerUid + " cannot kill pkg: " +
3292 pkg);
3293 }
3294 }
3295
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003296 public void closeSystemDialogs(String reason) {
3297 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003298 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003299 if (reason != null) {
3300 intent.putExtra("reason", reason);
3301 }
3302
3303 final int uid = Binder.getCallingUid();
3304 final long origId = Binder.clearCallingIdentity();
3305 synchronized (this) {
3306 int i = mWatchers.beginBroadcast();
3307 while (i > 0) {
3308 i--;
3309 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3310 if (w != null) {
3311 try {
3312 w.closingSystemDialogs(reason);
3313 } catch (RemoteException e) {
3314 }
3315 }
3316 }
3317 mWatchers.finishBroadcast();
3318
Dianne Hackbornffa42482009-09-23 22:20:11 -07003319 mWindowManager.closeSystemDialogs(reason);
3320
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003321 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3322 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003323 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003324 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003325 Activity.RESULT_CANCELED, null, "close-sys");
3326 }
3327 }
3328
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003329 broadcastIntentLocked(null, null, intent, null,
3330 null, 0, null, null, null, false, false, -1, uid);
3331 }
3332 Binder.restoreCallingIdentity(origId);
3333 }
3334
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003335 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003336 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003337 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3338 for (int i=pids.length-1; i>=0; i--) {
3339 infos[i] = new Debug.MemoryInfo();
3340 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003341 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003342 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003343 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003344
3345 public void killApplicationProcess(String processName, int uid) {
3346 if (processName == null) {
3347 return;
3348 }
3349
3350 int callerUid = Binder.getCallingUid();
3351 // Only the system server can kill an application
3352 if (callerUid == Process.SYSTEM_UID) {
3353 synchronized (this) {
3354 ProcessRecord app = getProcessRecordLocked(processName, uid);
Christopher Tate4a627c72011-04-01 14:43:32 -07003355 if (app != null && app.thread != null) {
Christopher Tate5e1ab332009-09-01 20:32:49 -07003356 try {
3357 app.thread.scheduleSuicide();
3358 } catch (RemoteException e) {
3359 // If the other end already died, then our work here is done.
3360 }
3361 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003362 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003363 + processName + " / " + uid);
3364 }
3365 }
3366 } else {
3367 throw new SecurityException(callerUid + " cannot kill app process: " +
3368 processName);
3369 }
3370 }
3371
Dianne Hackborn03abb812010-01-04 18:43:19 -08003372 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003373 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3375 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003376 if (!mProcessesReady) {
3377 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379 intent.putExtra(Intent.EXTRA_UID, uid);
3380 broadcastIntentLocked(null, null, intent,
3381 null, null, 0, null, null, null,
3382 false, false, MY_PID, Process.SYSTEM_UID);
3383 }
3384
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003385 private final boolean killPackageProcessesLocked(String packageName, int uid,
3386 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003387 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388
Dianne Hackborn03abb812010-01-04 18:43:19 -08003389 // Remove all processes this package may have touched: all with the
3390 // same UID (except for the system or root user), and all whose name
3391 // matches the package name.
3392 final String procNamePrefix = packageName + ":";
3393 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3394 final int NA = apps.size();
3395 for (int ia=0; ia<NA; ia++) {
3396 ProcessRecord app = apps.valueAt(ia);
3397 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003398 if (doit) {
3399 procs.add(app);
3400 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003401 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3402 || app.processName.equals(packageName)
3403 || app.processName.startsWith(procNamePrefix)) {
3404 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003405 if (!doit) {
3406 return true;
3407 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003408 app.removed = true;
3409 procs.add(app);
3410 }
3411 }
3412 }
3413 }
3414
3415 int N = procs.size();
3416 for (int i=0; i<N; i++) {
3417 removeProcessLocked(procs.get(i), callerWillRestart);
3418 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003419 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003420 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003421
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003422 private final boolean forceStopPackageLocked(String name, int uid,
3423 boolean callerWillRestart, boolean purgeCache, boolean doit) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07003424 int i;
3425 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 if (uid < 0) {
3428 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003429 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 } catch (RemoteException e) {
3431 }
3432 }
3433
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003434 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003435 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003436
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003437 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3438 while (badApps.hasNext()) {
3439 SparseArray<Long> ba = badApps.next();
3440 if (ba.get(uid) != null) {
3441 badApps.remove();
3442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003443 }
3444 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003445
3446 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3447 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003449 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3450 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003452 if (!doit) {
3453 return true;
3454 }
3455 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003456 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 if (r.app != null) {
3458 r.app.removed = true;
3459 }
3460 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003461 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003462 }
3463 }
3464
3465 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3466 for (ServiceRecord service : mServices.values()) {
3467 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003468 if (!doit) {
3469 return true;
3470 }
3471 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003472 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 if (service.app != null) {
3474 service.app.removed = true;
3475 }
3476 service.app = null;
3477 services.add(service);
3478 }
3479 }
3480
3481 N = services.size();
3482 for (i=0; i<N; i++) {
3483 bringDownServiceLocked(services.get(i), true);
3484 }
3485
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003486 if (doit) {
3487 if (purgeCache) {
3488 AttributeCache ac = AttributeCache.instance();
3489 if (ac != null) {
3490 ac.removePackage(name);
3491 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003492 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003493 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003494 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003495
3496 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 }
3498
3499 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3500 final String name = app.processName;
3501 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003502 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003503 TAG, "Force removing process " + app + " (" + name
3504 + "/" + uid + ")");
3505
3506 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003507 if (mHeavyWeightProcess == app) {
3508 mHeavyWeightProcess = null;
3509 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3510 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003511 boolean needRestart = false;
3512 if (app.pid > 0 && app.pid != MY_PID) {
3513 int pid = app.pid;
3514 synchronized (mPidsSelfLocked) {
3515 mPidsSelfLocked.remove(pid);
3516 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3517 }
3518 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003519 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520 Process.killProcess(pid);
3521
3522 if (app.persistent) {
3523 if (!callerWillRestart) {
3524 addAppLocked(app.info);
3525 } else {
3526 needRestart = true;
3527 }
3528 }
3529 } else {
3530 mRemovedProcesses.add(app);
3531 }
3532
3533 return needRestart;
3534 }
3535
3536 private final void processStartTimedOutLocked(ProcessRecord app) {
3537 final int pid = app.pid;
3538 boolean gone = false;
3539 synchronized (mPidsSelfLocked) {
3540 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3541 if (knownApp != null && knownApp.thread == null) {
3542 mPidsSelfLocked.remove(pid);
3543 gone = true;
3544 }
3545 }
3546
3547 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003548 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003549 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003550 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003552 if (mHeavyWeightProcess == app) {
3553 mHeavyWeightProcess = null;
3554 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3555 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003556 // Take care of any launching providers waiting for this process.
3557 checkAppInLaunchingProvidersLocked(app, true);
3558 // Take care of any services that are waiting for the process.
3559 for (int i=0; i<mPendingServices.size(); i++) {
3560 ServiceRecord sr = mPendingServices.get(i);
3561 if (app.info.uid == sr.appInfo.uid
3562 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003563 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003564 mPendingServices.remove(i);
3565 i--;
3566 bringDownServiceLocked(sr, true);
3567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003569 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
3570 app.processName, app.setAdj, "start timeout");
3571 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003572 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003573 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003574 try {
3575 IBackupManager bm = IBackupManager.Stub.asInterface(
3576 ServiceManager.getService(Context.BACKUP_SERVICE));
3577 bm.agentDisconnected(app.info.packageName);
3578 } catch (RemoteException e) {
3579 // Can't happen; the backup manager is local
3580 }
3581 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003582 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003583 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003584 mPendingBroadcast.state = BroadcastRecord.IDLE;
3585 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003586 mPendingBroadcast = null;
3587 scheduleBroadcastsLocked();
3588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003590 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 }
3592 }
3593
3594 private final boolean attachApplicationLocked(IApplicationThread thread,
3595 int pid) {
3596
3597 // Find the application record that is being attached... either via
3598 // the pid if we are running in multiple processes, or just pull the
3599 // next app record if we are emulating process with anonymous threads.
3600 ProcessRecord app;
3601 if (pid != MY_PID && pid >= 0) {
3602 synchronized (mPidsSelfLocked) {
3603 app = mPidsSelfLocked.get(pid);
3604 }
3605 } else if (mStartingProcesses.size() > 0) {
3606 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003607 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608 } else {
3609 app = null;
3610 }
3611
3612 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003613 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003615 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003617 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 } else {
3619 try {
3620 thread.scheduleExit();
3621 } catch (Exception e) {
3622 // Ignore exceptions.
3623 }
3624 }
3625 return false;
3626 }
3627
3628 // If this application record is still attached to a previous
3629 // process, clean it up now.
3630 if (app.thread != null) {
3631 handleAppDiedLocked(app, true);
3632 }
3633
3634 // Tell the process all about itself.
3635
Joe Onorato8a9b2202010-02-26 18:56:32 -08003636 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637 TAG, "Binding process pid " + pid + " to record " + app);
3638
3639 String processName = app.processName;
3640 try {
3641 thread.asBinder().linkToDeath(new AppDeathRecipient(
3642 app, pid, thread), 0);
3643 } catch (RemoteException e) {
3644 app.resetPackageList();
3645 startProcessLocked(app, "link fail", processName);
3646 return false;
3647 }
3648
Doug Zongker2bec3d42009-12-04 12:52:44 -08003649 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650
3651 app.thread = thread;
3652 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003653 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3654 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003655 app.forcingToForeground = null;
3656 app.foregroundServices = false;
3657 app.debugging = false;
3658
3659 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3660
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003661 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003662 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003664 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003665 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003666 }
3667
Joe Onorato8a9b2202010-02-26 18:56:32 -08003668 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 TAG, "New app record " + app
3670 + " thread=" + thread.asBinder() + " pid=" + pid);
3671 try {
3672 int testMode = IApplicationThread.DEBUG_OFF;
3673 if (mDebugApp != null && mDebugApp.equals(processName)) {
3674 testMode = mWaitForDebugger
3675 ? IApplicationThread.DEBUG_WAIT
3676 : IApplicationThread.DEBUG_ON;
3677 app.debugging = true;
3678 if (mDebugTransient) {
3679 mDebugApp = mOrigDebugApp;
3680 mWaitForDebugger = mOrigWaitForDebugger;
3681 }
3682 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003683
Christopher Tate181fafa2009-05-14 11:12:14 -07003684 // If the app is being launched for restore or full backup, set it up specially
3685 boolean isRestrictedBackupMode = false;
3686 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3687 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07003688 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07003689 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3690 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003691
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003692 ensurePackageDexOpt(app.instrumentationInfo != null
3693 ? app.instrumentationInfo.packageName
3694 : app.info.packageName);
3695 if (app.instrumentationClass != null) {
3696 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003697 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003698 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003699 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003700 ApplicationInfo appInfo = app.instrumentationInfo != null
3701 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003702 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003703 thread.bindApplication(processName, appInfo, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003704 app.instrumentationClass, app.instrumentationProfileFile,
3705 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003706 isRestrictedBackupMode || !normalMode,
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003707 mConfiguration, app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003708 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003709 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003710 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003711 } catch (Exception e) {
3712 // todo: Yikes! What should we do? For now we will try to
3713 // start another process, but that could easily get us in
3714 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003715 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003716
3717 app.resetPackageList();
3718 startProcessLocked(app, "bind fail", processName);
3719 return false;
3720 }
3721
3722 // Remove this record from the list of starting applications.
3723 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003724 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3725 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003726 mProcessesOnHold.remove(app);
3727
3728 boolean badApp = false;
3729 boolean didSomething = false;
3730
3731 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003732 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003733 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003734 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3735 && processName.equals(hr.processName)) {
3736 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003737 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003738 didSomething = true;
3739 }
3740 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003741 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742 + hr.intent.getComponent().flattenToShortString(), e);
3743 badApp = true;
3744 }
3745 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003746 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003747 }
3748 }
3749
3750 // Find any services that should be running in this process...
3751 if (!badApp && mPendingServices.size() > 0) {
3752 ServiceRecord sr = null;
3753 try {
3754 for (int i=0; i<mPendingServices.size(); i++) {
3755 sr = mPendingServices.get(i);
3756 if (app.info.uid != sr.appInfo.uid
3757 || !processName.equals(sr.processName)) {
3758 continue;
3759 }
3760
3761 mPendingServices.remove(i);
3762 i--;
3763 realStartServiceLocked(sr, app);
3764 didSomething = true;
3765 }
3766 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003767 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003768 + sr.shortName, e);
3769 badApp = true;
3770 }
3771 }
3772
3773 // Check if the next broadcast receiver is in this process...
3774 BroadcastRecord br = mPendingBroadcast;
3775 if (!badApp && br != null && br.curApp == app) {
3776 try {
3777 mPendingBroadcast = null;
3778 processCurBroadcastLocked(br, app);
3779 didSomething = true;
3780 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003781 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782 + br.curComponent.flattenToShortString(), e);
3783 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003784 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003785 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3786 br.resultExtras, br.resultAbort, true);
3787 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003788 // We need to reset the state if we fails to start the receiver.
3789 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790 }
3791 }
3792
Christopher Tate181fafa2009-05-14 11:12:14 -07003793 // Check whether the next backup agent is in this process...
3794 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003795 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003796 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003797 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003798 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
3799 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
3800 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07003801 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003802 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003803 e.printStackTrace();
3804 }
3805 }
3806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 if (badApp) {
3808 // todo: Also need to kill application to deal with all
3809 // kinds of exceptions.
3810 handleAppDiedLocked(app, false);
3811 return false;
3812 }
3813
3814 if (!didSomething) {
3815 updateOomAdjLocked();
3816 }
3817
3818 return true;
3819 }
3820
3821 public final void attachApplication(IApplicationThread thread) {
3822 synchronized (this) {
3823 int callingPid = Binder.getCallingPid();
3824 final long origId = Binder.clearCallingIdentity();
3825 attachApplicationLocked(thread, callingPid);
3826 Binder.restoreCallingIdentity(origId);
3827 }
3828 }
3829
Dianne Hackborne88846e2009-09-30 21:34:25 -07003830 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003832 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003833 Binder.restoreCallingIdentity(origId);
3834 }
3835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003837 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003838 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 mWindowManager.enableScreenAfterBoot();
3840 }
3841
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003842 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003843 IntentFilter pkgFilter = new IntentFilter();
3844 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3845 pkgFilter.addDataScheme("package");
3846 mContext.registerReceiver(new BroadcastReceiver() {
3847 @Override
3848 public void onReceive(Context context, Intent intent) {
3849 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3850 if (pkgs != null) {
3851 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003852 synchronized (ActivityManagerService.this) {
3853 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3854 setResultCode(Activity.RESULT_OK);
3855 return;
3856 }
3857 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003858 }
3859 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003860 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003861 }, pkgFilter);
3862
3863 synchronized (this) {
3864 // Ensure that any processes we had put on hold are now started
3865 // up.
3866 final int NP = mProcessesOnHold.size();
3867 if (NP > 0) {
3868 ArrayList<ProcessRecord> procs =
3869 new ArrayList<ProcessRecord>(mProcessesOnHold);
3870 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003871 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3872 + procs.get(ip));
3873 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003874 }
3875 }
3876
3877 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003878 // Start looking for apps that are abusing wake locks.
3879 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003880 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003881 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003882 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003883 broadcastIntentLocked(null, null,
3884 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3885 null, null, 0, null, null,
3886 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3887 false, false, MY_PID, Process.SYSTEM_UID);
3888 }
3889 }
3890 }
3891
3892 final void ensureBootCompleted() {
3893 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003894 boolean enableScreen;
3895 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003896 booting = mBooting;
3897 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003898 enableScreen = !mBooted;
3899 mBooted = true;
3900 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003901
3902 if (booting) {
3903 finishBooting();
3904 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003905
3906 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003907 enableScreenAfterBoot();
3908 }
3909 }
3910
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003911 public final void activityPaused(IBinder token) {
3912 final long origId = Binder.clearCallingIdentity();
3913 mMainStack.activityPaused(token, false);
3914 Binder.restoreCallingIdentity(origId);
3915 }
3916
3917 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3918 CharSequence description) {
3919 if (localLOGV) Slog.v(
3920 TAG, "Activity stopped: token=" + token);
3921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003922 // Refuse possible leaked file descriptors
3923 if (icicle != null && icicle.hasFileDescriptors()) {
3924 throw new IllegalArgumentException("File descriptors passed in Bundle");
3925 }
3926
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003927 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928
3929 final long origId = Binder.clearCallingIdentity();
3930
3931 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003932 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003933 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003934 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003935 r.icicle = icicle;
3936 r.haveState = true;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003937 r.updateThumbnail(thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 r.stopped = true;
3939 r.state = ActivityState.STOPPED;
3940 if (!r.finishing) {
3941 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003942 r.stack.destroyActivityLocked(r, true);
3943 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944 }
3945 }
3946 }
3947 }
3948
3949 if (r != null) {
3950 sendPendingThumbnail(r, null, null, null, false);
3951 }
3952
3953 trimApplications();
3954
3955 Binder.restoreCallingIdentity(origId);
3956 }
3957
3958 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003959 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003960 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003961 }
3962
3963 public String getCallingPackage(IBinder token) {
3964 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003965 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003966 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003967 }
3968 }
3969
3970 public ComponentName getCallingActivity(IBinder token) {
3971 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003972 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003973 return r != null ? r.intent.getComponent() : null;
3974 }
3975 }
3976
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003977 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003978 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003980 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003981 if (r != null) {
3982 return r.resultTo;
3983 }
3984 }
3985 return null;
3986 }
3987
3988 public ComponentName getActivityClassForToken(IBinder token) {
3989 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003990 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003991 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003992 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 return r.intent.getComponent();
3994 }
3995 return null;
3996 }
3997 }
3998
3999 public String getPackageForToken(IBinder token) {
4000 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004001 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004002 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004003 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 return r.packageName;
4005 }
4006 return null;
4007 }
4008 }
4009
4010 public IIntentSender getIntentSender(int type,
4011 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004012 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004013 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004014 if (intents != null) {
4015 if (intents.length < 1) {
4016 throw new IllegalArgumentException("Intents array length must be >= 1");
4017 }
4018 for (int i=0; i<intents.length; i++) {
4019 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07004020 if (intent != null) {
4021 if (intent.hasFileDescriptors()) {
4022 throw new IllegalArgumentException("File descriptors passed in Intent");
4023 }
4024 if (type == INTENT_SENDER_BROADCAST &&
4025 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
4026 throw new IllegalArgumentException(
4027 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
4028 }
4029 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004030 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004031 }
4032 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004033 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004034 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004035 }
4036 }
4037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 synchronized(this) {
4039 int callingUid = Binder.getCallingUid();
4040 try {
4041 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
4042 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004043 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004044 .getPackageUid(packageName);
4045 if (uid != Binder.getCallingUid()) {
4046 String msg = "Permission Denial: getIntentSender() from pid="
4047 + Binder.getCallingPid()
4048 + ", uid=" + Binder.getCallingUid()
4049 + ", (need uid=" + uid + ")"
4050 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004051 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004052 throw new SecurityException(msg);
4053 }
4054 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004055
4056 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004057 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004059 } catch (RemoteException e) {
4060 throw new SecurityException(e);
4061 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004062 }
4063 }
4064
4065 IIntentSender getIntentSenderLocked(int type,
4066 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004067 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004068 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004069 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004070 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004071 if (index < 0) {
4072 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004073 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004074 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004075 if (activity.finishing) {
4076 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004078 }
4079
4080 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4081 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4082 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4083 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4084 |PendingIntent.FLAG_UPDATE_CURRENT);
4085
4086 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4087 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004088 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004089 WeakReference<PendingIntentRecord> ref;
4090 ref = mIntentSenderRecords.get(key);
4091 PendingIntentRecord rec = ref != null ? ref.get() : null;
4092 if (rec != null) {
4093 if (!cancelCurrent) {
4094 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004095 if (rec.key.requestIntent != null) {
4096 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4097 }
4098 if (intents != null) {
4099 intents[intents.length-1] = rec.key.requestIntent;
4100 rec.key.allIntents = intents;
4101 rec.key.allResolvedTypes = resolvedTypes;
4102 } else {
4103 rec.key.allIntents = null;
4104 rec.key.allResolvedTypes = null;
4105 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 return rec;
4108 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004109 rec.canceled = true;
4110 mIntentSenderRecords.remove(key);
4111 }
4112 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004113 return rec;
4114 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004115 rec = new PendingIntentRecord(this, key, callingUid);
4116 mIntentSenderRecords.put(key, rec.ref);
4117 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4118 if (activity.pendingResults == null) {
4119 activity.pendingResults
4120 = new HashSet<WeakReference<PendingIntentRecord>>();
4121 }
4122 activity.pendingResults.add(rec.ref);
4123 }
4124 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125 }
4126
4127 public void cancelIntentSender(IIntentSender sender) {
4128 if (!(sender instanceof PendingIntentRecord)) {
4129 return;
4130 }
4131 synchronized(this) {
4132 PendingIntentRecord rec = (PendingIntentRecord)sender;
4133 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004134 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004135 .getPackageUid(rec.key.packageName);
4136 if (uid != Binder.getCallingUid()) {
4137 String msg = "Permission Denial: cancelIntentSender() from pid="
4138 + Binder.getCallingPid()
4139 + ", uid=" + Binder.getCallingUid()
4140 + " is not allowed to cancel packges "
4141 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004142 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004143 throw new SecurityException(msg);
4144 }
4145 } catch (RemoteException e) {
4146 throw new SecurityException(e);
4147 }
4148 cancelIntentSenderLocked(rec, true);
4149 }
4150 }
4151
4152 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4153 rec.canceled = true;
4154 mIntentSenderRecords.remove(rec.key);
4155 if (cleanActivity && rec.key.activity != null) {
4156 rec.key.activity.pendingResults.remove(rec.ref);
4157 }
4158 }
4159
4160 public String getPackageForIntentSender(IIntentSender pendingResult) {
4161 if (!(pendingResult instanceof PendingIntentRecord)) {
4162 return null;
4163 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004164 try {
4165 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4166 return res.key.packageName;
4167 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004168 }
4169 return null;
4170 }
4171
Dianne Hackborn6c418d52011-06-29 14:05:33 -07004172 public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
4173 if (!(pendingResult instanceof PendingIntentRecord)) {
4174 return false;
4175 }
4176 try {
4177 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4178 if (res.key.allIntents == null) {
4179 return false;
4180 }
4181 for (int i=0; i<res.key.allIntents.length; i++) {
4182 Intent intent = res.key.allIntents[i];
4183 if (intent.getPackage() != null && intent.getComponent() != null) {
4184 return false;
4185 }
4186 }
4187 return true;
4188 } catch (ClassCastException e) {
4189 }
4190 return false;
4191 }
4192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193 public void setProcessLimit(int max) {
4194 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4195 "setProcessLimit()");
4196 mProcessLimit = max;
4197 }
4198
4199 public int getProcessLimit() {
4200 return mProcessLimit;
4201 }
4202
4203 void foregroundTokenDied(ForegroundToken token) {
4204 synchronized (ActivityManagerService.this) {
4205 synchronized (mPidsSelfLocked) {
4206 ForegroundToken cur
4207 = mForegroundProcesses.get(token.pid);
4208 if (cur != token) {
4209 return;
4210 }
4211 mForegroundProcesses.remove(token.pid);
4212 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4213 if (pr == null) {
4214 return;
4215 }
4216 pr.forcingToForeground = null;
4217 pr.foregroundServices = false;
4218 }
4219 updateOomAdjLocked();
4220 }
4221 }
4222
4223 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4224 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4225 "setProcessForeground()");
4226 synchronized(this) {
4227 boolean changed = false;
4228
4229 synchronized (mPidsSelfLocked) {
4230 ProcessRecord pr = mPidsSelfLocked.get(pid);
4231 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004232 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004233 return;
4234 }
4235 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4236 if (oldToken != null) {
4237 oldToken.token.unlinkToDeath(oldToken, 0);
4238 mForegroundProcesses.remove(pid);
4239 pr.forcingToForeground = null;
4240 changed = true;
4241 }
4242 if (isForeground && token != null) {
4243 ForegroundToken newToken = new ForegroundToken() {
4244 public void binderDied() {
4245 foregroundTokenDied(this);
4246 }
4247 };
4248 newToken.pid = pid;
4249 newToken.token = token;
4250 try {
4251 token.linkToDeath(newToken, 0);
4252 mForegroundProcesses.put(pid, newToken);
4253 pr.forcingToForeground = token;
4254 changed = true;
4255 } catch (RemoteException e) {
4256 // If the process died while doing this, we will later
4257 // do the cleanup with the process death link.
4258 }
4259 }
4260 }
4261
4262 if (changed) {
4263 updateOomAdjLocked();
4264 }
4265 }
4266 }
4267
4268 // =========================================================
4269 // PERMISSIONS
4270 // =========================================================
4271
4272 static class PermissionController extends IPermissionController.Stub {
4273 ActivityManagerService mActivityManagerService;
4274 PermissionController(ActivityManagerService activityManagerService) {
4275 mActivityManagerService = activityManagerService;
4276 }
4277
4278 public boolean checkPermission(String permission, int pid, int uid) {
4279 return mActivityManagerService.checkPermission(permission, pid,
4280 uid) == PackageManager.PERMISSION_GRANTED;
4281 }
4282 }
4283
4284 /**
4285 * This can be called with or without the global lock held.
4286 */
4287 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004288 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 // We might be performing an operation on behalf of an indirect binder
4290 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4291 // client identity accordingly before proceeding.
4292 Identity tlsIdentity = sCallerIdentity.get();
4293 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004294 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4296 uid = tlsIdentity.uid;
4297 pid = tlsIdentity.pid;
4298 }
4299
4300 // Root, system server and our own process get to do everything.
4301 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4302 !Process.supportsProcesses()) {
4303 return PackageManager.PERMISSION_GRANTED;
4304 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004305 // If there is a uid that owns whatever is being accessed, it has
4306 // blanket access to it regardless of the permissions it requires.
4307 if (owningUid >= 0 && uid == owningUid) {
4308 return PackageManager.PERMISSION_GRANTED;
4309 }
4310 // If the target is not exported, then nobody else can get to it.
4311 if (!exported) {
4312 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004313 return PackageManager.PERMISSION_DENIED;
4314 }
4315 if (permission == null) {
4316 return PackageManager.PERMISSION_GRANTED;
4317 }
4318 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004319 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 .checkUidPermission(permission, uid);
4321 } catch (RemoteException e) {
4322 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004323 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004324 }
4325 return PackageManager.PERMISSION_DENIED;
4326 }
4327
4328 /**
4329 * As the only public entry point for permissions checking, this method
4330 * can enforce the semantic that requesting a check on a null global
4331 * permission is automatically denied. (Internally a null permission
4332 * string is used when calling {@link #checkComponentPermission} in cases
4333 * when only uid-based security is needed.)
4334 *
4335 * This can be called with or without the global lock held.
4336 */
4337 public int checkPermission(String permission, int pid, int uid) {
4338 if (permission == null) {
4339 return PackageManager.PERMISSION_DENIED;
4340 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004341 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004342 }
4343
4344 /**
4345 * Binder IPC calls go through the public entry point.
4346 * This can be called with or without the global lock held.
4347 */
4348 int checkCallingPermission(String permission) {
4349 return checkPermission(permission,
4350 Binder.getCallingPid(),
4351 Binder.getCallingUid());
4352 }
4353
4354 /**
4355 * This can be called with or without the global lock held.
4356 */
4357 void enforceCallingPermission(String permission, String func) {
4358 if (checkCallingPermission(permission)
4359 == PackageManager.PERMISSION_GRANTED) {
4360 return;
4361 }
4362
4363 String msg = "Permission Denial: " + func + " from pid="
4364 + Binder.getCallingPid()
4365 + ", uid=" + Binder.getCallingUid()
4366 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004367 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368 throw new SecurityException(msg);
4369 }
4370
4371 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004372 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4373 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4374 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4375 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4376 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004377 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004378 // Is the component private from the target uid?
4379 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4380
4381 // Acceptable if the there is no read permission needed from the
4382 // target or the target is holding the read permission.
4383 if (!readPerm) {
4384 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004386 == PackageManager.PERMISSION_GRANTED)) {
4387 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004388 }
4389 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004390
4391 // Acceptable if the there is no write permission needed from the
4392 // target or the target is holding the read permission.
4393 if (!writePerm) {
4394 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004395 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004396 == PackageManager.PERMISSION_GRANTED)) {
4397 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004398 }
4399 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004400
4401 // Acceptable if there is a path permission matching the URI that
4402 // the target holds the permission on.
4403 PathPermission[] pps = pi.pathPermissions;
4404 if (pps != null && (!readPerm || !writePerm)) {
4405 final String path = uri.getPath();
4406 int i = pps.length;
4407 while (i > 0 && (!readPerm || !writePerm)) {
4408 i--;
4409 PathPermission pp = pps[i];
4410 if (!readPerm) {
4411 final String pprperm = pp.getReadPermission();
4412 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4413 + pprperm + " for " + pp.getPath()
4414 + ": match=" + pp.match(path)
4415 + " check=" + pm.checkUidPermission(pprperm, uid));
4416 if (pprperm != null && pp.match(path) &&
4417 (pm.checkUidPermission(pprperm, uid)
4418 == PackageManager.PERMISSION_GRANTED)) {
4419 readPerm = true;
4420 }
4421 }
4422 if (!writePerm) {
4423 final String ppwperm = pp.getWritePermission();
4424 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4425 + ppwperm + " for " + pp.getPath()
4426 + ": match=" + pp.match(path)
4427 + " check=" + pm.checkUidPermission(ppwperm, uid));
4428 if (ppwperm != null && pp.match(path) &&
4429 (pm.checkUidPermission(ppwperm, uid)
4430 == PackageManager.PERMISSION_GRANTED)) {
4431 writePerm = true;
4432 }
4433 }
4434 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 } catch (RemoteException e) {
4437 return false;
4438 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004439
4440 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 }
4442
4443 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4444 int modeFlags) {
4445 // Root gets to do everything.
4446 if (uid == 0 || !Process.supportsProcesses()) {
4447 return true;
4448 }
4449 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4450 if (perms == null) return false;
4451 UriPermission perm = perms.get(uri);
4452 if (perm == null) return false;
4453 return (modeFlags&perm.modeFlags) == modeFlags;
4454 }
4455
4456 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4457 // Another redirected-binder-call permissions check as in
4458 // {@link checkComponentPermission}.
4459 Identity tlsIdentity = sCallerIdentity.get();
4460 if (tlsIdentity != null) {
4461 uid = tlsIdentity.uid;
4462 pid = tlsIdentity.pid;
4463 }
4464
4465 // Our own process gets to do everything.
4466 if (pid == MY_PID) {
4467 return PackageManager.PERMISSION_GRANTED;
4468 }
4469 synchronized(this) {
4470 return checkUriPermissionLocked(uri, uid, modeFlags)
4471 ? PackageManager.PERMISSION_GRANTED
4472 : PackageManager.PERMISSION_DENIED;
4473 }
4474 }
4475
Dianne Hackborn39792d22010-08-19 18:01:52 -07004476 /**
4477 * Check if the targetPkg can be granted permission to access uri by
4478 * the callingUid using the given modeFlags. Throws a security exception
4479 * if callingUid is not allowed to do this. Returns the uid of the target
4480 * if the URI permission grant should be performed; returns -1 if it is not
4481 * needed (for example targetPkg already has permission to access the URI).
4482 */
4483 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4484 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4486 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4487 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004488 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 }
4490
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004491 if (targetPkg != null) {
4492 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4493 "Checking grant " + targetPkg + " permission to " + uri);
4494 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004495
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004496 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497
4498 // If this is not a content: uri, we can't do anything with it.
4499 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004500 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004501 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004502 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 }
4504
4505 String name = uri.getAuthority();
4506 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004507 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 if (cpr != null) {
4509 pi = cpr.info;
4510 } else {
4511 try {
4512 pi = pm.resolveContentProvider(name,
4513 PackageManager.GET_URI_PERMISSION_PATTERNS);
4514 } catch (RemoteException ex) {
4515 }
4516 }
4517 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004518 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004519 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004520 }
4521
4522 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004523 if (targetPkg != null) {
4524 try {
4525 targetUid = pm.getPackageUid(targetPkg);
4526 if (targetUid < 0) {
4527 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4528 "Can't grant URI permission no uid for: " + targetPkg);
4529 return -1;
4530 }
4531 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004532 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004533 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004534 } else {
4535 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 }
4537
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004538 if (targetUid >= 0) {
4539 // First... does the target actually need this permission?
4540 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4541 // No need to grant the target this permission.
4542 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4543 "Target " + targetPkg + " already has full permission to " + uri);
4544 return -1;
4545 }
4546 } else {
4547 // First... there is no target package, so can anyone access it?
4548 boolean allowed = pi.exported;
4549 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4550 if (pi.readPermission != null) {
4551 allowed = false;
4552 }
4553 }
4554 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4555 if (pi.writePermission != null) {
4556 allowed = false;
4557 }
4558 }
4559 if (allowed) {
4560 return -1;
4561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004562 }
4563
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004564 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565 if (!pi.grantUriPermissions) {
4566 throw new SecurityException("Provider " + pi.packageName
4567 + "/" + pi.name
4568 + " does not allow granting of Uri permissions (uri "
4569 + uri + ")");
4570 }
4571 if (pi.uriPermissionPatterns != null) {
4572 final int N = pi.uriPermissionPatterns.length;
4573 boolean allowed = false;
4574 for (int i=0; i<N; i++) {
4575 if (pi.uriPermissionPatterns[i] != null
4576 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4577 allowed = true;
4578 break;
4579 }
4580 }
4581 if (!allowed) {
4582 throw new SecurityException("Provider " + pi.packageName
4583 + "/" + pi.name
4584 + " does not allow granting of permission to path of Uri "
4585 + uri);
4586 }
4587 }
4588
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004589 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004590 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004591 if (callingUid != Process.myUid()) {
4592 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4593 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4594 throw new SecurityException("Uid " + callingUid
4595 + " does not have permission to uri " + uri);
4596 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 }
4598 }
4599
Dianne Hackborn39792d22010-08-19 18:01:52 -07004600 return targetUid;
4601 }
4602
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004603 public int checkGrantUriPermission(int callingUid, String targetPkg,
4604 Uri uri, int modeFlags) {
4605 synchronized(this) {
4606 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4607 }
4608 }
4609
Dianne Hackborn39792d22010-08-19 18:01:52 -07004610 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4611 Uri uri, int modeFlags, UriPermissionOwner owner) {
4612 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4613 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4614 if (modeFlags == 0) {
4615 return;
4616 }
4617
4618 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 // to the uri, and the target doesn't. Let's now give this to
4620 // the target.
4621
Joe Onorato8a9b2202010-02-26 18:56:32 -08004622 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004623 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 HashMap<Uri, UriPermission> targetUris
4626 = mGrantedUriPermissions.get(targetUid);
4627 if (targetUris == null) {
4628 targetUris = new HashMap<Uri, UriPermission>();
4629 mGrantedUriPermissions.put(targetUid, targetUris);
4630 }
4631
4632 UriPermission perm = targetUris.get(uri);
4633 if (perm == null) {
4634 perm = new UriPermission(targetUid, uri);
4635 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004636 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004638 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004639 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004641 } else {
4642 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4643 perm.readOwners.add(owner);
4644 owner.addReadPermission(perm);
4645 }
4646 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4647 perm.writeOwners.add(owner);
4648 owner.addWritePermission(perm);
4649 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 }
4651 }
4652
Dianne Hackborn39792d22010-08-19 18:01:52 -07004653 void grantUriPermissionLocked(int callingUid,
4654 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004655 if (targetPkg == null) {
4656 throw new NullPointerException("targetPkg");
4657 }
4658
Dianne Hackborn39792d22010-08-19 18:01:52 -07004659 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4660 if (targetUid < 0) {
4661 return;
4662 }
4663
4664 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4665 }
4666
4667 /**
4668 * Like checkGrantUriPermissionLocked, but takes an Intent.
4669 */
4670 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4671 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004672 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004673 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004674 + " from " + intent + "; flags=0x"
4675 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4676
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004677 if (targetPkg == null) {
4678 throw new NullPointerException("targetPkg");
4679 }
4680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004681 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004682 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004683 }
4684 Uri data = intent.getData();
4685 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004686 return -1;
4687 }
4688 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4689 intent.getFlags());
4690 }
4691
4692 /**
4693 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4694 */
4695 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4696 String targetPkg, Intent intent, UriPermissionOwner owner) {
4697 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4698 intent.getFlags(), owner);
4699 }
4700
4701 void grantUriPermissionFromIntentLocked(int callingUid,
4702 String targetPkg, Intent intent, UriPermissionOwner owner) {
4703 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4704 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004705 return;
4706 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004707
4708 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004709 }
4710
4711 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4712 Uri uri, int modeFlags) {
4713 synchronized(this) {
4714 final ProcessRecord r = getRecordForAppLocked(caller);
4715 if (r == null) {
4716 throw new SecurityException("Unable to find app for caller "
4717 + caller
4718 + " when granting permission to uri " + uri);
4719 }
4720 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004721 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 }
4723 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004724 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004725 }
4726
4727 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4728 null);
4729 }
4730 }
4731
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004732 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004733 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4734 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4735 HashMap<Uri, UriPermission> perms
4736 = mGrantedUriPermissions.get(perm.uid);
4737 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004738 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004739 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 perms.remove(perm.uri);
4741 if (perms.size() == 0) {
4742 mGrantedUriPermissions.remove(perm.uid);
4743 }
4744 }
4745 }
4746 }
4747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004748 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4749 int modeFlags) {
4750 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4751 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4752 if (modeFlags == 0) {
4753 return;
4754 }
4755
Joe Onorato8a9b2202010-02-26 18:56:32 -08004756 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004757 "Revoking all granted permissions to " + uri);
4758
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004759 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004760
4761 final String authority = uri.getAuthority();
4762 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004763 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004764 if (cpr != null) {
4765 pi = cpr.info;
4766 } else {
4767 try {
4768 pi = pm.resolveContentProvider(authority,
4769 PackageManager.GET_URI_PERMISSION_PATTERNS);
4770 } catch (RemoteException ex) {
4771 }
4772 }
4773 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004774 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775 return;
4776 }
4777
4778 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004779 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 // Right now, if you are not the original owner of the permission,
4781 // you are not allowed to revoke it.
4782 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4783 throw new SecurityException("Uid " + callingUid
4784 + " does not have permission to uri " + uri);
4785 //}
4786 }
4787
4788 // Go through all of the permissions and remove any that match.
4789 final List<String> SEGMENTS = uri.getPathSegments();
4790 if (SEGMENTS != null) {
4791 final int NS = SEGMENTS.size();
4792 int N = mGrantedUriPermissions.size();
4793 for (int i=0; i<N; i++) {
4794 HashMap<Uri, UriPermission> perms
4795 = mGrantedUriPermissions.valueAt(i);
4796 Iterator<UriPermission> it = perms.values().iterator();
4797 toploop:
4798 while (it.hasNext()) {
4799 UriPermission perm = it.next();
4800 Uri targetUri = perm.uri;
4801 if (!authority.equals(targetUri.getAuthority())) {
4802 continue;
4803 }
4804 List<String> targetSegments = targetUri.getPathSegments();
4805 if (targetSegments == null) {
4806 continue;
4807 }
4808 if (targetSegments.size() < NS) {
4809 continue;
4810 }
4811 for (int j=0; j<NS; j++) {
4812 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4813 continue toploop;
4814 }
4815 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004816 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004817 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004818 perm.clearModes(modeFlags);
4819 if (perm.modeFlags == 0) {
4820 it.remove();
4821 }
4822 }
4823 if (perms.size() == 0) {
4824 mGrantedUriPermissions.remove(
4825 mGrantedUriPermissions.keyAt(i));
4826 N--;
4827 i--;
4828 }
4829 }
4830 }
4831 }
4832
4833 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4834 int modeFlags) {
4835 synchronized(this) {
4836 final ProcessRecord r = getRecordForAppLocked(caller);
4837 if (r == null) {
4838 throw new SecurityException("Unable to find app for caller "
4839 + caller
4840 + " when revoking permission to uri " + uri);
4841 }
4842 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004843 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004844 return;
4845 }
4846
4847 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4848 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4849 if (modeFlags == 0) {
4850 return;
4851 }
4852
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004853 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004854
4855 final String authority = uri.getAuthority();
4856 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004857 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 if (cpr != null) {
4859 pi = cpr.info;
4860 } else {
4861 try {
4862 pi = pm.resolveContentProvider(authority,
4863 PackageManager.GET_URI_PERMISSION_PATTERNS);
4864 } catch (RemoteException ex) {
4865 }
4866 }
4867 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004868 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004869 return;
4870 }
4871
4872 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4873 }
4874 }
4875
Dianne Hackborn7e269642010-08-25 19:50:20 -07004876 @Override
4877 public IBinder newUriPermissionOwner(String name) {
4878 synchronized(this) {
4879 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4880 return owner.getExternalTokenLocked();
4881 }
4882 }
4883
4884 @Override
4885 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4886 Uri uri, int modeFlags) {
4887 synchronized(this) {
4888 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4889 if (owner == null) {
4890 throw new IllegalArgumentException("Unknown owner: " + token);
4891 }
4892 if (fromUid != Binder.getCallingUid()) {
4893 if (Binder.getCallingUid() != Process.myUid()) {
4894 // Only system code can grant URI permissions on behalf
4895 // of other users.
4896 throw new SecurityException("nice try");
4897 }
4898 }
4899 if (targetPkg == null) {
4900 throw new IllegalArgumentException("null target");
4901 }
4902 if (uri == null) {
4903 throw new IllegalArgumentException("null uri");
4904 }
4905
4906 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4907 }
4908 }
4909
4910 @Override
4911 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4912 synchronized(this) {
4913 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4914 if (owner == null) {
4915 throw new IllegalArgumentException("Unknown owner: " + token);
4916 }
4917
4918 if (uri == null) {
4919 owner.removeUriPermissionsLocked(mode);
4920 } else {
4921 owner.removeUriPermissionLocked(uri, mode);
4922 }
4923 }
4924 }
4925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004926 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4927 synchronized (this) {
4928 ProcessRecord app =
4929 who != null ? getRecordForAppLocked(who) : null;
4930 if (app == null) return;
4931
4932 Message msg = Message.obtain();
4933 msg.what = WAIT_FOR_DEBUGGER_MSG;
4934 msg.obj = app;
4935 msg.arg1 = waiting ? 1 : 0;
4936 mHandler.sendMessage(msg);
4937 }
4938 }
4939
4940 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4941 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004942 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004943 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004944 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 }
4946
4947 // =========================================================
4948 // TASK MANAGEMENT
4949 // =========================================================
4950
4951 public List getTasks(int maxNum, int flags,
4952 IThumbnailReceiver receiver) {
4953 ArrayList list = new ArrayList();
4954
4955 PendingThumbnailsRecord pending = null;
4956 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004957 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004958
4959 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004960 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4962 + ", receiver=" + receiver);
4963
4964 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4965 != PackageManager.PERMISSION_GRANTED) {
4966 if (receiver != null) {
4967 // If the caller wants to wait for pending thumbnails,
4968 // it ain't gonna get them.
4969 try {
4970 receiver.finished();
4971 } catch (RemoteException ex) {
4972 }
4973 }
4974 String msg = "Permission Denial: getTasks() from pid="
4975 + Binder.getCallingPid()
4976 + ", uid=" + Binder.getCallingUid()
4977 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004978 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004979 throw new SecurityException(msg);
4980 }
4981
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004982 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004983 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004984 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004985 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 TaskRecord curTask = null;
4987 int numActivities = 0;
4988 int numRunning = 0;
4989 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004990 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004991 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004992 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993
4994 // Initialize state for next task if needed.
4995 if (top == null ||
4996 (top.state == ActivityState.INITIALIZING
4997 && top.task == r.task)) {
4998 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 curTask = r.task;
5000 numActivities = numRunning = 0;
5001 }
5002
5003 // Add 'r' into the current task.
5004 numActivities++;
5005 if (r.app != null && r.app.thread != null) {
5006 numRunning++;
5007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008
Joe Onorato8a9b2202010-02-26 18:56:32 -08005009 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005010 TAG, r.intent.getComponent().flattenToShortString()
5011 + ": task=" + r.task);
5012
5013 // If the next one is a different task, generate a new
5014 // TaskInfo entry for what we have.
5015 if (next == null || next.task != curTask) {
5016 ActivityManager.RunningTaskInfo ci
5017 = new ActivityManager.RunningTaskInfo();
5018 ci.id = curTask.taskId;
5019 ci.baseActivity = r.intent.getComponent();
5020 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005021 if (top.thumbHolder != null) {
5022 ci.description = top.thumbHolder.lastDescription;
5023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005024 ci.numActivities = numActivities;
5025 ci.numRunning = numRunning;
5026 //System.out.println(
5027 // "#" + maxNum + ": " + " descr=" + ci.description);
5028 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005029 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 TAG, "State=" + top.state + "Idle=" + top.idle
5031 + " app=" + top.app
5032 + " thr=" + (top.app != null ? top.app.thread : null));
5033 if (top.state == ActivityState.RESUMED
5034 || top.state == ActivityState.PAUSING) {
5035 if (top.idle && top.app != null
5036 && top.app.thread != null) {
5037 topRecord = top;
5038 topThumbnail = top.app.thread;
5039 } else {
5040 top.thumbnailNeeded = true;
5041 }
5042 }
5043 if (pending == null) {
5044 pending = new PendingThumbnailsRecord(receiver);
5045 }
5046 pending.pendingRecords.add(top);
5047 }
5048 list.add(ci);
5049 maxNum--;
5050 top = null;
5051 }
5052 }
5053
5054 if (pending != null) {
5055 mPendingThumbnails.add(pending);
5056 }
5057 }
5058
Joe Onorato8a9b2202010-02-26 18:56:32 -08005059 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005060
5061 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005062 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 try {
5064 topThumbnail.requestThumbnail(topRecord);
5065 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005066 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005067 sendPendingThumbnail(null, topRecord, null, null, true);
5068 }
5069 }
5070
5071 if (pending == null && receiver != null) {
5072 // In this case all thumbnails were available and the client
5073 // is being asked to be told when the remaining ones come in...
5074 // which is unusually, since the top-most currently running
5075 // activity should never have a canned thumbnail! Oh well.
5076 try {
5077 receiver.finished();
5078 } catch (RemoteException ex) {
5079 }
5080 }
5081
5082 return list;
5083 }
5084
5085 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5086 int flags) {
5087 synchronized (this) {
5088 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5089 "getRecentTasks()");
5090
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005091 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 final int N = mRecentTasks.size();
5094 ArrayList<ActivityManager.RecentTaskInfo> res
5095 = new ArrayList<ActivityManager.RecentTaskInfo>(
5096 maxNum < N ? maxNum : N);
5097 for (int i=0; i<N && maxNum > 0; i++) {
5098 TaskRecord tr = mRecentTasks.get(i);
5099 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
5100 || (tr.intent == null)
5101 || ((tr.intent.getFlags()
5102 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5103 ActivityManager.RecentTaskInfo rti
5104 = new ActivityManager.RecentTaskInfo();
5105 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005106 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005107 rti.baseIntent = new Intent(
5108 tr.intent != null ? tr.intent : tr.affinityIntent);
5109 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005110 rti.description = tr.lastDescription;
5111
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005112 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5113 // Check whether this activity is currently available.
5114 try {
5115 if (rti.origActivity != null) {
5116 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5117 continue;
5118 }
5119 } else if (rti.baseIntent != null) {
5120 if (pm.queryIntentActivities(rti.baseIntent,
5121 null, 0) == null) {
5122 continue;
5123 }
5124 }
5125 } catch (RemoteException e) {
5126 // Will never happen.
5127 }
5128 }
5129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 res.add(rti);
5131 maxNum--;
5132 }
5133 }
5134 return res;
5135 }
5136 }
5137
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005138 private TaskRecord taskForIdLocked(int id) {
5139 final int N = mRecentTasks.size();
5140 for (int i=0; i<N; i++) {
5141 TaskRecord tr = mRecentTasks.get(i);
5142 if (tr.taskId == id) {
5143 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005144 }
5145 }
5146 return null;
5147 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005148
5149 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5150 synchronized (this) {
5151 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5152 "getTaskThumbnails()");
5153 TaskRecord tr = taskForIdLocked(id);
5154 if (tr != null) {
5155 return mMainStack.getTaskThumbnailsLocked(tr);
5156 }
5157 }
5158 return null;
5159 }
5160
5161 public boolean removeSubTask(int taskId, int subTaskIndex) {
5162 synchronized (this) {
5163 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5164 "removeSubTask()");
5165 long ident = Binder.clearCallingIdentity();
5166 try {
5167 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5168 } finally {
5169 Binder.restoreCallingIdentity(ident);
5170 }
5171 }
5172 }
5173
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005174 private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005175 TaskRecord tr = root.task;
5176 Intent baseIntent = new Intent(
5177 tr.intent != null ? tr.intent : tr.affinityIntent);
5178 ComponentName component = baseIntent.getComponent();
5179 if (component == null) {
5180 Slog.w(TAG, "Now component for base intent of task: " + tr);
5181 return;
5182 }
5183
5184 // Find any running services associated with this app.
5185 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5186 for (ServiceRecord sr : mServices.values()) {
5187 if (sr.packageName.equals(component.getPackageName())) {
5188 services.add(sr);
5189 }
5190 }
5191
5192 // Take care of any running services associated with the app.
5193 for (int i=0; i<services.size(); i++) {
5194 ServiceRecord sr = services.get(i);
5195 if (sr.startRequested) {
5196 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005197 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005198 stopServiceLocked(sr);
5199 } else {
5200 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5201 sr.makeNextStartId(), baseIntent, -1));
5202 if (sr.app != null && sr.app.thread != null) {
5203 sendServiceArgsLocked(sr, false);
5204 }
5205 }
5206 }
5207 }
5208
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005209 if (killProcesses) {
5210 // Find any running processes associated with this app.
5211 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5212 SparseArray<ProcessRecord> appProcs
5213 = mProcessNames.getMap().get(component.getPackageName());
5214 if (appProcs != null) {
5215 for (int i=0; i<appProcs.size(); i++) {
5216 procs.add(appProcs.valueAt(i));
5217 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005218 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005219
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005220 // Kill the running processes.
5221 for (int i=0; i<procs.size(); i++) {
5222 ProcessRecord pr = procs.get(i);
5223 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5224 Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
5225 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5226 pr.processName, pr.setAdj, "remove task");
5227 Process.killProcessQuiet(pr.pid);
5228 } else {
5229 pr.waitingToKill = "remove task";
5230 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005231 }
5232 }
5233 }
5234
5235 public boolean removeTask(int taskId, int flags) {
5236 synchronized (this) {
5237 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5238 "removeTask()");
5239 long ident = Binder.clearCallingIdentity();
5240 try {
5241 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5242 if (r != null) {
5243 mRecentTasks.remove(r.task);
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005244 cleanUpRemovedTaskLocked(r,
5245 (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005246 return true;
5247 }
5248 } finally {
5249 Binder.restoreCallingIdentity(ident);
5250 }
5251 }
5252 return false;
5253 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5256 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005257 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005258 TaskRecord jt = startTask;
5259
5260 // First look backwards
5261 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005262 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 if (r.task != jt) {
5264 jt = r.task;
5265 if (affinity.equals(jt.affinity)) {
5266 return j;
5267 }
5268 }
5269 }
5270
5271 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005272 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005273 jt = startTask;
5274 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005275 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 if (r.task != jt) {
5277 if (affinity.equals(jt.affinity)) {
5278 return j;
5279 }
5280 jt = r.task;
5281 }
5282 }
5283
5284 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005285 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005286 return N-1;
5287 }
5288
5289 return -1;
5290 }
5291
5292 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005293 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005295 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5297 "moveTaskToFront()");
5298
5299 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005300 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5301 Binder.getCallingUid(), "Task to front")) {
5302 return;
5303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 final long origId = Binder.clearCallingIdentity();
5305 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005306 TaskRecord tr = taskForIdLocked(task);
5307 if (tr != null) {
5308 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5309 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005311 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5312 // Caller wants the home activity moved with it. To accomplish this,
5313 // we'll just move the home task to the top first.
5314 mMainStack.moveHomeToFrontLocked();
5315 }
5316 mMainStack.moveTaskToFrontLocked(tr, null);
5317 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005318 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005319 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5320 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005322 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5323 mMainStack.mUserLeaving = true;
5324 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005325 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5326 // Caller wants the home activity moved with it. To accomplish this,
5327 // we'll just move the home task to the top first.
5328 mMainStack.moveHomeToFrontLocked();
5329 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005330 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 return;
5332 }
5333 }
5334 } finally {
5335 Binder.restoreCallingIdentity(origId);
5336 }
5337 }
5338 }
5339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005340 public void moveTaskToBack(int task) {
5341 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5342 "moveTaskToBack()");
5343
5344 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005345 if (mMainStack.mResumedActivity != null
5346 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005347 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5348 Binder.getCallingUid(), "Task to back")) {
5349 return;
5350 }
5351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005352 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005353 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 Binder.restoreCallingIdentity(origId);
5355 }
5356 }
5357
5358 /**
5359 * Moves an activity, and all of the other activities within the same task, to the bottom
5360 * of the history stack. The activity's order within the task is unchanged.
5361 *
5362 * @param token A reference to the activity we wish to move
5363 * @param nonRoot If false then this only works if the activity is the root
5364 * of a task; if true it will work for any activity in a task.
5365 * @return Returns true if the move completed, false if not.
5366 */
5367 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5368 synchronized(this) {
5369 final long origId = Binder.clearCallingIdentity();
5370 int taskId = getTaskForActivityLocked(token, !nonRoot);
5371 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005372 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005373 }
5374 Binder.restoreCallingIdentity(origId);
5375 }
5376 return false;
5377 }
5378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 public void moveTaskBackwards(int task) {
5380 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5381 "moveTaskBackwards()");
5382
5383 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005384 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5385 Binder.getCallingUid(), "Task backwards")) {
5386 return;
5387 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 final long origId = Binder.clearCallingIdentity();
5389 moveTaskBackwardsLocked(task);
5390 Binder.restoreCallingIdentity(origId);
5391 }
5392 }
5393
5394 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005395 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 }
5397
5398 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5399 synchronized(this) {
5400 return getTaskForActivityLocked(token, onlyRoot);
5401 }
5402 }
5403
5404 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005405 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005406 TaskRecord lastTask = null;
5407 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005408 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005409 if (r == token) {
5410 if (!onlyRoot || lastTask != r.task) {
5411 return r.task.taskId;
5412 }
5413 return -1;
5414 }
5415 lastTask = r.task;
5416 }
5417
5418 return -1;
5419 }
5420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005421 public void finishOtherInstances(IBinder token, ComponentName className) {
5422 synchronized(this) {
5423 final long origId = Binder.clearCallingIdentity();
5424
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005425 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005426 TaskRecord lastTask = null;
5427 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005428 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 if (r.realActivity.equals(className)
5430 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005431 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005432 null, "others")) {
5433 i--;
5434 N--;
5435 }
5436 }
5437 lastTask = r.task;
5438 }
5439
5440 Binder.restoreCallingIdentity(origId);
5441 }
5442 }
5443
5444 // =========================================================
5445 // THUMBNAILS
5446 // =========================================================
5447
5448 public void reportThumbnail(IBinder token,
5449 Bitmap thumbnail, CharSequence description) {
5450 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5451 final long origId = Binder.clearCallingIdentity();
5452 sendPendingThumbnail(null, token, thumbnail, description, true);
5453 Binder.restoreCallingIdentity(origId);
5454 }
5455
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005456 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005457 Bitmap thumbnail, CharSequence description, boolean always) {
5458 TaskRecord task = null;
5459 ArrayList receivers = null;
5460
5461 //System.out.println("Send pending thumbnail: " + r);
5462
5463 synchronized(this) {
5464 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005465 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005466 if (index < 0) {
5467 return;
5468 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005469 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005470 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005471 if (thumbnail == null && r.thumbHolder != null) {
5472 thumbnail = r.thumbHolder.lastThumbnail;
5473 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 }
5475 if (thumbnail == null && !always) {
5476 // If there is no thumbnail, and this entry is not actually
5477 // going away, then abort for now and pick up the next
5478 // thumbnail we get.
5479 return;
5480 }
5481 task = r.task;
5482
5483 int N = mPendingThumbnails.size();
5484 int i=0;
5485 while (i<N) {
5486 PendingThumbnailsRecord pr =
5487 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5488 //System.out.println("Looking in " + pr.pendingRecords);
5489 if (pr.pendingRecords.remove(r)) {
5490 if (receivers == null) {
5491 receivers = new ArrayList();
5492 }
5493 receivers.add(pr);
5494 if (pr.pendingRecords.size() == 0) {
5495 pr.finished = true;
5496 mPendingThumbnails.remove(i);
5497 N--;
5498 continue;
5499 }
5500 }
5501 i++;
5502 }
5503 }
5504
5505 if (receivers != null) {
5506 final int N = receivers.size();
5507 for (int i=0; i<N; i++) {
5508 try {
5509 PendingThumbnailsRecord pr =
5510 (PendingThumbnailsRecord)receivers.get(i);
5511 pr.receiver.newThumbnail(
5512 task != null ? task.taskId : -1, thumbnail, description);
5513 if (pr.finished) {
5514 pr.receiver.finished();
5515 }
5516 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005517 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005518 }
5519 }
5520 }
5521 }
5522
5523 // =========================================================
5524 // CONTENT PROVIDERS
5525 // =========================================================
5526
5527 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5528 List providers = null;
5529 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005530 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005531 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005532 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005533 } catch (RemoteException ex) {
5534 }
5535 if (providers != null) {
5536 final int N = providers.size();
5537 for (int i=0; i<N; i++) {
5538 ProviderInfo cpi =
5539 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005540 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005541 if (cpr == null) {
5542 cpr = new ContentProviderRecord(cpi, app.info);
5543 mProvidersByClass.put(cpi.name, cpr);
5544 }
5545 app.pubProviders.put(cpi.name, cpr);
5546 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005547 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005548 }
5549 }
5550 return providers;
5551 }
5552
5553 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005554 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005555 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5556 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5557 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005558 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005559 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005560 return null;
5561 }
5562 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005563 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005564 == PackageManager.PERMISSION_GRANTED) {
5565 return null;
5566 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005567
5568 PathPermission[] pps = cpi.pathPermissions;
5569 if (pps != null) {
5570 int i = pps.length;
5571 while (i > 0) {
5572 i--;
5573 PathPermission pp = pps[i];
5574 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005575 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005576 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005577 return null;
5578 }
5579 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005580 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005581 == PackageManager.PERMISSION_GRANTED) {
5582 return null;
5583 }
5584 }
5585 }
5586
Dianne Hackbornb424b632010-08-18 15:59:05 -07005587 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5588 if (perms != null) {
5589 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5590 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5591 return null;
5592 }
5593 }
5594 }
5595
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005596 String msg;
5597 if (!cpi.exported) {
5598 msg = "Permission Denial: opening provider " + cpi.name
5599 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5600 + ", uid=" + callingUid + ") that is not exported from uid "
5601 + cpi.applicationInfo.uid;
5602 } else {
5603 msg = "Permission Denial: opening provider " + cpi.name
5604 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5605 + ", uid=" + callingUid + ") requires "
5606 + cpi.readPermission + " or " + cpi.writePermission;
5607 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005608 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005609 return msg;
5610 }
5611
5612 private final ContentProviderHolder getContentProviderImpl(
5613 IApplicationThread caller, String name) {
5614 ContentProviderRecord cpr;
5615 ProviderInfo cpi = null;
5616
5617 synchronized(this) {
5618 ProcessRecord r = null;
5619 if (caller != null) {
5620 r = getRecordForAppLocked(caller);
5621 if (r == null) {
5622 throw new SecurityException(
5623 "Unable to find app for caller " + caller
5624 + " (pid=" + Binder.getCallingPid()
5625 + ") when getting content provider " + name);
5626 }
5627 }
5628
5629 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005630 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 if (cpr != null) {
5632 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005633 String msg;
5634 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5635 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636 }
5637
5638 if (r != null && cpr.canRunHere(r)) {
5639 // This provider has been published or is in the process
5640 // of being published... but it is also allowed to run
5641 // in the caller's process, so don't make a connection
5642 // and just let the caller instantiate its own instance.
5643 if (cpr.provider != null) {
5644 // don't give caller the provider object, it needs
5645 // to make its own.
5646 cpr = new ContentProviderRecord(cpr);
5647 }
5648 return cpr;
5649 }
5650
5651 final long origId = Binder.clearCallingIdentity();
5652
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005653 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005654 // return it right away.
5655 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005656 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005657 "Adding provider requested by "
5658 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005659 + cpr.info.processName);
5660 Integer cnt = r.conProviders.get(cpr);
5661 if (cnt == null) {
5662 r.conProviders.put(cpr, new Integer(1));
5663 } else {
5664 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005667 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5668 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005669 // make sure to count it as being accessed and thus
5670 // back up on the LRU list. This is good because
5671 // content providers are often expensive to start.
5672 updateLruProcessLocked(cpr.app, false, true);
5673 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005674 } else {
5675 cpr.externals++;
5676 }
5677
5678 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 updateOomAdjLocked(cpr.app);
5680 }
5681
5682 Binder.restoreCallingIdentity(origId);
5683
5684 } else {
5685 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005686 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005687 resolveContentProvider(name,
5688 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005689 } catch (RemoteException ex) {
5690 }
5691 if (cpi == null) {
5692 return null;
5693 }
5694
Dianne Hackbornb424b632010-08-18 15:59:05 -07005695 String msg;
5696 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5697 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005698 }
5699
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005700 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005701 && !cpi.processName.equals("system")) {
5702 // If this content provider does not run in the system
5703 // process, and the system is not yet ready to run other
5704 // processes, then fail fast instead of hanging.
5705 throw new IllegalArgumentException(
5706 "Attempt to launch content provider before system ready");
5707 }
5708
Dianne Hackborn860755f2010-06-03 18:47:52 -07005709 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005710 final boolean firstClass = cpr == null;
5711 if (firstClass) {
5712 try {
5713 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005714 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005715 getApplicationInfo(
5716 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005717 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005718 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005719 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 + cpi.name);
5721 return null;
5722 }
5723 cpr = new ContentProviderRecord(cpi, ai);
5724 } catch (RemoteException ex) {
5725 // pm is in same process, this will never happen.
5726 }
5727 }
5728
5729 if (r != null && cpr.canRunHere(r)) {
5730 // If this is a multiprocess provider, then just return its
5731 // info and allow the caller to instantiate it. Only do
5732 // this if the provider is the same user as the caller's
5733 // process, or can run as root (so can be in any process).
5734 return cpr;
5735 }
5736
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005737 if (DEBUG_PROVIDER) {
5738 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005739 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005740 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005741 }
5742
5743 // This is single process, and our app is now connecting to it.
5744 // See if we are already in the process of launching this
5745 // provider.
5746 final int N = mLaunchingProviders.size();
5747 int i;
5748 for (i=0; i<N; i++) {
5749 if (mLaunchingProviders.get(i) == cpr) {
5750 break;
5751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005752 }
5753
5754 // If the provider is not already being launched, then get it
5755 // started.
5756 if (i >= N) {
5757 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005758
5759 try {
5760 // Content provider is now in use, its package can't be stopped.
5761 try {
5762 AppGlobals.getPackageManager().setPackageStoppedState(
5763 cpr.appInfo.packageName, false);
5764 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005765 } catch (IllegalArgumentException e) {
5766 Slog.w(TAG, "Failed trying to unstop package "
5767 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005768 }
5769
5770 ProcessRecord proc = startProcessLocked(cpi.processName,
5771 cpr.appInfo, false, 0, "content provider",
5772 new ComponentName(cpi.applicationInfo.packageName,
5773 cpi.name), false);
5774 if (proc == null) {
5775 Slog.w(TAG, "Unable to launch app "
5776 + cpi.applicationInfo.packageName + "/"
5777 + cpi.applicationInfo.uid + " for provider "
5778 + name + ": process is bad");
5779 return null;
5780 }
5781 cpr.launchingApp = proc;
5782 mLaunchingProviders.add(cpr);
5783 } finally {
5784 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005785 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 }
5787
5788 // Make sure the provider is published (the same provider class
5789 // may be published under multiple names).
5790 if (firstClass) {
5791 mProvidersByClass.put(cpi.name, cpr);
5792 }
5793 mProvidersByName.put(name, cpr);
5794
5795 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005796 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005797 "Adding provider requested by "
5798 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005799 + cpr.info.processName);
5800 Integer cnt = r.conProviders.get(cpr);
5801 if (cnt == null) {
5802 r.conProviders.put(cpr, new Integer(1));
5803 } else {
5804 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 cpr.clients.add(r);
5807 } else {
5808 cpr.externals++;
5809 }
5810 }
5811 }
5812
5813 // Wait for the provider to be published...
5814 synchronized (cpr) {
5815 while (cpr.provider == null) {
5816 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005817 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818 + cpi.applicationInfo.packageName + "/"
5819 + cpi.applicationInfo.uid + " for provider "
5820 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005821 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005822 cpi.applicationInfo.packageName,
5823 cpi.applicationInfo.uid, name);
5824 return null;
5825 }
5826 try {
5827 cpr.wait();
5828 } catch (InterruptedException ex) {
5829 }
5830 }
5831 }
5832 return cpr;
5833 }
5834
5835 public final ContentProviderHolder getContentProvider(
5836 IApplicationThread caller, String name) {
5837 if (caller == null) {
5838 String msg = "null IApplicationThread when getting content provider "
5839 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005840 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005841 throw new SecurityException(msg);
5842 }
5843
5844 return getContentProviderImpl(caller, name);
5845 }
5846
5847 private ContentProviderHolder getContentProviderExternal(String name) {
5848 return getContentProviderImpl(null, name);
5849 }
5850
5851 /**
5852 * Drop a content provider from a ProcessRecord's bookkeeping
5853 * @param cpr
5854 */
5855 public void removeContentProvider(IApplicationThread caller, String name) {
5856 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005857 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005858 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005859 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005860 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005861 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 return;
5863 }
5864 final ProcessRecord r = getRecordForAppLocked(caller);
5865 if (r == null) {
5866 throw new SecurityException(
5867 "Unable to find app for caller " + caller +
5868 " when removing content provider " + name);
5869 }
5870 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005871 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005872 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005873 + r.info.processName + " from process "
5874 + localCpr.appInfo.processName);
5875 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005876 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005877 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005878 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 return;
5880 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005881 Integer cnt = r.conProviders.get(localCpr);
5882 if (cnt == null || cnt.intValue() <= 1) {
5883 localCpr.clients.remove(r);
5884 r.conProviders.remove(localCpr);
5885 } else {
5886 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005888 }
5889 updateOomAdjLocked();
5890 }
5891 }
5892
5893 private void removeContentProviderExternal(String name) {
5894 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005895 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005896 if(cpr == null) {
5897 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005898 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005899 return;
5900 }
5901
5902 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005903 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 localCpr.externals--;
5905 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005906 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 }
5908 updateOomAdjLocked();
5909 }
5910 }
5911
5912 public final void publishContentProviders(IApplicationThread caller,
5913 List<ContentProviderHolder> providers) {
5914 if (providers == null) {
5915 return;
5916 }
5917
5918 synchronized(this) {
5919 final ProcessRecord r = getRecordForAppLocked(caller);
5920 if (r == null) {
5921 throw new SecurityException(
5922 "Unable to find app for caller " + caller
5923 + " (pid=" + Binder.getCallingPid()
5924 + ") when publishing content providers");
5925 }
5926
5927 final long origId = Binder.clearCallingIdentity();
5928
5929 final int N = providers.size();
5930 for (int i=0; i<N; i++) {
5931 ContentProviderHolder src = providers.get(i);
5932 if (src == null || src.info == null || src.provider == null) {
5933 continue;
5934 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005935 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005936 if (dst != null) {
5937 mProvidersByClass.put(dst.info.name, dst);
5938 String names[] = dst.info.authority.split(";");
5939 for (int j = 0; j < names.length; j++) {
5940 mProvidersByName.put(names[j], dst);
5941 }
5942
5943 int NL = mLaunchingProviders.size();
5944 int j;
5945 for (j=0; j<NL; j++) {
5946 if (mLaunchingProviders.get(j) == dst) {
5947 mLaunchingProviders.remove(j);
5948 j--;
5949 NL--;
5950 }
5951 }
5952 synchronized (dst) {
5953 dst.provider = src.provider;
5954 dst.app = r;
5955 dst.notifyAll();
5956 }
5957 updateOomAdjLocked(r);
5958 }
5959 }
5960
5961 Binder.restoreCallingIdentity(origId);
5962 }
5963 }
5964
5965 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005966 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005967 synchronized (mSelf) {
5968 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5969 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005970 if (providers != null) {
5971 for (int i=providers.size()-1; i>=0; i--) {
5972 ProviderInfo pi = (ProviderInfo)providers.get(i);
5973 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5974 Slog.w(TAG, "Not installing system proc provider " + pi.name
5975 + ": not system .apk");
5976 providers.remove(i);
5977 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005978 }
5979 }
5980 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005981 if (providers != null) {
5982 mSystemThread.installSystemProviders(providers);
5983 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005984
5985 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005986 }
5987
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005988 /**
5989 * Allows app to retrieve the MIME type of a URI without having permission
5990 * to access its content provider.
5991 *
5992 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5993 *
5994 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5995 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5996 */
5997 public String getProviderMimeType(Uri uri) {
5998 final String name = uri.getAuthority();
5999 final long ident = Binder.clearCallingIdentity();
6000 ContentProviderHolder holder = null;
6001
6002 try {
6003 holder = getContentProviderExternal(name);
6004 if (holder != null) {
6005 return holder.provider.getType(uri);
6006 }
6007 } catch (RemoteException e) {
6008 Log.w(TAG, "Content provider dead retrieving " + uri, e);
6009 return null;
6010 } finally {
6011 if (holder != null) {
6012 removeContentProviderExternal(name);
6013 }
6014 Binder.restoreCallingIdentity(ident);
6015 }
6016
6017 return null;
6018 }
6019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 // =========================================================
6021 // GLOBAL MANAGEMENT
6022 // =========================================================
6023
6024 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
6025 ApplicationInfo info, String customProcess) {
6026 String proc = customProcess != null ? customProcess : info.processName;
6027 BatteryStatsImpl.Uid.Proc ps = null;
6028 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6029 synchronized (stats) {
6030 ps = stats.getProcessStatsLocked(info.uid, proc);
6031 }
6032 return new ProcessRecord(ps, thread, info, proc);
6033 }
6034
6035 final ProcessRecord addAppLocked(ApplicationInfo info) {
6036 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
6037
6038 if (app == null) {
6039 app = newProcessRecordLocked(null, info, null);
6040 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006041 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 }
6043
Dianne Hackborne7f97212011-02-24 14:40:20 -08006044 // This package really, really can not be stopped.
6045 try {
6046 AppGlobals.getPackageManager().setPackageStoppedState(
6047 info.packageName, false);
6048 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006049 } catch (IllegalArgumentException e) {
6050 Slog.w(TAG, "Failed trying to unstop package "
6051 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006052 }
6053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006054 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6055 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6056 app.persistent = true;
6057 app.maxAdj = CORE_SERVER_ADJ;
6058 }
6059 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6060 mPersistentStartingProcesses.add(app);
6061 startProcessLocked(app, "added application", app.processName);
6062 }
6063
6064 return app;
6065 }
6066
6067 public void unhandledBack() {
6068 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6069 "unhandledBack()");
6070
6071 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006072 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006073 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006074 TAG, "Performing unhandledBack(): stack size = " + count);
6075 if (count > 1) {
6076 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006077 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006078 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6079 Binder.restoreCallingIdentity(origId);
6080 }
6081 }
6082 }
6083
6084 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6085 String name = uri.getAuthority();
6086 ContentProviderHolder cph = getContentProviderExternal(name);
6087 ParcelFileDescriptor pfd = null;
6088 if (cph != null) {
6089 // We record the binder invoker's uid in thread-local storage before
6090 // going to the content provider to open the file. Later, in the code
6091 // that handles all permissions checks, we look for this uid and use
6092 // that rather than the Activity Manager's own uid. The effect is that
6093 // we do the check against the caller's permissions even though it looks
6094 // to the content provider like the Activity Manager itself is making
6095 // the request.
6096 sCallerIdentity.set(new Identity(
6097 Binder.getCallingPid(), Binder.getCallingUid()));
6098 try {
6099 pfd = cph.provider.openFile(uri, "r");
6100 } catch (FileNotFoundException e) {
6101 // do nothing; pfd will be returned null
6102 } finally {
6103 // Ensure that whatever happens, we clean up the identity state
6104 sCallerIdentity.remove();
6105 }
6106
6107 // We've got the fd now, so we're done with the provider.
6108 removeContentProviderExternal(name);
6109 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006110 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006111 }
6112 return pfd;
6113 }
6114
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006115 // Actually is sleeping or shutting down or whatever else in the future
6116 // is an inactive state.
6117 public boolean isSleeping() {
6118 return mSleeping || mShuttingDown;
6119 }
6120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006121 public void goingToSleep() {
6122 synchronized(this) {
6123 mSleeping = true;
6124 mWindowManager.setEventDispatching(false);
6125
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006126 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006127
6128 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006129 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006130 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6131 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006132 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006133 }
6134 }
6135
Dianne Hackborn55280a92009-05-07 15:53:46 -07006136 public boolean shutdown(int timeout) {
6137 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6138 != PackageManager.PERMISSION_GRANTED) {
6139 throw new SecurityException("Requires permission "
6140 + android.Manifest.permission.SHUTDOWN);
6141 }
6142
6143 boolean timedout = false;
6144
6145 synchronized(this) {
6146 mShuttingDown = true;
6147 mWindowManager.setEventDispatching(false);
6148
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006149 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006150 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006151 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006152 while (mMainStack.mResumedActivity != null
6153 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006154 long delay = endTime - System.currentTimeMillis();
6155 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006156 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006157 timedout = true;
6158 break;
6159 }
6160 try {
6161 this.wait();
6162 } catch (InterruptedException e) {
6163 }
6164 }
6165 }
6166 }
6167
6168 mUsageStatsService.shutdown();
6169 mBatteryStatsService.shutdown();
6170
6171 return timedout;
6172 }
6173
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006174 public final void activitySlept(IBinder token) {
6175 if (localLOGV) Slog.v(
6176 TAG, "Activity slept: token=" + token);
6177
6178 ActivityRecord r = null;
6179
6180 final long origId = Binder.clearCallingIdentity();
6181
6182 synchronized (this) {
6183 int index = mMainStack.indexOfTokenLocked(token);
6184 if (index >= 0) {
6185 r = (ActivityRecord)mMainStack.mHistory.get(index);
6186 mMainStack.activitySleptLocked(r);
6187 }
6188 }
6189
6190 Binder.restoreCallingIdentity(origId);
6191 }
6192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006193 public void wakingUp() {
6194 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006195 mWindowManager.setEventDispatching(true);
6196 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006197 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006198 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006199 }
6200 }
6201
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006202 public void stopAppSwitches() {
6203 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6204 != PackageManager.PERMISSION_GRANTED) {
6205 throw new SecurityException("Requires permission "
6206 + android.Manifest.permission.STOP_APP_SWITCHES);
6207 }
6208
6209 synchronized(this) {
6210 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6211 + APP_SWITCH_DELAY_TIME;
6212 mDidAppSwitch = false;
6213 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6214 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6215 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6216 }
6217 }
6218
6219 public void resumeAppSwitches() {
6220 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6221 != PackageManager.PERMISSION_GRANTED) {
6222 throw new SecurityException("Requires permission "
6223 + android.Manifest.permission.STOP_APP_SWITCHES);
6224 }
6225
6226 synchronized(this) {
6227 // Note that we don't execute any pending app switches... we will
6228 // let those wait until either the timeout, or the next start
6229 // activity request.
6230 mAppSwitchesAllowedTime = 0;
6231 }
6232 }
6233
6234 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6235 String name) {
6236 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6237 return true;
6238 }
6239
6240 final int perm = checkComponentPermission(
6241 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006242 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006243 if (perm == PackageManager.PERMISSION_GRANTED) {
6244 return true;
6245 }
6246
Joe Onorato8a9b2202010-02-26 18:56:32 -08006247 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006248 return false;
6249 }
6250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006251 public void setDebugApp(String packageName, boolean waitForDebugger,
6252 boolean persistent) {
6253 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6254 "setDebugApp()");
6255
6256 // Note that this is not really thread safe if there are multiple
6257 // callers into it at the same time, but that's not a situation we
6258 // care about.
6259 if (persistent) {
6260 final ContentResolver resolver = mContext.getContentResolver();
6261 Settings.System.putString(
6262 resolver, Settings.System.DEBUG_APP,
6263 packageName);
6264 Settings.System.putInt(
6265 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6266 waitForDebugger ? 1 : 0);
6267 }
6268
6269 synchronized (this) {
6270 if (!persistent) {
6271 mOrigDebugApp = mDebugApp;
6272 mOrigWaitForDebugger = mWaitForDebugger;
6273 }
6274 mDebugApp = packageName;
6275 mWaitForDebugger = waitForDebugger;
6276 mDebugTransient = !persistent;
6277 if (packageName != null) {
6278 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006279 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006280 Binder.restoreCallingIdentity(origId);
6281 }
6282 }
6283 }
6284
6285 public void setAlwaysFinish(boolean enabled) {
6286 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6287 "setAlwaysFinish()");
6288
6289 Settings.System.putInt(
6290 mContext.getContentResolver(),
6291 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6292
6293 synchronized (this) {
6294 mAlwaysFinishActivities = enabled;
6295 }
6296 }
6297
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006298 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006299 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006300 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006301 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006302 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006303 }
6304 }
6305
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006306 public boolean isUserAMonkey() {
6307 // For now the fact that there is a controller implies
6308 // we have a monkey.
6309 synchronized (this) {
6310 return mController != null;
6311 }
6312 }
6313
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006314 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006315 synchronized (this) {
6316 mWatchers.register(watcher);
6317 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006318 }
6319
6320 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006321 synchronized (this) {
6322 mWatchers.unregister(watcher);
6323 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006324 }
6325
Jeff Sharkeya4620792011-05-20 15:29:23 -07006326 public void registerProcessObserver(IProcessObserver observer) {
6327 mProcessObservers.register(observer);
6328 }
6329
6330 public void unregisterProcessObserver(IProcessObserver observer) {
6331 mProcessObservers.unregister(observer);
6332 }
6333
Daniel Sandler69a48172010-06-23 16:29:36 -04006334 public void setImmersive(IBinder token, boolean immersive) {
6335 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006336 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006337 if (index < 0) {
6338 throw new IllegalArgumentException();
6339 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006340 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006341 r.immersive = immersive;
6342 }
6343 }
6344
6345 public boolean isImmersive(IBinder token) {
6346 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006347 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006348 if (index < 0) {
6349 throw new IllegalArgumentException();
6350 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006351 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006352 return r.immersive;
6353 }
6354 }
6355
6356 public boolean isTopActivityImmersive() {
6357 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006358 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006359 return (r != null) ? r.immersive : false;
6360 }
6361 }
6362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 public final void enterSafeMode() {
6364 synchronized(this) {
6365 // It only makes sense to do this before the system is ready
6366 // and started launching other packages.
6367 if (!mSystemReady) {
6368 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006369 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006370 } catch (RemoteException e) {
6371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 }
6373 }
6374 }
6375
Jeff Brownb09abc12011-01-13 21:08:27 -08006376 public final void showSafeModeOverlay() {
6377 View v = LayoutInflater.from(mContext).inflate(
6378 com.android.internal.R.layout.safe_mode, null);
6379 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6380 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6381 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6382 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6383 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6384 lp.format = v.getBackground().getOpacity();
6385 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6386 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6387 ((WindowManager)mContext.getSystemService(
6388 Context.WINDOW_SERVICE)).addView(v, lp);
6389 }
6390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006391 public void noteWakeupAlarm(IIntentSender sender) {
6392 if (!(sender instanceof PendingIntentRecord)) {
6393 return;
6394 }
6395 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6396 synchronized (stats) {
6397 if (mBatteryStatsService.isOnBattery()) {
6398 mBatteryStatsService.enforceCallingPermission();
6399 PendingIntentRecord rec = (PendingIntentRecord)sender;
6400 int MY_UID = Binder.getCallingUid();
6401 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6402 BatteryStatsImpl.Uid.Pkg pkg =
6403 stats.getPackageStatsLocked(uid, rec.key.packageName);
6404 pkg.incWakeupsLocked();
6405 }
6406 }
6407 }
6408
Dianne Hackborn64825172011-03-02 21:32:58 -08006409 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006410 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006411 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006412 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006413 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006414 // XXX Note: don't acquire main activity lock here, because the window
6415 // manager calls in with its locks held.
6416
6417 boolean killed = false;
6418 synchronized (mPidsSelfLocked) {
6419 int[] types = new int[pids.length];
6420 int worstType = 0;
6421 for (int i=0; i<pids.length; i++) {
6422 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6423 if (proc != null) {
6424 int type = proc.setAdj;
6425 types[i] = type;
6426 if (type > worstType) {
6427 worstType = type;
6428 }
6429 }
6430 }
6431
Dianne Hackborn64825172011-03-02 21:32:58 -08006432 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006433 // then constrain it so we will kill all hidden procs.
6434 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6435 worstType = HIDDEN_APP_MIN_ADJ;
6436 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006437
6438 // If this is not a secure call, don't let it kill processes that
6439 // are important.
6440 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6441 worstType = SECONDARY_SERVER_ADJ;
6442 }
6443
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006444 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006445 for (int i=0; i<pids.length; i++) {
6446 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6447 if (proc == null) {
6448 continue;
6449 }
6450 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006451 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006452 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006453 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6454 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006455 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006456 proc.killedBackground = true;
6457 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006458 }
6459 }
6460 }
6461 return killed;
6462 }
6463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006464 public final void startRunning(String pkg, String cls, String action,
6465 String data) {
6466 synchronized(this) {
6467 if (mStartRunning) {
6468 return;
6469 }
6470 mStartRunning = true;
6471 mTopComponent = pkg != null && cls != null
6472 ? new ComponentName(pkg, cls) : null;
6473 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6474 mTopData = data;
6475 if (!mSystemReady) {
6476 return;
6477 }
6478 }
6479
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006480 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006481 }
6482
6483 private void retrieveSettings() {
6484 final ContentResolver resolver = mContext.getContentResolver();
6485 String debugApp = Settings.System.getString(
6486 resolver, Settings.System.DEBUG_APP);
6487 boolean waitForDebugger = Settings.System.getInt(
6488 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6489 boolean alwaysFinishActivities = Settings.System.getInt(
6490 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6491
6492 Configuration configuration = new Configuration();
6493 Settings.System.getConfiguration(resolver, configuration);
6494
6495 synchronized (this) {
6496 mDebugApp = mOrigDebugApp = debugApp;
6497 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6498 mAlwaysFinishActivities = alwaysFinishActivities;
6499 // This happens before any activities are started, so we can
6500 // change mConfiguration in-place.
6501 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006502 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006503 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006504 }
6505 }
6506
6507 public boolean testIsSystemReady() {
6508 // no need to synchronize(this) just to read & return the value
6509 return mSystemReady;
6510 }
6511
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006512 private static File getCalledPreBootReceiversFile() {
6513 File dataDir = Environment.getDataDirectory();
6514 File systemDir = new File(dataDir, "system");
6515 File fname = new File(systemDir, "called_pre_boots.dat");
6516 return fname;
6517 }
6518
6519 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6520 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6521 File file = getCalledPreBootReceiversFile();
6522 FileInputStream fis = null;
6523 try {
6524 fis = new FileInputStream(file);
6525 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6526 int vers = dis.readInt();
6527 String codename = dis.readUTF();
6528 if (vers == android.os.Build.VERSION.SDK_INT
6529 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6530 int num = dis.readInt();
6531 while (num > 0) {
6532 num--;
6533 String pkg = dis.readUTF();
6534 String cls = dis.readUTF();
6535 lastDoneReceivers.add(new ComponentName(pkg, cls));
6536 }
6537 }
6538 } catch (FileNotFoundException e) {
6539 } catch (IOException e) {
6540 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6541 } finally {
6542 if (fis != null) {
6543 try {
6544 fis.close();
6545 } catch (IOException e) {
6546 }
6547 }
6548 }
6549 return lastDoneReceivers;
6550 }
6551
6552 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6553 File file = getCalledPreBootReceiversFile();
6554 FileOutputStream fos = null;
6555 DataOutputStream dos = null;
6556 try {
6557 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6558 fos = new FileOutputStream(file);
6559 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6560 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6561 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6562 dos.writeInt(list.size());
6563 for (int i=0; i<list.size(); i++) {
6564 dos.writeUTF(list.get(i).getPackageName());
6565 dos.writeUTF(list.get(i).getClassName());
6566 }
6567 } catch (IOException e) {
6568 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6569 file.delete();
6570 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006571 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006572 if (dos != null) {
6573 try {
6574 dos.close();
6575 } catch (IOException e) {
6576 // TODO Auto-generated catch block
6577 e.printStackTrace();
6578 }
6579 }
6580 }
6581 }
6582
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006583 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 // In the simulator, startRunning will never have been called, which
6585 // normally sets a few crucial variables. Do it here instead.
6586 if (!Process.supportsProcesses()) {
6587 mStartRunning = true;
6588 mTopAction = Intent.ACTION_MAIN;
6589 }
6590
6591 synchronized(this) {
6592 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006593 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006594 return;
6595 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006596
6597 // Check to see if there are any update receivers to run.
6598 if (!mDidUpdate) {
6599 if (mWaitingUpdate) {
6600 return;
6601 }
6602 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6603 List<ResolveInfo> ris = null;
6604 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006605 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006606 intent, null, 0);
6607 } catch (RemoteException e) {
6608 }
6609 if (ris != null) {
6610 for (int i=ris.size()-1; i>=0; i--) {
6611 if ((ris.get(i).activityInfo.applicationInfo.flags
6612 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6613 ris.remove(i);
6614 }
6615 }
6616 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006617
6618 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6619
6620 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006621 for (int i=0; i<ris.size(); i++) {
6622 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006623 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6624 if (lastDoneReceivers.contains(comp)) {
6625 ris.remove(i);
6626 i--;
6627 }
6628 }
6629
6630 for (int i=0; i<ris.size(); i++) {
6631 ActivityInfo ai = ris.get(i).activityInfo;
6632 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6633 doneReceivers.add(comp);
6634 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006635 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006636 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006637 finisher = new IIntentReceiver.Stub() {
6638 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006639 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006640 boolean sticky) {
6641 // The raw IIntentReceiver interface is called
6642 // with the AM lock held, so redispatch to
6643 // execute our code without the lock.
6644 mHandler.post(new Runnable() {
6645 public void run() {
6646 synchronized (ActivityManagerService.this) {
6647 mDidUpdate = true;
6648 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006649 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006650 systemReady(goingCallback);
6651 }
6652 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006653 }
6654 };
6655 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006656 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006657 broadcastIntentLocked(null, null, intent, null, finisher,
6658 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006659 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006660 mWaitingUpdate = true;
6661 }
6662 }
6663 }
6664 if (mWaitingUpdate) {
6665 return;
6666 }
6667 mDidUpdate = true;
6668 }
6669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006670 mSystemReady = true;
6671 if (!mStartRunning) {
6672 return;
6673 }
6674 }
6675
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006676 ArrayList<ProcessRecord> procsToKill = null;
6677 synchronized(mPidsSelfLocked) {
6678 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6679 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6680 if (!isAllowedWhileBooting(proc.info)){
6681 if (procsToKill == null) {
6682 procsToKill = new ArrayList<ProcessRecord>();
6683 }
6684 procsToKill.add(proc);
6685 }
6686 }
6687 }
6688
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006689 synchronized(this) {
6690 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006691 for (int i=procsToKill.size()-1; i>=0; i--) {
6692 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006693 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006694 removeProcessLocked(proc, true);
6695 }
6696 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006697
6698 // Now that we have cleaned up any update processes, we
6699 // are ready to start launching real processes and know that
6700 // we won't trample on them any more.
6701 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006702 }
6703
Joe Onorato8a9b2202010-02-26 18:56:32 -08006704 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006705 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006706 SystemClock.uptimeMillis());
6707
6708 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006709 // Make sure we have no pre-ready processes sitting around.
6710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006711 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6712 ResolveInfo ri = mContext.getPackageManager()
6713 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006714 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 CharSequence errorMsg = null;
6716 if (ri != null) {
6717 ActivityInfo ai = ri.activityInfo;
6718 ApplicationInfo app = ai.applicationInfo;
6719 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6720 mTopAction = Intent.ACTION_FACTORY_TEST;
6721 mTopData = null;
6722 mTopComponent = new ComponentName(app.packageName,
6723 ai.name);
6724 } else {
6725 errorMsg = mContext.getResources().getText(
6726 com.android.internal.R.string.factorytest_not_system);
6727 }
6728 } else {
6729 errorMsg = mContext.getResources().getText(
6730 com.android.internal.R.string.factorytest_no_action);
6731 }
6732 if (errorMsg != null) {
6733 mTopAction = null;
6734 mTopData = null;
6735 mTopComponent = null;
6736 Message msg = Message.obtain();
6737 msg.what = SHOW_FACTORY_ERROR_MSG;
6738 msg.getData().putCharSequence("msg", errorMsg);
6739 mHandler.sendMessage(msg);
6740 }
6741 }
6742 }
6743
6744 retrieveSettings();
6745
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006746 if (goingCallback != null) goingCallback.run();
6747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006748 synchronized (this) {
6749 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6750 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006751 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006752 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006753 if (apps != null) {
6754 int N = apps.size();
6755 int i;
6756 for (i=0; i<N; i++) {
6757 ApplicationInfo info
6758 = (ApplicationInfo)apps.get(i);
6759 if (info != null &&
6760 !info.packageName.equals("android")) {
6761 addAppLocked(info);
6762 }
6763 }
6764 }
6765 } catch (RemoteException ex) {
6766 // pm is in same process, this will never happen.
6767 }
6768 }
6769
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006770 // Start up initial activity.
6771 mBooting = true;
6772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006773 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006774 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006775 Message msg = Message.obtain();
6776 msg.what = SHOW_UID_ERROR_MSG;
6777 mHandler.sendMessage(msg);
6778 }
6779 } catch (RemoteException e) {
6780 }
6781
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006782 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006783 }
6784 }
6785
Dan Egnorb7f03672009-12-09 16:22:32 -08006786 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006787 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006788 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006789 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006790 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006791 startAppProblemLocked(app);
6792 app.stopFreezingAllLocked();
6793 return handleAppCrashLocked(app);
6794 }
6795
Dan Egnorb7f03672009-12-09 16:22:32 -08006796 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006797 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006798 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006799 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006800 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6801 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006802 startAppProblemLocked(app);
6803 app.stopFreezingAllLocked();
6804 }
6805
6806 /**
6807 * Generate a process error record, suitable for attachment to a ProcessRecord.
6808 *
6809 * @param app The ProcessRecord in which the error occurred.
6810 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6811 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006812 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006813 * @param shortMsg Short message describing the crash.
6814 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006815 * @param stackTrace Full crash stack trace, may be null.
6816 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006817 * @return Returns a fully-formed AppErrorStateInfo record.
6818 */
6819 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006820 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006821 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006823 report.condition = condition;
6824 report.processName = app.processName;
6825 report.pid = app.pid;
6826 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006827 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006828 report.shortMsg = shortMsg;
6829 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006830 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006831
6832 return report;
6833 }
6834
Dan Egnor42471dd2010-01-07 17:25:22 -08006835 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006836 synchronized (this) {
6837 app.crashing = false;
6838 app.crashingReport = null;
6839 app.notResponding = false;
6840 app.notRespondingReport = null;
6841 if (app.anrDialog == fromDialog) {
6842 app.anrDialog = null;
6843 }
6844 if (app.waitDialog == fromDialog) {
6845 app.waitDialog = null;
6846 }
6847 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006848 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006849 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07006850 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6851 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006852 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006853 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854 }
6855 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006856
Dan Egnorb7f03672009-12-09 16:22:32 -08006857 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006858 long now = SystemClock.uptimeMillis();
6859
6860 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6861 app.info.uid);
6862 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6863 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006864 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006865 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006866 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006867 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006868 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6869 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006870 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006871 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006872 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006873 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006874 }
6875 }
6876 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006877 // Don't let services in this process be restarted and potentially
6878 // annoy the user repeatedly. Unless it is persistent, since those
6879 // processes run critical code.
6880 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006881 // We don't want to start this process again until the user
6882 // explicitly does so... but for persistent process, we really
6883 // need to keep it running. If a persistent process is actually
6884 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006885 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006886 app.info.processName);
6887 mBadProcesses.put(app.info.processName, app.info.uid, now);
6888 app.bad = true;
6889 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6890 app.removed = true;
6891 removeProcessLocked(app, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006892 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006893 return false;
6894 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006895 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006896 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006897 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006898 if (r.app == app) {
6899 // If the top running activity is from this crashing
6900 // process, then terminate it to avoid getting in a loop.
6901 Slog.w(TAG, " Force finishing activity "
6902 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006903 int index = mMainStack.indexOfTokenLocked(r);
6904 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006905 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006906 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006907 // stopped, to avoid a situation where one will get
6908 // re-start our crashing activity once it gets resumed again.
6909 index--;
6910 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006911 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006912 if (r.state == ActivityState.RESUMED
6913 || r.state == ActivityState.PAUSING
6914 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006915 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006916 Slog.w(TAG, " Force finishing activity "
6917 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006918 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006919 Activity.RESULT_CANCELED, null, "crashed");
6920 }
6921 }
6922 }
6923 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006924 }
6925
6926 // Bump up the crash count of any services currently running in the proc.
6927 if (app.services.size() != 0) {
6928 // Any services running in the application need to be placed
6929 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006930 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006931 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006932 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006933 sr.crashCount++;
6934 }
6935 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006936
6937 // If the crashing process is what we consider to be the "home process" and it has been
6938 // replaced by a third-party app, clear the package preferred activities from packages
6939 // with a home activity running in the process to prevent a repeatedly crashing app
6940 // from blocking the user to manually clear the list.
6941 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6942 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6943 Iterator it = mHomeProcess.activities.iterator();
6944 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006945 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006946 if (r.isHomeActivity) {
6947 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6948 try {
6949 ActivityThread.getPackageManager()
6950 .clearPackagePreferredActivities(r.packageName);
6951 } catch (RemoteException c) {
6952 // pm is in same process, this will never happen.
6953 }
6954 }
6955 }
6956 }
6957
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006958 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6959 return true;
6960 }
6961
6962 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006963 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6964 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006965 skipCurrentReceiverLocked(app);
6966 }
6967
6968 void skipCurrentReceiverLocked(ProcessRecord app) {
6969 boolean reschedule = false;
6970 BroadcastRecord r = app.curReceiver;
6971 if (r != null) {
6972 // The current broadcast is waiting for this app's receiver
6973 // to be finished. Looks like that's not going to happen, so
6974 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006975 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006976 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6977 r.resultExtras, r.resultAbort, true);
6978 reschedule = true;
6979 }
6980 r = mPendingBroadcast;
6981 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006982 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006983 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006984 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006985 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6986 r.resultExtras, r.resultAbort, true);
6987 reschedule = true;
6988 }
6989 if (reschedule) {
6990 scheduleBroadcastsLocked();
6991 }
6992 }
6993
Dan Egnor60d87622009-12-16 16:32:58 -08006994 /**
6995 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6996 * The application process will exit immediately after this call returns.
6997 * @param app object of the crashing app, null for the system server
6998 * @param crashInfo describing the exception
6999 */
7000 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007001 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08007002
7003 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
7004 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007005 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007006 crashInfo.exceptionClassName,
7007 crashInfo.exceptionMessage,
7008 crashInfo.throwFileName,
7009 crashInfo.throwLineNumber);
7010
Dan Egnor42471dd2010-01-07 17:25:22 -08007011 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007012
7013 crashApplication(r, crashInfo);
7014 }
7015
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007016 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007017 IBinder app,
7018 int violationMask,
7019 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007020 ProcessRecord r = findAppProcess(app, "StrictMode");
7021 if (r == null) {
7022 return;
7023 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007024
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007025 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08007026 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007027 boolean logIt = true;
7028 synchronized (mAlreadyLoggedViolatedStacks) {
7029 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
7030 logIt = false;
7031 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007032 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007033 // the relative pain numbers, without logging all
7034 // the stack traces repeatedly. We'd want to do
7035 // likewise in the client code, which also does
7036 // dup suppression, before the Binder call.
7037 } else {
7038 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
7039 mAlreadyLoggedViolatedStacks.clear();
7040 }
7041 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
7042 }
7043 }
7044 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007045 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007046 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007047 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007048
7049 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
7050 AppErrorResult result = new AppErrorResult();
7051 synchronized (this) {
7052 final long origId = Binder.clearCallingIdentity();
7053
7054 Message msg = Message.obtain();
7055 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7056 HashMap<String, Object> data = new HashMap<String, Object>();
7057 data.put("result", result);
7058 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007059 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007060 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007061 msg.obj = data;
7062 mHandler.sendMessage(msg);
7063
7064 Binder.restoreCallingIdentity(origId);
7065 }
7066 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007067 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007068 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007069 }
7070
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007071 // Depending on the policy in effect, there could be a bunch of
7072 // these in quick succession so we try to batch these together to
7073 // minimize disk writes, number of dropbox entries, and maximize
7074 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007075 private void logStrictModeViolationToDropBox(
7076 ProcessRecord process,
7077 StrictMode.ViolationInfo info) {
7078 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007079 return;
7080 }
7081 final boolean isSystemApp = process == null ||
7082 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7083 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
7084 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7085 final DropBoxManager dbox = (DropBoxManager)
7086 mContext.getSystemService(Context.DROPBOX_SERVICE);
7087
7088 // Exit early if the dropbox isn't configured to accept this report type.
7089 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7090
7091 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007092 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007093 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7094 synchronized (sb) {
7095 bufferWasEmpty = sb.length() == 0;
7096 appendDropBoxProcessHeaders(process, sb);
7097 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7098 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007099 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7100 if (info.violationNumThisLoop != 0) {
7101 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7102 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007103 if (info.numAnimationsRunning != 0) {
7104 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7105 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007106 if (info.broadcastIntentAction != null) {
7107 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7108 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007109 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007110 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007111 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007112 if (info.numInstances != -1) {
7113 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7114 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007115 if (info.tags != null) {
7116 for (String tag : info.tags) {
7117 sb.append("Span-Tag: ").append(tag).append("\n");
7118 }
7119 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007120 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007121 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7122 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007123 }
7124 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007125
7126 // Only buffer up to ~64k. Various logging bits truncate
7127 // things at 128k.
7128 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007129 }
7130
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007131 // Flush immediately if the buffer's grown too large, or this
7132 // is a non-system app. Non-system apps are isolated with a
7133 // different tag & policy and not batched.
7134 //
7135 // Batching is useful during internal testing with
7136 // StrictMode settings turned up high. Without batching,
7137 // thousands of separate files could be created on boot.
7138 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007139 new Thread("Error dump: " + dropboxTag) {
7140 @Override
7141 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007142 String report;
7143 synchronized (sb) {
7144 report = sb.toString();
7145 sb.delete(0, sb.length());
7146 sb.trimToSize();
7147 }
7148 if (report.length() != 0) {
7149 dbox.addText(dropboxTag, report);
7150 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007151 }
7152 }.start();
7153 return;
7154 }
7155
7156 // System app batching:
7157 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007158 // An existing dropbox-writing thread is outstanding, so
7159 // we don't need to start it up. The existing thread will
7160 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007161 return;
7162 }
7163
7164 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7165 // (After this point, we shouldn't access AMS internal data structures.)
7166 new Thread("Error dump: " + dropboxTag) {
7167 @Override
7168 public void run() {
7169 // 5 second sleep to let stacks arrive and be batched together
7170 try {
7171 Thread.sleep(5000); // 5 seconds
7172 } catch (InterruptedException e) {}
7173
7174 String errorReport;
7175 synchronized (mStrictModeBuffer) {
7176 errorReport = mStrictModeBuffer.toString();
7177 if (errorReport.length() == 0) {
7178 return;
7179 }
7180 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7181 mStrictModeBuffer.trimToSize();
7182 }
7183 dbox.addText(dropboxTag, errorReport);
7184 }
7185 }.start();
7186 }
7187
Dan Egnor60d87622009-12-16 16:32:58 -08007188 /**
7189 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7190 * @param app object of the crashing app, null for the system server
7191 * @param tag reported by the caller
7192 * @param crashInfo describing the context of the error
7193 * @return true if the process should exit immediately (WTF is fatal)
7194 */
7195 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007196 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007197 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007198
7199 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7200 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007201 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007202 tag, crashInfo.exceptionMessage);
7203
Dan Egnor42471dd2010-01-07 17:25:22 -08007204 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007205
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007206 if (r != null && r.pid != Process.myPid() &&
7207 Settings.Secure.getInt(mContext.getContentResolver(),
7208 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007209 crashApplication(r, crashInfo);
7210 return true;
7211 } else {
7212 return false;
7213 }
7214 }
7215
7216 /**
7217 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7218 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7219 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007220 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007221 if (app == null) {
7222 return null;
7223 }
7224
7225 synchronized (this) {
7226 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7227 final int NA = apps.size();
7228 for (int ia=0; ia<NA; ia++) {
7229 ProcessRecord p = apps.valueAt(ia);
7230 if (p.thread != null && p.thread.asBinder() == app) {
7231 return p;
7232 }
7233 }
7234 }
7235
Dianne Hackborncb44d962011-03-10 17:02:27 -08007236 Slog.w(TAG, "Can't find mystery application for " + reason
7237 + " from pid=" + Binder.getCallingPid()
7238 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007239 return null;
7240 }
7241 }
7242
7243 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007244 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7245 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007246 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007247 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007248 // Watchdog thread ends up invoking this function (with
7249 // a null ProcessRecord) to add the stack file to dropbox.
7250 // Do not acquire a lock on this (am) in such cases, as it
7251 // could cause a potential deadlock, if and when watchdog
7252 // is invoked due to unavailability of lock on am and it
7253 // would prevent watchdog from killing system_server.
7254 if (process == null) {
7255 sb.append("Process: system_server\n");
7256 return;
7257 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007258 // Note: ProcessRecord 'process' is guarded by the service
7259 // instance. (notably process.pkgList, which could otherwise change
7260 // concurrently during execution of this method)
7261 synchronized (this) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007262 if (process.pid == MY_PID) {
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007263 sb.append("Process: system_server\n");
7264 } else {
7265 sb.append("Process: ").append(process.processName).append("\n");
7266 }
Dan Egnora455d192010-03-12 08:52:28 -08007267 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007268 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007269 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7270 for (String pkg : process.pkgList) {
7271 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007272 try {
Dan Egnora455d192010-03-12 08:52:28 -08007273 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7274 if (pi != null) {
7275 sb.append(" v").append(pi.versionCode);
7276 if (pi.versionName != null) {
7277 sb.append(" (").append(pi.versionName).append(")");
7278 }
7279 }
7280 } catch (RemoteException e) {
7281 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007282 }
Dan Egnora455d192010-03-12 08:52:28 -08007283 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007284 }
Dan Egnora455d192010-03-12 08:52:28 -08007285 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007286 }
7287
7288 private static String processClass(ProcessRecord process) {
7289 if (process == null || process.pid == MY_PID) {
7290 return "system_server";
7291 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7292 return "system_app";
7293 } else {
7294 return "data_app";
7295 }
7296 }
7297
7298 /**
7299 * Write a description of an error (crash, WTF, ANR) to the drop box.
7300 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7301 * @param process which caused the error, null means the system server
7302 * @param activity which triggered the error, null if unknown
7303 * @param parent activity related to the error, null if unknown
7304 * @param subject line related to the error, null if absent
7305 * @param report in long form describing the error, null if absent
7306 * @param logFile to include in the report, null if none
7307 * @param crashInfo giving an application stack trace, null if absent
7308 */
7309 public void addErrorToDropBox(String eventType,
7310 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7311 final String report, final File logFile,
7312 final ApplicationErrorReport.CrashInfo crashInfo) {
7313 // NOTE -- this must never acquire the ActivityManagerService lock,
7314 // otherwise the watchdog may be prevented from resetting the system.
7315
7316 final String dropboxTag = processClass(process) + "_" + eventType;
7317 final DropBoxManager dbox = (DropBoxManager)
7318 mContext.getSystemService(Context.DROPBOX_SERVICE);
7319
7320 // Exit early if the dropbox isn't configured to accept this report type.
7321 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7322
7323 final StringBuilder sb = new StringBuilder(1024);
7324 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007325 if (activity != null) {
7326 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7327 }
7328 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7329 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7330 }
7331 if (parent != null && parent != activity) {
7332 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7333 }
7334 if (subject != null) {
7335 sb.append("Subject: ").append(subject).append("\n");
7336 }
7337 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007338 if (Debug.isDebuggerConnected()) {
7339 sb.append("Debugger: Connected\n");
7340 }
Dan Egnora455d192010-03-12 08:52:28 -08007341 sb.append("\n");
7342
7343 // Do the rest in a worker thread to avoid blocking the caller on I/O
7344 // (After this point, we shouldn't access AMS internal data structures.)
7345 Thread worker = new Thread("Error dump: " + dropboxTag) {
7346 @Override
7347 public void run() {
7348 if (report != null) {
7349 sb.append(report);
7350 }
7351 if (logFile != null) {
7352 try {
7353 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7354 } catch (IOException e) {
7355 Slog.e(TAG, "Error reading " + logFile, e);
7356 }
7357 }
7358 if (crashInfo != null && crashInfo.stackTrace != null) {
7359 sb.append(crashInfo.stackTrace);
7360 }
7361
7362 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7363 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7364 if (lines > 0) {
7365 sb.append("\n");
7366
7367 // Merge several logcat streams, and take the last N lines
7368 InputStreamReader input = null;
7369 try {
7370 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7371 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7372 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7373
7374 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7375 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7376 input = new InputStreamReader(logcat.getInputStream());
7377
7378 int num;
7379 char[] buf = new char[8192];
7380 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7381 } catch (IOException e) {
7382 Slog.e(TAG, "Error running logcat", e);
7383 } finally {
7384 if (input != null) try { input.close(); } catch (IOException e) {}
7385 }
7386 }
7387
7388 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007389 }
Dan Egnora455d192010-03-12 08:52:28 -08007390 };
7391
7392 if (process == null || process.pid == MY_PID) {
7393 worker.run(); // We may be about to die -- need to run this synchronously
7394 } else {
7395 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007396 }
7397 }
7398
7399 /**
7400 * Bring up the "unexpected error" dialog box for a crashing app.
7401 * Deal with edge cases (intercepts from instrumented applications,
7402 * ActivityController, error intent receivers, that sort of thing).
7403 * @param r the application crashing
7404 * @param crashInfo describing the failure
7405 */
7406 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007407 long timeMillis = System.currentTimeMillis();
7408 String shortMsg = crashInfo.exceptionClassName;
7409 String longMsg = crashInfo.exceptionMessage;
7410 String stackTrace = crashInfo.stackTrace;
7411 if (shortMsg != null && longMsg != null) {
7412 longMsg = shortMsg + ": " + longMsg;
7413 } else if (shortMsg != null) {
7414 longMsg = shortMsg;
7415 }
7416
Dan Egnor60d87622009-12-16 16:32:58 -08007417 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007418 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007419 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007420 try {
7421 String name = r != null ? r.processName : null;
7422 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007423 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007424 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007425 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007426 + " at watcher's request");
7427 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007428 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007429 }
7430 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007431 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007432 }
7433 }
7434
7435 final long origId = Binder.clearCallingIdentity();
7436
7437 // If this process is running instrumentation, finish it.
7438 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007439 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007441 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7442 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007443 Bundle info = new Bundle();
7444 info.putString("shortMsg", shortMsg);
7445 info.putString("longMsg", longMsg);
7446 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7447 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007448 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007449 }
7450
Dan Egnor60d87622009-12-16 16:32:58 -08007451 // If we can't identify the process or it's already exceeded its crash quota,
7452 // quit right away without showing a crash dialog.
7453 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007454 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007455 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007456 }
7457
7458 Message msg = Message.obtain();
7459 msg.what = SHOW_ERROR_MSG;
7460 HashMap data = new HashMap();
7461 data.put("result", result);
7462 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007463 msg.obj = data;
7464 mHandler.sendMessage(msg);
7465
7466 Binder.restoreCallingIdentity(origId);
7467 }
7468
7469 int res = result.get();
7470
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007471 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007472 synchronized (this) {
7473 if (r != null) {
7474 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7475 SystemClock.uptimeMillis());
7476 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007477 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007478 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007479 }
7480 }
7481
7482 if (appErrorIntent != null) {
7483 try {
7484 mContext.startActivity(appErrorIntent);
7485 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007486 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007489 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007490
7491 Intent createAppErrorIntentLocked(ProcessRecord r,
7492 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7493 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007494 if (report == null) {
7495 return null;
7496 }
7497 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7498 result.setComponent(r.errorReportReceiver);
7499 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7500 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7501 return result;
7502 }
7503
Dan Egnorb7f03672009-12-09 16:22:32 -08007504 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7505 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007506 if (r.errorReportReceiver == null) {
7507 return null;
7508 }
7509
7510 if (!r.crashing && !r.notResponding) {
7511 return null;
7512 }
7513
Dan Egnorb7f03672009-12-09 16:22:32 -08007514 ApplicationErrorReport report = new ApplicationErrorReport();
7515 report.packageName = r.info.packageName;
7516 report.installerPackageName = r.errorReportReceiver.getPackageName();
7517 report.processName = r.processName;
7518 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007519 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007520
Dan Egnorb7f03672009-12-09 16:22:32 -08007521 if (r.crashing) {
7522 report.type = ApplicationErrorReport.TYPE_CRASH;
7523 report.crashInfo = crashInfo;
7524 } else if (r.notResponding) {
7525 report.type = ApplicationErrorReport.TYPE_ANR;
7526 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007527
Dan Egnorb7f03672009-12-09 16:22:32 -08007528 report.anrInfo.activity = r.notRespondingReport.tag;
7529 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7530 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007531 }
7532
Dan Egnorb7f03672009-12-09 16:22:32 -08007533 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007534 }
7535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007536 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7537 // assume our apps are happy - lazy create the list
7538 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7539
7540 synchronized (this) {
7541
7542 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007543 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7544 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7546 // This one's in trouble, so we'll generate a report for it
7547 // crashes are higher priority (in case there's a crash *and* an anr)
7548 ActivityManager.ProcessErrorStateInfo report = null;
7549 if (app.crashing) {
7550 report = app.crashingReport;
7551 } else if (app.notResponding) {
7552 report = app.notRespondingReport;
7553 }
7554
7555 if (report != null) {
7556 if (errList == null) {
7557 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7558 }
7559 errList.add(report);
7560 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007561 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007562 " crashing = " + app.crashing +
7563 " notResponding = " + app.notResponding);
7564 }
7565 }
7566 }
7567 }
7568
7569 return errList;
7570 }
7571
7572 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7573 // Lazy instantiation of list
7574 List<ActivityManager.RunningAppProcessInfo> runList = null;
7575 synchronized (this) {
7576 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007577 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7578 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007579 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7580 // Generate process state info for running application
7581 ActivityManager.RunningAppProcessInfo currApp =
7582 new ActivityManager.RunningAppProcessInfo(app.processName,
7583 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007584 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007585 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007586 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007587 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007588 if (app.persistent) {
7589 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007592 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007593 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7594 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7595 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007596 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7597 } else if (adj >= HOME_APP_ADJ) {
7598 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7599 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007600 } else if (adj >= SECONDARY_SERVER_ADJ) {
7601 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007602 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007603 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007604 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7605 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 } else if (adj >= VISIBLE_APP_ADJ) {
7607 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7608 } else {
7609 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7610 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007611 currApp.importanceReasonCode = app.adjTypeCode;
7612 if (app.adjSource instanceof ProcessRecord) {
7613 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007614 } else if (app.adjSource instanceof ActivityRecord) {
7615 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007616 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7617 }
7618 if (app.adjTarget instanceof ComponentName) {
7619 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7620 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007621 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007622 // + " lru=" + currApp.lru);
7623 if (runList == null) {
7624 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7625 }
7626 runList.add(currApp);
7627 }
7628 }
7629 }
7630 return runList;
7631 }
7632
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007633 public List<ApplicationInfo> getRunningExternalApplications() {
7634 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7635 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7636 if (runningApps != null && runningApps.size() > 0) {
7637 Set<String> extList = new HashSet<String>();
7638 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7639 if (app.pkgList != null) {
7640 for (String pkg : app.pkgList) {
7641 extList.add(pkg);
7642 }
7643 }
7644 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007645 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007646 for (String pkg : extList) {
7647 try {
7648 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7649 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7650 retList.add(info);
7651 }
7652 } catch (RemoteException e) {
7653 }
7654 }
7655 }
7656 return retList;
7657 }
7658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007659 @Override
7660 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007661 if (checkCallingPermission(android.Manifest.permission.DUMP)
7662 != PackageManager.PERMISSION_GRANTED) {
7663 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7664 + Binder.getCallingPid()
7665 + ", uid=" + Binder.getCallingUid()
7666 + " without permission "
7667 + android.Manifest.permission.DUMP);
7668 return;
7669 }
7670
7671 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007672 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007673
7674 int opti = 0;
7675 while (opti < args.length) {
7676 String opt = args[opti];
7677 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7678 break;
7679 }
7680 opti++;
7681 if ("-a".equals(opt)) {
7682 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007683 } else if ("-c".equals(opt)) {
7684 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007685 } else if ("-h".equals(opt)) {
7686 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007687 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007688 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007689 pw.println(" a[ctivities]: activity stack state");
7690 pw.println(" b[roadcasts]: broadcast state");
7691 pw.println(" i[ntents]: pending intent state");
7692 pw.println(" p[rocesses]: process state");
7693 pw.println(" o[om]: out of memory management");
7694 pw.println(" prov[iders]: content provider state");
7695 pw.println(" s[ervices]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007696 pw.println(" service [COMP_SPEC]: service client-side state");
7697 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
7698 pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),");
7699 pw.println(" a partial substring in a component name, an");
7700 pw.println(" ActivityRecord hex object identifier, or");
Dianne Hackbornf9302322011-06-14 18:36:14 -07007701 pw.println(" \"all\" for all objects, or");
7702 pw.println(" \"top\" for the top activity.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007703 pw.println(" -a: include all available server state.");
7704 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007705 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007706 } else {
7707 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007708 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007709 }
7710
7711 // Is the caller requesting to dump a particular piece of data?
7712 if (opti < args.length) {
7713 String cmd = args[opti];
7714 opti++;
7715 if ("activities".equals(cmd) || "a".equals(cmd)) {
7716 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007717 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007719 return;
7720 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7721 synchronized (this) {
7722 dumpBroadcastsLocked(fd, pw, args, opti, true);
7723 }
7724 return;
7725 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7726 synchronized (this) {
7727 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7728 }
7729 return;
7730 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7731 synchronized (this) {
7732 dumpProcessesLocked(fd, pw, args, opti, true);
7733 }
7734 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007735 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7736 synchronized (this) {
7737 dumpOomLocked(fd, pw, args, opti, true);
7738 }
7739 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007740 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7741 synchronized (this) {
7742 dumpProvidersLocked(fd, pw, args, opti, true);
7743 }
7744 return;
7745 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007746 String[] newArgs;
7747 String name;
7748 if (opti >= args.length) {
7749 name = null;
7750 newArgs = EMPTY_STRING_ARRAY;
7751 } else {
7752 name = args[opti];
7753 opti++;
7754 newArgs = new String[args.length - opti];
7755 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7756 }
7757 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7758 pw.println("No services match: " + name);
7759 pw.println("Use -h for help.");
7760 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007761 return;
7762 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7763 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007764 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007765 }
7766 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007767 } else {
7768 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007769 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7770 pw.println("Bad activity command, or no activities match: " + cmd);
7771 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007772 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007773 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007775 }
7776
7777 // No piece of data specified, dump everything.
7778 synchronized (this) {
7779 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007780 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
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 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7788 if (needSep) {
7789 pw.println(" ");
7790 }
7791 if (dumpAll) {
7792 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007793 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007794 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007795 if (needSep) {
7796 pw.println(" ");
7797 }
7798 if (dumpAll) {
7799 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007800 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007801 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007802 if (needSep) {
7803 pw.println(" ");
7804 }
7805 if (dumpAll) {
7806 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007807 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007808 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007809 if (needSep) {
7810 pw.println(" ");
7811 }
7812 if (dumpAll) {
7813 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007814 }
7815 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7816 }
7817 }
7818
7819 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007820 int opti, boolean dumpAll, boolean dumpClient) {
7821 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7822 pw.println(" Main stack:");
7823 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007824 pw.println(" ");
7825 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007826 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007827 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007828 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007829 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007830 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7831 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007832 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007833 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007834 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007835 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007836 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7837 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007838 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007839 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7840 pw.println(" ");
7841 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007842 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7843 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007844 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007845 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007846 pw.println(" ");
7847 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007848 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7849 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007851
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007852 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007853 if (mMainStack.mPausingActivity != null) {
7854 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7855 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007856 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007857 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007858 if (dumpAll) {
7859 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7860 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
7861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007863 if (mRecentTasks.size() > 0) {
7864 pw.println();
7865 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007866
7867 final int N = mRecentTasks.size();
7868 for (int i=0; i<N; i++) {
7869 TaskRecord tr = mRecentTasks.get(i);
7870 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7871 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007872 if (dumpAll) {
7873 mRecentTasks.get(i).dump(pw, " ");
7874 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007875 }
7876 }
7877
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007878 if (dumpAll) {
7879 pw.println(" ");
7880 pw.println(" mCurTask: " + mCurTask);
7881 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007882
7883 return true;
7884 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007885
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007886 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7887 int opti, boolean dumpAll) {
7888 boolean needSep = false;
7889 int numPers = 0;
7890
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007891 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7892
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007893 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007894 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7895 final int NA = procs.size();
7896 for (int ia=0; ia<NA; ia++) {
7897 if (!needSep) {
7898 pw.println(" All known processes:");
7899 needSep = true;
7900 }
7901 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007902 pw.print(r.persistent ? " *PERS*" : " *APP*");
7903 pw.print(" UID "); pw.print(procs.keyAt(ia));
7904 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007905 r.dump(pw, " ");
7906 if (r.persistent) {
7907 numPers++;
7908 }
7909 }
7910 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007911 }
7912
7913 if (mLruProcesses.size() > 0) {
7914 if (needSep) pw.println(" ");
7915 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007916 pw.println(" Process LRU list (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007917 dumpProcessOomList(pw, this, mLruProcesses, " ",
7918 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007919 needSep = true;
7920 }
7921
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007922 if (dumpAll) {
7923 synchronized (mPidsSelfLocked) {
7924 if (mPidsSelfLocked.size() > 0) {
7925 if (needSep) pw.println(" ");
7926 needSep = true;
7927 pw.println(" PID mappings:");
7928 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7929 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7930 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
7931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007932 }
7933 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007934 }
7935
7936 if (mForegroundProcesses.size() > 0) {
7937 if (needSep) pw.println(" ");
7938 needSep = true;
7939 pw.println(" Foreground Processes:");
7940 for (int i=0; i<mForegroundProcesses.size(); i++) {
7941 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7942 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007943 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007944 }
7945
7946 if (mPersistentStartingProcesses.size() > 0) {
7947 if (needSep) pw.println(" ");
7948 needSep = true;
7949 pw.println(" Persisent processes that are starting:");
7950 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007951 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007952 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007953
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007954 if (mStartingProcesses.size() > 0) {
7955 if (needSep) pw.println(" ");
7956 needSep = true;
7957 pw.println(" Processes that are starting:");
7958 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007959 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007960 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007961
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007962 if (mRemovedProcesses.size() > 0) {
7963 if (needSep) pw.println(" ");
7964 needSep = true;
7965 pw.println(" Processes that are being removed:");
7966 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007967 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007968 }
7969
7970 if (mProcessesOnHold.size() > 0) {
7971 if (needSep) pw.println(" ");
7972 needSep = true;
7973 pw.println(" Processes that are on old until the system is ready:");
7974 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007975 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007977
Dianne Hackborn287952c2010-09-22 22:34:31 -07007978 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007979
7980 if (mProcessCrashTimes.getMap().size() > 0) {
7981 if (needSep) pw.println(" ");
7982 needSep = true;
7983 pw.println(" Time since processes crashed:");
7984 long now = SystemClock.uptimeMillis();
7985 for (Map.Entry<String, SparseArray<Long>> procs
7986 : mProcessCrashTimes.getMap().entrySet()) {
7987 SparseArray<Long> uids = procs.getValue();
7988 final int N = uids.size();
7989 for (int i=0; i<N; i++) {
7990 pw.print(" Process "); pw.print(procs.getKey());
7991 pw.print(" uid "); pw.print(uids.keyAt(i));
7992 pw.print(": last crashed ");
7993 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007994 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007995 }
7996 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007998
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007999 if (mBadProcesses.getMap().size() > 0) {
8000 if (needSep) pw.println(" ");
8001 needSep = true;
8002 pw.println(" Bad processes:");
8003 for (Map.Entry<String, SparseArray<Long>> procs
8004 : mBadProcesses.getMap().entrySet()) {
8005 SparseArray<Long> uids = procs.getValue();
8006 final int N = uids.size();
8007 for (int i=0; i<N; i++) {
8008 pw.print(" Bad process "); pw.print(procs.getKey());
8009 pw.print(" uid "); pw.print(uids.keyAt(i));
8010 pw.print(": crashed at time ");
8011 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008012 }
8013 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008014 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008015
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008016 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008017 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008018 if (mHeavyWeightProcess != null) {
8019 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8020 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008021 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008022 if (dumpAll) {
8023 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07008024 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07008025 pw.println(" mScreenCompatPackages:");
8026 for (Map.Entry<String, Integer> entry
8027 : mCompatModePackages.getPackages().entrySet()) {
8028 String pkg = entry.getKey();
8029 int mode = entry.getValue();
8030 pw.print(" "); pw.print(pkg); pw.print(": ");
8031 pw.print(mode); pw.println();
8032 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07008033 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008034 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008035 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
8036 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
8037 || mOrigWaitForDebugger) {
8038 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
8039 + " mDebugTransient=" + mDebugTransient
8040 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
8041 }
8042 if (mAlwaysFinishActivities || mController != null) {
8043 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
8044 + " mController=" + mController);
8045 }
8046 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008047 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008049 + " mProcessesReady=" + mProcessesReady
8050 + " mSystemReady=" + mSystemReady);
8051 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008052 + " mBooted=" + mBooted
8053 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008054 pw.print(" mLastPowerCheckRealtime=");
8055 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
8056 pw.println("");
8057 pw.print(" mLastPowerCheckUptime=");
8058 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
8059 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008060 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8061 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008062 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008063 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008064
8065 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 }
8067
Dianne Hackborn287952c2010-09-22 22:34:31 -07008068 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
8069 int opti, boolean needSep, boolean dumpAll) {
8070 if (mProcessesToGc.size() > 0) {
8071 if (needSep) pw.println(" ");
8072 needSep = true;
8073 pw.println(" Processes that are waiting to GC:");
8074 long now = SystemClock.uptimeMillis();
8075 for (int i=0; i<mProcessesToGc.size(); i++) {
8076 ProcessRecord proc = mProcessesToGc.get(i);
8077 pw.print(" Process "); pw.println(proc);
8078 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8079 pw.print(", last gced=");
8080 pw.print(now-proc.lastRequestedGc);
8081 pw.print(" ms ago, last lowMem=");
8082 pw.print(now-proc.lastLowMemory);
8083 pw.println(" ms ago");
8084
8085 }
8086 }
8087 return needSep;
8088 }
8089
8090 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8091 int opti, boolean dumpAll) {
8092 boolean needSep = false;
8093
8094 if (mLruProcesses.size() > 0) {
8095 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
8096
8097 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
8098 @Override
8099 public int compare(ProcessRecord object1, ProcessRecord object2) {
8100 if (object1.setAdj != object2.setAdj) {
8101 return object1.setAdj > object2.setAdj ? -1 : 1;
8102 }
8103 if (object1.setSchedGroup != object2.setSchedGroup) {
8104 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
8105 }
8106 if (object1.keeping != object2.keeping) {
8107 return object1.keeping ? -1 : 1;
8108 }
8109 if (object1.pid != object2.pid) {
8110 return object1.pid > object2.pid ? -1 : 1;
8111 }
8112 return 0;
8113 }
8114 };
8115
8116 Collections.sort(procs, comparator);
8117
8118 if (needSep) pw.println(" ");
8119 needSep = true;
8120 pw.println(" Process OOM control:");
8121 dumpProcessOomList(pw, this, procs, " ",
8122 "Proc", "PERS", true);
8123 needSep = true;
8124 }
8125
8126 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
8127
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008128 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008129 pw.println(" mHomeProcess: " + mHomeProcess);
8130 if (mHeavyWeightProcess != null) {
8131 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8132 }
8133
8134 return true;
8135 }
8136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 /**
8138 * There are three ways to call this:
8139 * - no service specified: dump all the services
8140 * - a flattened component name that matched an existing service was specified as the
8141 * first arg: dump that one service
8142 * - the first arg isn't the flattened component name of an existing service:
8143 * dump all services whose component contains the first arg as a substring
8144 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008145 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8146 int opti, boolean dumpAll) {
8147 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008148
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008149 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008150 synchronized (this) {
8151 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008152 services.add(r1);
8153 }
8154 }
8155 } else {
8156 ComponentName componentName = name != null
8157 ? ComponentName.unflattenFromString(name) : null;
8158 int objectId = 0;
8159 if (componentName == null) {
8160 // Not a '/' separated full component name; maybe an object ID?
8161 try {
8162 objectId = Integer.parseInt(name, 16);
8163 name = null;
8164 componentName = null;
8165 } catch (RuntimeException e) {
8166 }
8167 }
8168
8169 synchronized (this) {
8170 for (ServiceRecord r1 : mServices.values()) {
8171 if (componentName != null) {
8172 if (r1.name.equals(componentName)) {
8173 services.add(r1);
8174 }
8175 } else if (name != null) {
8176 if (r1.name.flattenToString().contains(name)) {
8177 services.add(r1);
8178 }
8179 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008180 services.add(r1);
8181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008182 }
8183 }
8184 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008185
8186 if (services.size() <= 0) {
8187 return false;
8188 }
8189
8190 boolean needSep = false;
8191 for (int i=0; i<services.size(); i++) {
8192 if (needSep) {
8193 pw.println();
8194 }
8195 needSep = true;
8196 dumpService("", fd, pw, services.get(i), args, dumpAll);
8197 }
8198 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008199 }
8200
8201 /**
8202 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8203 * there is a thread associated with the service.
8204 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008205 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8206 final ServiceRecord r, String[] args, boolean dumpAll) {
8207 String innerPrefix = prefix + " ";
8208 synchronized (this) {
8209 pw.print(prefix); pw.print("SERVICE ");
8210 pw.print(r.shortName); pw.print(" ");
8211 pw.print(Integer.toHexString(System.identityHashCode(r)));
8212 pw.print(" pid=");
8213 if (r.app != null) pw.println(r.app.pid);
8214 else pw.println("(not running)");
8215 if (dumpAll) {
8216 r.dump(pw, innerPrefix);
8217 }
8218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008220 pw.print(prefix); pw.println(" Client:");
8221 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008222 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008223 TransferPipe tp = new TransferPipe();
8224 try {
8225 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8226 tp.setBufferPrefix(prefix + " ");
8227 tp.go(fd);
8228 } finally {
8229 tp.kill();
8230 }
8231 } catch (IOException e) {
8232 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008233 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008234 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008235 }
8236 }
8237 }
8238
Dianne Hackborn625ac272010-09-17 18:29:22 -07008239 /**
8240 * There are three things that cmd can be:
8241 * - a flattened component name that matched an existing activity
8242 * - the cmd arg isn't the flattened component name of an existing activity:
8243 * dump all activity whose component contains the cmd as a substring
8244 * - A hex number of the ActivityRecord object instance.
8245 */
8246 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8247 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008248 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008249
8250 if ("all".equals(name)) {
8251 synchronized (this) {
8252 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008253 activities.add(r1);
8254 }
8255 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07008256 } else if ("top".equals(name)) {
8257 synchronized (this) {
8258 final int N = mMainStack.mHistory.size();
8259 if (N > 0) {
8260 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
8261 }
8262 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008263 } else {
8264 ComponentName componentName = ComponentName.unflattenFromString(name);
8265 int objectId = 0;
8266 if (componentName == null) {
8267 // Not a '/' separated full component name; maybe an object ID?
8268 try {
8269 objectId = Integer.parseInt(name, 16);
8270 name = null;
8271 componentName = null;
8272 } catch (RuntimeException e) {
8273 }
8274 }
8275
8276 synchronized (this) {
8277 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
8278 if (componentName != null) {
8279 if (r1.intent.getComponent().equals(componentName)) {
8280 activities.add(r1);
8281 }
8282 } else if (name != null) {
8283 if (r1.intent.getComponent().flattenToString().contains(name)) {
8284 activities.add(r1);
8285 }
8286 } else if (System.identityHashCode(r1) == objectId) {
8287 activities.add(r1);
8288 }
8289 }
8290 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008291 }
8292
8293 if (activities.size() <= 0) {
8294 return false;
8295 }
8296
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008297 String[] newArgs = new String[args.length - opti];
8298 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8299
Dianne Hackborn30d71892010-12-11 10:37:55 -08008300 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008301 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008302 for (int i=activities.size()-1; i>=0; i--) {
8303 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008304 if (needSep) {
8305 pw.println();
8306 }
8307 needSep = true;
8308 synchronized (this) {
8309 if (lastTask != r.task) {
8310 lastTask = r.task;
8311 pw.print("TASK "); pw.print(lastTask.affinity);
8312 pw.print(" id="); pw.println(lastTask.taskId);
8313 if (dumpAll) {
8314 lastTask.dump(pw, " ");
8315 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008316 }
8317 }
8318 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008319 }
8320 return true;
8321 }
8322
8323 /**
8324 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8325 * there is a thread associated with the activity.
8326 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008327 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008328 final ActivityRecord r, String[] args, boolean dumpAll) {
8329 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008330 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008331 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8332 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8333 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008334 if (r.app != null) pw.println(r.app.pid);
8335 else pw.println("(not running)");
8336 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008337 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008338 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008339 }
8340 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008341 // flush anything that is already in the PrintWriter since the thread is going
8342 // to write to the file descriptor directly
8343 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008344 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008345 TransferPipe tp = new TransferPipe();
8346 try {
8347 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8348 innerPrefix, args);
8349 tp.go(fd);
8350 } finally {
8351 tp.kill();
8352 }
8353 } catch (IOException e) {
8354 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008355 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008356 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008357 }
8358 }
8359 }
8360
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008361 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8362 int opti, boolean dumpAll) {
8363 boolean needSep = false;
8364
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008365 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008366 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008367 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008368 pw.println(" Registered Receivers:");
8369 Iterator it = mRegisteredReceivers.values().iterator();
8370 while (it.hasNext()) {
8371 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008372 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008373 r.dump(pw, " ");
8374 }
8375 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008376
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008377 pw.println();
8378 pw.println(" Receiver Resolver Table:");
8379 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008380 needSep = true;
8381 }
8382
8383 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8384 || mPendingBroadcast != null) {
8385 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008386 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008387 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008388 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008389 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8390 pw.println(" Broadcast #" + i + ":");
8391 mParallelBroadcasts.get(i).dump(pw, " ");
8392 }
8393 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008394 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008395 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008396 }
8397 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8398 pw.println(" Serialized Broadcast #" + i + ":");
8399 mOrderedBroadcasts.get(i).dump(pw, " ");
8400 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008401 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008402 pw.println(" Pending broadcast:");
8403 if (mPendingBroadcast != null) {
8404 mPendingBroadcast.dump(pw, " ");
8405 } else {
8406 pw.println(" (null)");
8407 }
8408 needSep = true;
8409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008410
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008411 if (needSep) {
8412 pw.println();
8413 }
8414 pw.println(" Historical broadcasts:");
8415 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8416 BroadcastRecord r = mBroadcastHistory[i];
8417 if (r == null) {
8418 break;
8419 }
8420 if (dumpAll) {
8421 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8422 r.dump(pw, " ");
8423 } else {
8424 if (i >= 50) {
8425 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008426 break;
8427 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008428 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008429 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008430 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008431 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008432
8433 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008434 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008435 pw.println(" Sticky broadcasts:");
8436 StringBuilder sb = new StringBuilder(128);
8437 for (Map.Entry<String, ArrayList<Intent>> ent
8438 : mStickyBroadcasts.entrySet()) {
8439 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008440 if (dumpAll) {
8441 pw.println(":");
8442 ArrayList<Intent> intents = ent.getValue();
8443 final int N = intents.size();
8444 for (int i=0; i<N; i++) {
8445 sb.setLength(0);
8446 sb.append(" Intent: ");
8447 intents.get(i).toShortString(sb, true, false);
8448 pw.println(sb.toString());
8449 Bundle bundle = intents.get(i).getExtras();
8450 if (bundle != null) {
8451 pw.print(" ");
8452 pw.println(bundle.toString());
8453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008454 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008455 } else {
8456 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008457 }
8458 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008459 needSep = true;
8460 }
8461
8462 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008463 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008464 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008465 pw.println(" mHandler:");
8466 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008467 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008468 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008469
8470 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 }
8472
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008473 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008474 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008475 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008476
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008477 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8478 if (mServices.size() > 0) {
8479 pw.println(" Active services:");
8480 long nowReal = SystemClock.elapsedRealtime();
8481 Iterator<ServiceRecord> it = mServices.values().iterator();
8482 needSep = false;
8483 while (it.hasNext()) {
8484 ServiceRecord r = it.next();
8485 if (needSep) {
8486 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008487 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008488 pw.print(" * "); pw.println(r);
8489 if (dumpAll) {
8490 r.dump(pw, " ");
8491 needSep = true;
8492 } else {
8493 pw.print(" app="); pw.println(r.app);
8494 pw.print(" created=");
8495 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8496 pw.print(" started="); pw.print(r.startRequested);
8497 pw.print(" connections="); pw.println(r.connections.size());
8498 }
8499 if (dumpClient && r.app != null && r.app.thread != null) {
8500 pw.println(" Client:");
8501 pw.flush();
8502 try {
8503 TransferPipe tp = new TransferPipe();
8504 try {
8505 r.app.thread.dumpService(
8506 tp.getWriteFd().getFileDescriptor(), r, args);
8507 tp.setBufferPrefix(" ");
8508 // Short timeout, since blocking here can
8509 // deadlock with the application.
8510 tp.go(fd, 2000);
8511 } finally {
8512 tp.kill();
8513 }
8514 } catch (IOException e) {
8515 pw.println(" Failure while dumping the service: " + e);
8516 } catch (RemoteException e) {
8517 pw.println(" Got a RemoteException while dumping the service");
8518 }
8519 needSep = true;
8520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008521 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008522 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008524
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008525 if (mPendingServices.size() > 0) {
8526 if (needSep) pw.println(" ");
8527 pw.println(" Pending services:");
8528 for (int i=0; i<mPendingServices.size(); i++) {
8529 ServiceRecord r = mPendingServices.get(i);
8530 pw.print(" * Pending "); pw.println(r);
8531 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008532 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008533 needSep = true;
8534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008535
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008536 if (mRestartingServices.size() > 0) {
8537 if (needSep) pw.println(" ");
8538 pw.println(" Restarting services:");
8539 for (int i=0; i<mRestartingServices.size(); i++) {
8540 ServiceRecord r = mRestartingServices.get(i);
8541 pw.print(" * Restarting "); pw.println(r);
8542 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008543 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008544 needSep = true;
8545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008546
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008547 if (mStoppingServices.size() > 0) {
8548 if (needSep) pw.println(" ");
8549 pw.println(" Stopping services:");
8550 for (int i=0; i<mStoppingServices.size(); i++) {
8551 ServiceRecord r = mStoppingServices.get(i);
8552 pw.print(" * Stopping "); pw.println(r);
8553 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008554 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008555 needSep = true;
8556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008557
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008558 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008559 if (mServiceConnections.size() > 0) {
8560 if (needSep) pw.println(" ");
8561 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008562 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008563 = mServiceConnections.values().iterator();
8564 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008565 ArrayList<ConnectionRecord> r = it.next();
8566 for (int i=0; i<r.size(); i++) {
8567 pw.print(" * "); pw.println(r.get(i));
8568 r.get(i).dump(pw, " ");
8569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008570 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008571 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008572 }
8573 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008574
8575 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008576 }
8577
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008578 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8579 int opti, boolean dumpAll) {
8580 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008581
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008582 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8583 if (mProvidersByClass.size() > 0) {
8584 if (needSep) pw.println(" ");
8585 pw.println(" Published content providers (by class):");
8586 Iterator<Map.Entry<String, ContentProviderRecord>> it
8587 = mProvidersByClass.entrySet().iterator();
8588 while (it.hasNext()) {
8589 Map.Entry<String, ContentProviderRecord> e = it.next();
8590 ContentProviderRecord r = e.getValue();
8591 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008592 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008593 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008594 } else {
8595 pw.print(" * "); pw.print(r.name.toShortString());
8596 if (r.app != null) {
8597 pw.println(":");
8598 pw.print(" "); pw.println(r.app);
8599 } else {
8600 pw.println();
8601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008603 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008604 needSep = true;
8605 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008606
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008607 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008608 if (mProvidersByName.size() > 0) {
8609 pw.println(" ");
8610 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008611 Iterator<Map.Entry<String, ContentProviderRecord>> it
8612 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008613 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008614 Map.Entry<String, ContentProviderRecord> e = it.next();
8615 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008616 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8617 pw.println(r);
8618 }
8619 needSep = true;
8620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008621 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008622
8623 if (mLaunchingProviders.size() > 0) {
8624 if (needSep) pw.println(" ");
8625 pw.println(" Launching content providers:");
8626 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8627 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8628 pw.println(mLaunchingProviders.get(i));
8629 }
8630 needSep = true;
8631 }
8632
8633 if (mGrantedUriPermissions.size() > 0) {
8634 pw.println();
8635 pw.println("Granted Uri Permissions:");
8636 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8637 int uid = mGrantedUriPermissions.keyAt(i);
8638 HashMap<Uri, UriPermission> perms
8639 = mGrantedUriPermissions.valueAt(i);
8640 pw.print(" * UID "); pw.print(uid);
8641 pw.println(" holds:");
8642 for (UriPermission perm : perms.values()) {
8643 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008644 if (dumpAll) {
8645 perm.dump(pw, " ");
8646 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008647 }
8648 }
8649 needSep = true;
8650 }
8651
8652 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008653 }
8654
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008655 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8656 int opti, boolean dumpAll) {
8657 boolean needSep = false;
8658
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008659 if (this.mIntentSenderRecords.size() > 0) {
8660 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8661 Iterator<WeakReference<PendingIntentRecord>> it
8662 = mIntentSenderRecords.values().iterator();
8663 while (it.hasNext()) {
8664 WeakReference<PendingIntentRecord> ref = it.next();
8665 PendingIntentRecord rec = ref != null ? ref.get(): null;
8666 needSep = true;
8667 if (rec != null) {
8668 pw.print(" * "); pw.println(rec);
8669 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008670 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008671 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008672 } else {
8673 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008674 }
8675 }
8676 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008677
8678 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008679 }
8680
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008681 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8682 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008683 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008684 boolean needNL = false;
8685 final String innerPrefix = prefix + " ";
8686 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008687 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008688 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008689 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008690 if (needNL) {
8691 pw.println(" ");
8692 needNL = false;
8693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008694 if (lastTask != r.task) {
8695 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008696 pw.print(prefix);
8697 pw.print(full ? "* " : " ");
8698 pw.println(lastTask);
8699 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008700 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008701 } else if (complete) {
8702 // Complete + brief == give a summary. Isn't that obvious?!?
8703 if (lastTask.intent != null) {
8704 pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
8705 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008707 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008708 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8709 pw.print(" #"); pw.print(i); pw.print(": ");
8710 pw.println(r);
8711 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008712 r.dump(pw, innerPrefix);
8713 } else if (complete) {
8714 // Complete + brief == give a summary. Isn't that obvious?!?
8715 pw.print(innerPrefix); pw.println(r.intent);
8716 if (r.app != null) {
8717 pw.print(innerPrefix); pw.println(r.app);
8718 }
8719 }
8720 if (client && r.app != null && r.app.thread != null) {
8721 // flush anything that is already in the PrintWriter since the thread is going
8722 // to write to the file descriptor directly
8723 pw.flush();
8724 try {
8725 TransferPipe tp = new TransferPipe();
8726 try {
8727 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8728 innerPrefix, args);
8729 // Short timeout, since blocking here can
8730 // deadlock with the application.
8731 tp.go(fd, 2000);
8732 } finally {
8733 tp.kill();
8734 }
8735 } catch (IOException e) {
8736 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8737 } catch (RemoteException e) {
8738 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8739 }
8740 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008742 }
8743 }
8744
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008745 private static String buildOomTag(String prefix, String space, int val, int base) {
8746 if (val == base) {
8747 if (space == null) return prefix;
8748 return prefix + " ";
8749 }
8750 return prefix + "+" + Integer.toString(val-base);
8751 }
8752
8753 private static final int dumpProcessList(PrintWriter pw,
8754 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008755 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008756 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008757 final int N = list.size()-1;
8758 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008760 pw.println(String.format("%s%s #%2d: %s",
8761 prefix, (r.persistent ? persistentLabel : normalLabel),
8762 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008763 if (r.persistent) {
8764 numPers++;
8765 }
8766 }
8767 return numPers;
8768 }
8769
Dianne Hackborn287952c2010-09-22 22:34:31 -07008770 private static final void dumpProcessOomList(PrintWriter pw,
8771 ActivityManagerService service, List<ProcessRecord> list,
8772 String prefix, String normalLabel, String persistentLabel,
8773 boolean inclDetails) {
8774
8775 final long curRealtime = SystemClock.elapsedRealtime();
8776 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8777 final long curUptime = SystemClock.uptimeMillis();
8778 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8779
8780 final int N = list.size()-1;
8781 for (int i=N; i>=0; i--) {
8782 ProcessRecord r = list.get(i);
8783 String oomAdj;
8784 if (r.setAdj >= EMPTY_APP_ADJ) {
8785 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8786 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8787 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8788 } else if (r.setAdj >= HOME_APP_ADJ) {
8789 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8790 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8791 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8792 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8793 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8794 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8795 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8796 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8797 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8798 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8799 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8800 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8801 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8802 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8803 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8804 } else if (r.setAdj >= SYSTEM_ADJ) {
8805 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8806 } else {
8807 oomAdj = Integer.toString(r.setAdj);
8808 }
8809 String schedGroup;
8810 switch (r.setSchedGroup) {
8811 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8812 schedGroup = "B";
8813 break;
8814 case Process.THREAD_GROUP_DEFAULT:
8815 schedGroup = "F";
8816 break;
8817 default:
8818 schedGroup = Integer.toString(r.setSchedGroup);
8819 break;
8820 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008821 String foreground;
8822 if (r.foregroundActivities) {
8823 foreground = "A";
8824 } else if (r.foregroundServices) {
8825 foreground = "S";
8826 } else {
8827 foreground = " ";
8828 }
8829 pw.println(String.format("%s%s #%2d: adj=%s/%s%s %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008830 prefix, (r.persistent ? persistentLabel : normalLabel),
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008831 N-i, oomAdj, schedGroup, foreground, r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07008832 if (r.adjSource != null || r.adjTarget != null) {
8833 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008834 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008835 if (r.adjTarget instanceof ComponentName) {
8836 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8837 } else if (r.adjTarget != null) {
8838 pw.print(r.adjTarget.toString());
8839 } else {
8840 pw.print("{null}");
8841 }
8842 pw.print("<=");
8843 if (r.adjSource instanceof ProcessRecord) {
8844 pw.print("Proc{");
8845 pw.print(((ProcessRecord)r.adjSource).toShortString());
8846 pw.println("}");
8847 } else if (r.adjSource != null) {
8848 pw.println(r.adjSource.toString());
8849 } else {
8850 pw.println("{null}");
8851 }
8852 }
8853 if (inclDetails) {
8854 pw.print(prefix);
8855 pw.print(" ");
8856 pw.print("oom: max="); pw.print(r.maxAdj);
8857 pw.print(" hidden="); pw.print(r.hiddenAdj);
8858 pw.print(" curRaw="); pw.print(r.curRawAdj);
8859 pw.print(" setRaw="); pw.print(r.setRawAdj);
8860 pw.print(" cur="); pw.print(r.curAdj);
8861 pw.print(" set="); pw.println(r.setAdj);
8862 pw.print(prefix);
8863 pw.print(" ");
8864 pw.print("keeping="); pw.print(r.keeping);
8865 pw.print(" hidden="); pw.print(r.hidden);
8866 pw.print(" empty="); pw.println(r.empty);
8867
8868 if (!r.keeping) {
8869 if (r.lastWakeTime != 0) {
8870 long wtime;
8871 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8872 synchronized (stats) {
8873 wtime = stats.getProcessWakeTime(r.info.uid,
8874 r.pid, curRealtime);
8875 }
8876 long timeUsed = wtime - r.lastWakeTime;
8877 pw.print(prefix);
8878 pw.print(" ");
8879 pw.print("keep awake over ");
8880 TimeUtils.formatDuration(realtimeSince, pw);
8881 pw.print(" used ");
8882 TimeUtils.formatDuration(timeUsed, pw);
8883 pw.print(" (");
8884 pw.print((timeUsed*100)/realtimeSince);
8885 pw.println("%)");
8886 }
8887 if (r.lastCpuTime != 0) {
8888 long timeUsed = r.curCpuTime - r.lastCpuTime;
8889 pw.print(prefix);
8890 pw.print(" ");
8891 pw.print("run cpu over ");
8892 TimeUtils.formatDuration(uptimeSince, pw);
8893 pw.print(" used ");
8894 TimeUtils.formatDuration(timeUsed, pw);
8895 pw.print(" (");
8896 pw.print((timeUsed*100)/uptimeSince);
8897 pw.println("%)");
8898 }
8899 }
8900 }
8901 }
8902 }
8903
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008904 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
8905 ArrayList<ProcessRecord> procs;
8906 synchronized (this) {
8907 if (args != null && args.length > 0
8908 && args[0].charAt(0) != '-') {
8909 procs = new ArrayList<ProcessRecord>();
8910 int pid = -1;
8911 try {
8912 pid = Integer.parseInt(args[0]);
8913 } catch (NumberFormatException e) {
8914
8915 }
8916 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8917 ProcessRecord proc = mLruProcesses.get(i);
8918 if (proc.pid == pid) {
8919 procs.add(proc);
8920 } else if (proc.processName.equals(args[0])) {
8921 procs.add(proc);
8922 }
8923 }
8924 if (procs.size() <= 0) {
8925 pw.println("No process found for: " + args[0]);
8926 return null;
8927 }
8928 } else {
8929 procs = new ArrayList<ProcessRecord>(mLruProcesses);
8930 }
8931 }
8932 return procs;
8933 }
8934
8935 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
8936 PrintWriter pw, String[] args) {
8937 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8938 if (procs == null) {
8939 return;
8940 }
8941
8942 long uptime = SystemClock.uptimeMillis();
8943 long realtime = SystemClock.elapsedRealtime();
8944 pw.println("Applications Graphics Acceleration Info:");
8945 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8946
8947 String callArgs[] = {"graphics"};
8948 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8949 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008950 if (r.thread != null) {
8951 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
8952 pw.flush();
8953 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008954 TransferPipe.goDump(r.thread.asBinder(), fd, callArgs);
8955 } catch (IOException e) {
8956 pw.println("Failure: " + e);
8957 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07008958 } catch (RemoteException e) {
8959 pw.println("Got RemoteException!");
8960 pw.flush();
8961 }
8962 }
8963 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07008964 }
8965
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008966 final void dumpApplicationMemoryUsage(FileDescriptor fd,
8967 PrintWriter pw, String prefix, String[] args) {
8968 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8969 if (procs == null) {
8970 return;
8971 }
8972
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008973 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008974 long uptime = SystemClock.uptimeMillis();
8975 long realtime = SystemClock.elapsedRealtime();
8976
8977 if (isCheckinRequest) {
8978 // short checkin version
8979 pw.println(uptime + "," + realtime);
8980 pw.flush();
8981 } else {
8982 pw.println("Applications Memory Usage (kB):");
8983 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8984 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008985 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8986 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008987 if (r.thread != null) {
8988 if (!isCheckinRequest) {
8989 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8990 pw.flush();
8991 }
8992 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008993 TransferPipe.goDump(r.thread.asBinder(), fd, args);
8994 } catch (IOException e) {
8995 pw.println("Failure: " + e);
8996 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008997 } catch (RemoteException e) {
8998 if (!isCheckinRequest) {
8999 pw.println("Got RemoteException!");
9000 pw.flush();
9001 }
9002 }
9003 }
9004 }
9005 }
9006
9007 /**
9008 * Searches array of arguments for the specified string
9009 * @param args array of argument strings
9010 * @param value value to search for
9011 * @return true if the value is contained in the array
9012 */
9013 private static boolean scanArgs(String[] args, String value) {
9014 if (args != null) {
9015 for (String arg : args) {
9016 if (value.equals(arg)) {
9017 return true;
9018 }
9019 }
9020 }
9021 return false;
9022 }
9023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009024 private final void killServicesLocked(ProcessRecord app,
9025 boolean allowRestart) {
9026 // Report disconnected services.
9027 if (false) {
9028 // XXX we are letting the client link to the service for
9029 // death notifications.
9030 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009031 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009032 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009033 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009034 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009035 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009036 = r.connections.values().iterator();
9037 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009038 ArrayList<ConnectionRecord> cl = jt.next();
9039 for (int i=0; i<cl.size(); i++) {
9040 ConnectionRecord c = cl.get(i);
9041 if (c.binding.client != app) {
9042 try {
9043 //c.conn.connected(r.className, null);
9044 } catch (Exception e) {
9045 // todo: this should be asynchronous!
9046 Slog.w(TAG, "Exception thrown disconnected servce "
9047 + r.shortName
9048 + " from app " + app.processName, e);
9049 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009050 }
9051 }
9052 }
9053 }
9054 }
9055 }
9056 }
9057
9058 // Clean up any connections this application has to other services.
9059 if (app.connections.size() > 0) {
9060 Iterator<ConnectionRecord> it = app.connections.iterator();
9061 while (it.hasNext()) {
9062 ConnectionRecord r = it.next();
9063 removeConnectionLocked(r, app, null);
9064 }
9065 }
9066 app.connections.clear();
9067
9068 if (app.services.size() != 0) {
9069 // Any services running in the application need to be placed
9070 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009071 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009072 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009073 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009074 synchronized (sr.stats.getBatteryStats()) {
9075 sr.stats.stopLaunchedLocked();
9076 }
9077 sr.app = null;
9078 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009079 if (mStoppingServices.remove(sr)) {
9080 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
9081 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009082
9083 boolean hasClients = sr.bindings.size() > 0;
9084 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009085 Iterator<IntentBindRecord> bindings
9086 = sr.bindings.values().iterator();
9087 while (bindings.hasNext()) {
9088 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009089 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009090 + ": shouldUnbind=" + b.hasBound);
9091 b.binder = null;
9092 b.requested = b.received = b.hasBound = false;
9093 }
9094 }
9095
Dianne Hackborn070783f2010-12-29 16:46:28 -08009096 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
9097 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009098 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009099 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009100 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009101 sr.crashCount, sr.shortName, app.pid);
9102 bringDownServiceLocked(sr, true);
9103 } else if (!allowRestart) {
9104 bringDownServiceLocked(sr, true);
9105 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009106 boolean canceled = scheduleServiceRestartLocked(sr, true);
9107
9108 // Should the service remain running? Note that in the
9109 // extreme case of so many attempts to deliver a command
9110 // that it failed, that we also will stop it here.
9111 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
9112 if (sr.pendingStarts.size() == 0) {
9113 sr.startRequested = false;
9114 if (!hasClients) {
9115 // Whoops, no reason to restart!
9116 bringDownServiceLocked(sr, true);
9117 }
9118 }
9119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 }
9121 }
9122
9123 if (!allowRestart) {
9124 app.services.clear();
9125 }
9126 }
9127
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009128 // Make sure we have no more records on the stopping list.
9129 int i = mStoppingServices.size();
9130 while (i > 0) {
9131 i--;
9132 ServiceRecord sr = mStoppingServices.get(i);
9133 if (sr.app == app) {
9134 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009135 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009136 }
9137 }
9138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009139 app.executingServices.clear();
9140 }
9141
9142 private final void removeDyingProviderLocked(ProcessRecord proc,
9143 ContentProviderRecord cpr) {
9144 synchronized (cpr) {
9145 cpr.launchingApp = null;
9146 cpr.notifyAll();
9147 }
9148
9149 mProvidersByClass.remove(cpr.info.name);
9150 String names[] = cpr.info.authority.split(";");
9151 for (int j = 0; j < names.length; j++) {
9152 mProvidersByName.remove(names[j]);
9153 }
9154
9155 Iterator<ProcessRecord> cit = cpr.clients.iterator();
9156 while (cit.hasNext()) {
9157 ProcessRecord capp = cit.next();
9158 if (!capp.persistent && capp.thread != null
9159 && capp.pid != 0
9160 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009161 Slog.i(TAG, "Kill " + capp.processName
9162 + " (pid " + capp.pid + "): provider " + cpr.info.name
9163 + " in dying process " + proc.processName);
9164 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
9165 capp.processName, capp.setAdj, "dying provider " + proc.processName);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009166 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009167 }
9168 }
9169
9170 mLaunchingProviders.remove(cpr);
9171 }
9172
9173 /**
9174 * Main code for cleaning up a process when it has gone away. This is
9175 * called both as a result of the process dying, or directly when stopping
9176 * a process when running in single process mode.
9177 */
9178 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
9179 boolean restarting, int index) {
9180 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009181 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182 }
9183
Dianne Hackborn36124872009-10-08 16:22:03 -07009184 mProcessesToGc.remove(app);
9185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009186 // Dismiss any open dialogs.
9187 if (app.crashDialog != null) {
9188 app.crashDialog.dismiss();
9189 app.crashDialog = null;
9190 }
9191 if (app.anrDialog != null) {
9192 app.anrDialog.dismiss();
9193 app.anrDialog = null;
9194 }
9195 if (app.waitDialog != null) {
9196 app.waitDialog.dismiss();
9197 app.waitDialog = null;
9198 }
9199
9200 app.crashing = false;
9201 app.notResponding = false;
9202
9203 app.resetPackageList();
9204 app.thread = null;
9205 app.forcingToForeground = null;
9206 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009207 app.foregroundActivities = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009208
9209 killServicesLocked(app, true);
9210
9211 boolean restart = false;
9212
9213 int NL = mLaunchingProviders.size();
9214
9215 // Remove published content providers.
9216 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009217 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009218 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009219 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009220 cpr.provider = null;
9221 cpr.app = null;
9222
9223 // See if someone is waiting for this provider... in which
9224 // case we don't remove it, but just let it restart.
9225 int i = 0;
9226 if (!app.bad) {
9227 for (; i<NL; i++) {
9228 if (mLaunchingProviders.get(i) == cpr) {
9229 restart = true;
9230 break;
9231 }
9232 }
9233 } else {
9234 i = NL;
9235 }
9236
9237 if (i >= NL) {
9238 removeDyingProviderLocked(app, cpr);
9239 NL = mLaunchingProviders.size();
9240 }
9241 }
9242 app.pubProviders.clear();
9243 }
9244
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009245 // Take care of any launching providers waiting for this process.
9246 if (checkAppInLaunchingProvidersLocked(app, false)) {
9247 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009248 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 // Unregister from connected content providers.
9251 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009252 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009253 while (it.hasNext()) {
9254 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9255 cpr.clients.remove(app);
9256 }
9257 app.conProviders.clear();
9258 }
9259
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009260 // At this point there may be remaining entries in mLaunchingProviders
9261 // where we were the only one waiting, so they are no longer of use.
9262 // Look for these and clean up if found.
9263 // XXX Commented out for now. Trying to figure out a way to reproduce
9264 // the actual situation to identify what is actually going on.
9265 if (false) {
9266 for (int i=0; i<NL; i++) {
9267 ContentProviderRecord cpr = (ContentProviderRecord)
9268 mLaunchingProviders.get(i);
9269 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9270 synchronized (cpr) {
9271 cpr.launchingApp = null;
9272 cpr.notifyAll();
9273 }
9274 }
9275 }
9276 }
9277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009278 skipCurrentReceiverLocked(app);
9279
9280 // Unregister any receivers.
9281 if (app.receivers.size() > 0) {
9282 Iterator<ReceiverList> it = app.receivers.iterator();
9283 while (it.hasNext()) {
9284 removeReceiverLocked(it.next());
9285 }
9286 app.receivers.clear();
9287 }
9288
Christopher Tate181fafa2009-05-14 11:12:14 -07009289 // If the app is undergoing backup, tell the backup manager about it
9290 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009291 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009292 try {
9293 IBackupManager bm = IBackupManager.Stub.asInterface(
9294 ServiceManager.getService(Context.BACKUP_SERVICE));
9295 bm.agentDisconnected(app.info.packageName);
9296 } catch (RemoteException e) {
9297 // can't happen; backup manager is local
9298 }
9299 }
9300
Jeff Sharkey287bd832011-05-28 19:36:26 -07009301 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009303 // If the caller is restarting this app, then leave it in its
9304 // current lists and let the caller take care of it.
9305 if (restarting) {
9306 return;
9307 }
9308
9309 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009310 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009311 "Removing non-persistent process during cleanup: " + app);
9312 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009313 if (mHeavyWeightProcess == app) {
9314 mHeavyWeightProcess = null;
9315 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009317 } else if (!app.removed) {
9318 // This app is persistent, so we need to keep its record around.
9319 // If it is not already on the pending app list, add it there
9320 // and start a new process for it.
9321 app.thread = null;
9322 app.forcingToForeground = null;
9323 app.foregroundServices = false;
9324 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9325 mPersistentStartingProcesses.add(app);
9326 restart = true;
9327 }
9328 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009329 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9330 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009331 mProcessesOnHold.remove(app);
9332
The Android Open Source Project4df24232009-03-05 14:34:35 -08009333 if (app == mHomeProcess) {
9334 mHomeProcess = null;
9335 }
9336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009337 if (restart) {
9338 // We have components that still need to be running in the
9339 // process, so re-launch it.
9340 mProcessNames.put(app.processName, app.info.uid, app);
9341 startProcessLocked(app, "restart", app.processName);
9342 } else if (app.pid > 0 && app.pid != MY_PID) {
9343 // Goodbye!
9344 synchronized (mPidsSelfLocked) {
9345 mPidsSelfLocked.remove(app.pid);
9346 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9347 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009348 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009349 }
9350 }
9351
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009352 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9353 // Look through the content providers we are waiting to have launched,
9354 // and if any run in this process then either schedule a restart of
9355 // the process or kill the client waiting for it if this process has
9356 // gone bad.
9357 int NL = mLaunchingProviders.size();
9358 boolean restart = false;
9359 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009360 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009361 if (cpr.launchingApp == app) {
9362 if (!alwaysBad && !app.bad) {
9363 restart = true;
9364 } else {
9365 removeDyingProviderLocked(app, cpr);
9366 NL = mLaunchingProviders.size();
9367 }
9368 }
9369 }
9370 return restart;
9371 }
9372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009373 // =========================================================
9374 // SERVICES
9375 // =========================================================
9376
9377 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9378 ActivityManager.RunningServiceInfo info =
9379 new ActivityManager.RunningServiceInfo();
9380 info.service = r.name;
9381 if (r.app != null) {
9382 info.pid = r.app.pid;
9383 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009384 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009385 info.process = r.processName;
9386 info.foreground = r.isForeground;
9387 info.activeSince = r.createTime;
9388 info.started = r.startRequested;
9389 info.clientCount = r.connections.size();
9390 info.crashCount = r.crashCount;
9391 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009392 if (r.isForeground) {
9393 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9394 }
9395 if (r.startRequested) {
9396 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9397 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009398 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009399 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9400 }
9401 if (r.app != null && r.app.persistent) {
9402 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9403 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009404
9405 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9406 for (int i=0; i<connl.size(); i++) {
9407 ConnectionRecord conn = connl.get(i);
9408 if (conn.clientLabel != 0) {
9409 info.clientPackage = conn.binding.client.info.packageName;
9410 info.clientLabel = conn.clientLabel;
9411 return info;
9412 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009413 }
9414 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009415 return info;
9416 }
9417
9418 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9419 int flags) {
9420 synchronized (this) {
9421 ArrayList<ActivityManager.RunningServiceInfo> res
9422 = new ArrayList<ActivityManager.RunningServiceInfo>();
9423
9424 if (mServices.size() > 0) {
9425 Iterator<ServiceRecord> it = mServices.values().iterator();
9426 while (it.hasNext() && res.size() < maxNum) {
9427 res.add(makeRunningServiceInfoLocked(it.next()));
9428 }
9429 }
9430
9431 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9432 ServiceRecord r = mRestartingServices.get(i);
9433 ActivityManager.RunningServiceInfo info =
9434 makeRunningServiceInfoLocked(r);
9435 info.restarting = r.nextRestartTime;
9436 res.add(info);
9437 }
9438
9439 return res;
9440 }
9441 }
9442
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009443 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9444 synchronized (this) {
9445 ServiceRecord r = mServices.get(name);
9446 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009447 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9448 for (int i=0; i<conn.size(); i++) {
9449 if (conn.get(i).clientIntent != null) {
9450 return conn.get(i).clientIntent;
9451 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009452 }
9453 }
9454 }
9455 }
9456 return null;
9457 }
9458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009459 private final ServiceRecord findServiceLocked(ComponentName name,
9460 IBinder token) {
9461 ServiceRecord r = mServices.get(name);
9462 return r == token ? r : null;
9463 }
9464
9465 private final class ServiceLookupResult {
9466 final ServiceRecord record;
9467 final String permission;
9468
9469 ServiceLookupResult(ServiceRecord _record, String _permission) {
9470 record = _record;
9471 permission = _permission;
9472 }
9473 };
9474
9475 private ServiceLookupResult findServiceLocked(Intent service,
9476 String resolvedType) {
9477 ServiceRecord r = null;
9478 if (service.getComponent() != null) {
9479 r = mServices.get(service.getComponent());
9480 }
9481 if (r == null) {
9482 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9483 r = mServicesByIntent.get(filter);
9484 }
9485
9486 if (r == null) {
9487 try {
9488 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009489 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009490 service, resolvedType, 0);
9491 ServiceInfo sInfo =
9492 rInfo != null ? rInfo.serviceInfo : null;
9493 if (sInfo == null) {
9494 return null;
9495 }
9496
9497 ComponentName name = new ComponentName(
9498 sInfo.applicationInfo.packageName, sInfo.name);
9499 r = mServices.get(name);
9500 } catch (RemoteException ex) {
9501 // pm is in same process, this will never happen.
9502 }
9503 }
9504 if (r != null) {
9505 int callingPid = Binder.getCallingPid();
9506 int callingUid = Binder.getCallingUid();
9507 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009508 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009509 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009510 if (!r.exported) {
9511 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9512 + " from pid=" + callingPid
9513 + ", uid=" + callingUid
9514 + " that is not exported from uid " + r.appInfo.uid);
9515 return new ServiceLookupResult(null, "not exported from uid "
9516 + r.appInfo.uid);
9517 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009518 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009519 + " from pid=" + callingPid
9520 + ", uid=" + callingUid
9521 + " requires " + r.permission);
9522 return new ServiceLookupResult(null, r.permission);
9523 }
9524 return new ServiceLookupResult(r, null);
9525 }
9526 return null;
9527 }
9528
9529 private class ServiceRestarter implements Runnable {
9530 private ServiceRecord mService;
9531
9532 void setService(ServiceRecord service) {
9533 mService = service;
9534 }
9535
9536 public void run() {
9537 synchronized(ActivityManagerService.this) {
9538 performServiceRestartLocked(mService);
9539 }
9540 }
9541 }
9542
9543 private ServiceLookupResult retrieveServiceLocked(Intent service,
9544 String resolvedType, int callingPid, int callingUid) {
9545 ServiceRecord r = null;
9546 if (service.getComponent() != null) {
9547 r = mServices.get(service.getComponent());
9548 }
9549 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9550 r = mServicesByIntent.get(filter);
9551 if (r == null) {
9552 try {
9553 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009554 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009555 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009556 ServiceInfo sInfo =
9557 rInfo != null ? rInfo.serviceInfo : null;
9558 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009559 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009560 ": not found");
9561 return null;
9562 }
9563
9564 ComponentName name = new ComponentName(
9565 sInfo.applicationInfo.packageName, sInfo.name);
9566 r = mServices.get(name);
9567 if (r == null) {
9568 filter = new Intent.FilterComparison(service.cloneFilter());
9569 ServiceRestarter res = new ServiceRestarter();
9570 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9571 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9572 synchronized (stats) {
9573 ss = stats.getServiceStatsLocked(
9574 sInfo.applicationInfo.uid, sInfo.packageName,
9575 sInfo.name);
9576 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009577 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578 res.setService(r);
9579 mServices.put(name, r);
9580 mServicesByIntent.put(filter, r);
9581
9582 // Make sure this component isn't in the pending list.
9583 int N = mPendingServices.size();
9584 for (int i=0; i<N; i++) {
9585 ServiceRecord pr = mPendingServices.get(i);
9586 if (pr.name.equals(name)) {
9587 mPendingServices.remove(i);
9588 i--;
9589 N--;
9590 }
9591 }
9592 }
9593 } catch (RemoteException ex) {
9594 // pm is in same process, this will never happen.
9595 }
9596 }
9597 if (r != null) {
9598 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009599 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009600 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009601 if (!r.exported) {
9602 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9603 + " from pid=" + callingPid
9604 + ", uid=" + callingUid
9605 + " that is not exported from uid " + r.appInfo.uid);
9606 return new ServiceLookupResult(null, "not exported from uid "
9607 + r.appInfo.uid);
9608 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009609 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009610 + " from pid=" + callingPid
9611 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009612 + " requires " + r.permission);
9613 return new ServiceLookupResult(null, r.permission);
9614 }
9615 return new ServiceLookupResult(r, null);
9616 }
9617 return null;
9618 }
9619
Dianne Hackborn287952c2010-09-22 22:34:31 -07009620 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9621 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9622 + why + " of " + r + " in app " + r.app);
9623 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9624 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009625 long now = SystemClock.uptimeMillis();
9626 if (r.executeNesting == 0 && r.app != null) {
9627 if (r.app.executingServices.size() == 0) {
9628 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9629 msg.obj = r.app;
9630 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9631 }
9632 r.app.executingServices.add(r);
9633 }
9634 r.executeNesting++;
9635 r.executingStart = now;
9636 }
9637
9638 private final void sendServiceArgsLocked(ServiceRecord r,
9639 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009640 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009641 if (N == 0) {
9642 return;
9643 }
9644
Dianne Hackborn39792d22010-08-19 18:01:52 -07009645 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009646 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009647 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009648 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9649 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009650 if (si.intent == null && N > 1) {
9651 // If somehow we got a dummy null intent in the middle,
9652 // then skip it. DO NOT skip a null intent when it is
9653 // the only one in the list -- this is to support the
9654 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009655 continue;
9656 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009657 si.deliveredTime = SystemClock.uptimeMillis();
9658 r.deliveredStarts.add(si);
9659 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009660 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009661 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009662 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009663 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009664 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009665 if (!oomAdjusted) {
9666 oomAdjusted = true;
9667 updateOomAdjLocked(r.app);
9668 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009669 int flags = 0;
9670 if (si.deliveryCount > 0) {
9671 flags |= Service.START_FLAG_RETRY;
9672 }
9673 if (si.doneExecutingCount > 0) {
9674 flags |= Service.START_FLAG_REDELIVERY;
9675 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009676 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009677 } catch (RemoteException e) {
9678 // Remote process gone... we'll let the normal cleanup take
9679 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009680 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009681 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009682 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009683 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009684 break;
9685 }
9686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009687 }
9688
9689 private final boolean requestServiceBindingLocked(ServiceRecord r,
9690 IntentBindRecord i, boolean rebind) {
9691 if (r.app == null || r.app.thread == null) {
9692 // If service is not currently running, can't yet bind.
9693 return false;
9694 }
9695 if ((!i.requested || rebind) && i.apps.size() > 0) {
9696 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009697 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9699 if (!rebind) {
9700 i.requested = true;
9701 }
9702 i.hasBound = true;
9703 i.doRebind = false;
9704 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009705 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009706 return false;
9707 }
9708 }
9709 return true;
9710 }
9711
9712 private final void requestServiceBindingsLocked(ServiceRecord r) {
9713 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9714 while (bindings.hasNext()) {
9715 IntentBindRecord i = bindings.next();
9716 if (!requestServiceBindingLocked(r, i, false)) {
9717 break;
9718 }
9719 }
9720 }
9721
9722 private final void realStartServiceLocked(ServiceRecord r,
9723 ProcessRecord app) throws RemoteException {
9724 if (app.thread == null) {
9725 throw new RemoteException();
9726 }
9727
9728 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009729 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009730
9731 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009732 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009733 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009734
9735 boolean created = false;
9736 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009737 mStringBuilder.setLength(0);
9738 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009739 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009740 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009741 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009742 synchronized (r.stats.getBatteryStats()) {
9743 r.stats.startLaunchedLocked();
9744 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009745 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04009746 app.thread.scheduleCreateService(r, r.serviceInfo,
9747 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009748 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009749 created = true;
9750 } finally {
9751 if (!created) {
9752 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009753 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009754 }
9755 }
9756
9757 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009758
9759 // If the service is in the started state, and there are no
9760 // pending arguments, then fake up one so its onStartCommand() will
9761 // be called.
9762 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009763 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
9764 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009765 }
9766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009767 sendServiceArgsLocked(r, true);
9768 }
9769
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009770 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9771 boolean allowCancel) {
9772 boolean canceled = false;
9773
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009774 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009775 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009776 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009777
Dianne Hackborn070783f2010-12-29 16:46:28 -08009778 if ((r.serviceInfo.applicationInfo.flags
9779 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9780 minDuration /= 4;
9781 }
9782
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009783 // Any delivered but not yet finished starts should be put back
9784 // on the pending list.
9785 final int N = r.deliveredStarts.size();
9786 if (N > 0) {
9787 for (int i=N-1; i>=0; i--) {
9788 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009789 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009790 if (si.intent == null) {
9791 // We'll generate this again if needed.
9792 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9793 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9794 r.pendingStarts.add(0, si);
9795 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9796 dur *= 2;
9797 if (minDuration < dur) minDuration = dur;
9798 if (resetTime < dur) resetTime = dur;
9799 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009800 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009801 + r.name);
9802 canceled = true;
9803 }
9804 }
9805 r.deliveredStarts.clear();
9806 }
9807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009808 r.totalRestartCount++;
9809 if (r.restartDelay == 0) {
9810 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009811 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009812 } else {
9813 // If it has been a "reasonably long time" since the service
9814 // was started, then reset our restart duration back to
9815 // the beginning, so we don't infinitely increase the duration
9816 // on a service that just occasionally gets killed (which is
9817 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009818 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009819 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009820 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009822 if ((r.serviceInfo.applicationInfo.flags
9823 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9824 // Services in peristent processes will restart much more
9825 // quickly, since they are pretty important. (Think SystemUI).
9826 r.restartDelay += minDuration/2;
9827 } else {
9828 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9829 if (r.restartDelay < minDuration) {
9830 r.restartDelay = minDuration;
9831 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833 }
9834 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009835
9836 r.nextRestartTime = now + r.restartDelay;
9837
9838 // Make sure that we don't end up restarting a bunch of services
9839 // all at the same time.
9840 boolean repeat;
9841 do {
9842 repeat = false;
9843 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9844 ServiceRecord r2 = mRestartingServices.get(i);
9845 if (r2 != r && r.nextRestartTime
9846 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9847 && r.nextRestartTime
9848 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9849 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9850 r.restartDelay = r.nextRestartTime - now;
9851 repeat = true;
9852 break;
9853 }
9854 }
9855 } while (repeat);
9856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009857 if (!mRestartingServices.contains(r)) {
9858 mRestartingServices.add(r);
9859 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009860
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009861 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009863 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009864 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009866 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009867 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009868 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009869 r.shortName, r.restartDelay);
9870
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009871 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009872 }
9873
9874 final void performServiceRestartLocked(ServiceRecord r) {
9875 if (!mRestartingServices.contains(r)) {
9876 return;
9877 }
9878 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9879 }
9880
9881 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9882 if (r.restartDelay == 0) {
9883 return false;
9884 }
9885 r.resetRestartCounter();
9886 mRestartingServices.remove(r);
9887 mHandler.removeCallbacks(r.restarter);
9888 return true;
9889 }
9890
9891 private final boolean bringUpServiceLocked(ServiceRecord r,
9892 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009893 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009894 //r.dump(" ");
9895
Dianne Hackborn36124872009-10-08 16:22:03 -07009896 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009897 sendServiceArgsLocked(r, false);
9898 return true;
9899 }
9900
9901 if (!whileRestarting && r.restartDelay > 0) {
9902 // If waiting for a restart, then do nothing.
9903 return true;
9904 }
9905
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009906 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009907
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009908 // We are now bringing the service up, so no longer in the
9909 // restarting state.
9910 mRestartingServices.remove(r);
9911
Dianne Hackborne7f97212011-02-24 14:40:20 -08009912 // Service is now being launched, its package can't be stopped.
9913 try {
9914 AppGlobals.getPackageManager().setPackageStoppedState(
9915 r.packageName, false);
9916 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009917 } catch (IllegalArgumentException e) {
9918 Slog.w(TAG, "Failed trying to unstop package "
9919 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009920 }
9921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 final String appName = r.processName;
9923 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9924 if (app != null && app.thread != null) {
9925 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -07009926 app.addPackage(r.appInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009927 realStartServiceLocked(r, app);
9928 return true;
9929 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009930 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009931 }
9932
9933 // If a dead object exception was thrown -- fall through to
9934 // restart the application.
9935 }
9936
Dianne Hackborn36124872009-10-08 16:22:03 -07009937 // Not running -- get it started, and enqueue this service record
9938 // to be executed when the app comes up.
9939 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9940 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009941 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009942 + r.appInfo.packageName + "/"
9943 + r.appInfo.uid + " for service "
9944 + r.intent.getIntent() + ": process is bad");
9945 bringDownServiceLocked(r, true);
9946 return false;
9947 }
9948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009949 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009950 mPendingServices.add(r);
9951 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009953 return true;
9954 }
9955
9956 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009957 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009958 //r.dump(" ");
9959
9960 // Does it still need to run?
9961 if (!force && r.startRequested) {
9962 return;
9963 }
9964 if (r.connections.size() > 0) {
9965 if (!force) {
9966 // XXX should probably keep a count of the number of auto-create
9967 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009968 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009969 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009970 ArrayList<ConnectionRecord> cr = it.next();
9971 for (int i=0; i<cr.size(); i++) {
9972 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9973 return;
9974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009975 }
9976 }
9977 }
9978
9979 // Report to all of the connections that the service is no longer
9980 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009981 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009982 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009983 ArrayList<ConnectionRecord> c = it.next();
9984 for (int i=0; i<c.size(); i++) {
9985 try {
9986 c.get(i).conn.connected(r.name, null);
9987 } catch (Exception e) {
9988 Slog.w(TAG, "Failure disconnecting service " + r.name +
9989 " to connection " + c.get(i).conn.asBinder() +
9990 " (in " + c.get(i).binding.client.processName + ")", e);
9991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009992 }
9993 }
9994 }
9995
9996 // Tell the service that it has been unbound.
9997 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9998 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9999 while (it.hasNext()) {
10000 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010001 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010002 + ": hasBound=" + ibr.hasBound);
10003 if (r.app != null && r.app.thread != null && ibr.hasBound) {
10004 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010005 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 updateOomAdjLocked(r.app);
10007 ibr.hasBound = false;
10008 r.app.thread.scheduleUnbindService(r,
10009 ibr.intent.getIntent());
10010 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010011 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010012 + r.shortName, e);
10013 serviceDoneExecutingLocked(r, true);
10014 }
10015 }
10016 }
10017 }
10018
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010019 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010020 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010021 System.identityHashCode(r), r.shortName,
10022 (r.app != null) ? r.app.pid : -1);
10023
10024 mServices.remove(r.name);
10025 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010026 r.totalRestartCount = 0;
10027 unscheduleServiceRestartLocked(r);
10028
10029 // Also make sure it is not on the pending list.
10030 int N = mPendingServices.size();
10031 for (int i=0; i<N; i++) {
10032 if (mPendingServices.get(i) == r) {
10033 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010034 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010035 i--;
10036 N--;
10037 }
10038 }
10039
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010040 r.cancelNotification();
10041 r.isForeground = false;
10042 r.foregroundId = 0;
10043 r.foregroundNoti = null;
10044
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010045 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070010046 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010047 r.pendingStarts.clear();
10048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010049 if (r.app != null) {
10050 synchronized (r.stats.getBatteryStats()) {
10051 r.stats.stopLaunchedLocked();
10052 }
10053 r.app.services.remove(r);
10054 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010055 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010056 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010057 mStoppingServices.add(r);
10058 updateOomAdjLocked(r.app);
10059 r.app.thread.scheduleStopService(r);
10060 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010061 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010062 + r.shortName, e);
10063 serviceDoneExecutingLocked(r, true);
10064 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010065 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010067 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010068 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010069 }
10070 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010071 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010072 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010073 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080010074
10075 if (r.bindings.size() > 0) {
10076 r.bindings.clear();
10077 }
10078
10079 if (r.restarter instanceof ServiceRestarter) {
10080 ((ServiceRestarter)r.restarter).setService(null);
10081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010082 }
10083
10084 ComponentName startServiceLocked(IApplicationThread caller,
10085 Intent service, String resolvedType,
10086 int callingPid, int callingUid) {
10087 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010088 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010089 + " type=" + resolvedType + " args=" + service.getExtras());
10090
10091 if (caller != null) {
10092 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10093 if (callerApp == null) {
10094 throw new SecurityException(
10095 "Unable to find app for caller " + caller
10096 + " (pid=" + Binder.getCallingPid()
10097 + ") when starting service " + service);
10098 }
10099 }
10100
10101 ServiceLookupResult res =
10102 retrieveServiceLocked(service, resolvedType,
10103 callingPid, callingUid);
10104 if (res == null) {
10105 return null;
10106 }
10107 if (res.record == null) {
10108 return new ComponentName("!", res.permission != null
10109 ? res.permission : "private to package");
10110 }
10111 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070010112 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
10113 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010115 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010116 }
10117 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010118 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010119 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070010120 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010121 r.lastActivity = SystemClock.uptimeMillis();
10122 synchronized (r.stats.getBatteryStats()) {
10123 r.stats.startRunningLocked();
10124 }
10125 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
10126 return new ComponentName("!", "Service process is bad");
10127 }
10128 return r.name;
10129 }
10130 }
10131
10132 public ComponentName startService(IApplicationThread caller, Intent service,
10133 String resolvedType) {
10134 // Refuse possible leaked file descriptors
10135 if (service != null && service.hasFileDescriptors() == true) {
10136 throw new IllegalArgumentException("File descriptors passed in Intent");
10137 }
10138
10139 synchronized(this) {
10140 final int callingPid = Binder.getCallingPid();
10141 final int callingUid = Binder.getCallingUid();
10142 final long origId = Binder.clearCallingIdentity();
10143 ComponentName res = startServiceLocked(caller, service,
10144 resolvedType, callingPid, callingUid);
10145 Binder.restoreCallingIdentity(origId);
10146 return res;
10147 }
10148 }
10149
10150 ComponentName startServiceInPackage(int uid,
10151 Intent service, String resolvedType) {
10152 synchronized(this) {
10153 final long origId = Binder.clearCallingIdentity();
10154 ComponentName res = startServiceLocked(null, service,
10155 resolvedType, -1, uid);
10156 Binder.restoreCallingIdentity(origId);
10157 return res;
10158 }
10159 }
10160
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010161 private void stopServiceLocked(ServiceRecord service) {
10162 synchronized (service.stats.getBatteryStats()) {
10163 service.stats.stopRunningLocked();
10164 }
10165 service.startRequested = false;
10166 service.callStart = false;
10167 bringDownServiceLocked(service, false);
10168 }
10169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010170 public int stopService(IApplicationThread caller, Intent service,
10171 String resolvedType) {
10172 // Refuse possible leaked file descriptors
10173 if (service != null && service.hasFileDescriptors() == true) {
10174 throw new IllegalArgumentException("File descriptors passed in Intent");
10175 }
10176
10177 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010178 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010179 + " type=" + resolvedType);
10180
10181 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10182 if (caller != null && callerApp == null) {
10183 throw new SecurityException(
10184 "Unable to find app for caller " + caller
10185 + " (pid=" + Binder.getCallingPid()
10186 + ") when stopping service " + service);
10187 }
10188
10189 // If this service is active, make sure it is stopped.
10190 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10191 if (r != null) {
10192 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010193 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010194 try {
10195 stopServiceLocked(r.record);
10196 } finally {
10197 Binder.restoreCallingIdentity(origId);
10198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010199 return 1;
10200 }
10201 return -1;
10202 }
10203 }
10204
10205 return 0;
10206 }
10207
10208 public IBinder peekService(Intent service, String resolvedType) {
10209 // Refuse possible leaked file descriptors
10210 if (service != null && service.hasFileDescriptors() == true) {
10211 throw new IllegalArgumentException("File descriptors passed in Intent");
10212 }
10213
10214 IBinder ret = null;
10215
10216 synchronized(this) {
10217 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10218
10219 if (r != null) {
10220 // r.record is null if findServiceLocked() failed the caller permission check
10221 if (r.record == null) {
10222 throw new SecurityException(
10223 "Permission Denial: Accessing service " + r.record.name
10224 + " from pid=" + Binder.getCallingPid()
10225 + ", uid=" + Binder.getCallingUid()
10226 + " requires " + r.permission);
10227 }
10228 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10229 if (ib != null) {
10230 ret = ib.binder;
10231 }
10232 }
10233 }
10234
10235 return ret;
10236 }
10237
10238 public boolean stopServiceToken(ComponentName className, IBinder token,
10239 int startId) {
10240 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010241 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 + " " + token + " startId=" + startId);
10243 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010244 if (r != null) {
10245 if (startId >= 0) {
10246 // Asked to only stop if done with all work. Note that
10247 // to avoid leaks, we will take this as dropping all
10248 // start items up to and including this one.
10249 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10250 if (si != null) {
10251 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010252 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10253 cur.removeUriPermissionsLocked();
10254 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010255 break;
10256 }
10257 }
10258 }
10259
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010260 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010261 return false;
10262 }
10263
10264 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010265 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010266 + " is last, but have " + r.deliveredStarts.size()
10267 + " remaining args");
10268 }
10269 }
10270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010271 synchronized (r.stats.getBatteryStats()) {
10272 r.stats.stopRunningLocked();
10273 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010274 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010275 }
10276 final long origId = Binder.clearCallingIdentity();
10277 bringDownServiceLocked(r, false);
10278 Binder.restoreCallingIdentity(origId);
10279 return true;
10280 }
10281 }
10282 return false;
10283 }
10284
10285 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010286 int id, Notification notification, boolean removeNotification) {
10287 final long origId = Binder.clearCallingIdentity();
10288 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010289 synchronized(this) {
10290 ServiceRecord r = findServiceLocked(className, token);
10291 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010292 if (id != 0) {
10293 if (notification == null) {
10294 throw new IllegalArgumentException("null notification");
10295 }
10296 if (r.foregroundId != id) {
10297 r.cancelNotification();
10298 r.foregroundId = id;
10299 }
10300 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10301 r.foregroundNoti = notification;
10302 r.isForeground = true;
10303 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010304 if (r.app != null) {
10305 updateServiceForegroundLocked(r.app, true);
10306 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010307 } else {
10308 if (r.isForeground) {
10309 r.isForeground = false;
10310 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010311 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010312 updateServiceForegroundLocked(r.app, true);
10313 }
10314 }
10315 if (removeNotification) {
10316 r.cancelNotification();
10317 r.foregroundId = 0;
10318 r.foregroundNoti = null;
10319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010320 }
10321 }
10322 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010323 } finally {
10324 Binder.restoreCallingIdentity(origId);
10325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010326 }
10327
10328 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10329 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010330 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010331 if (sr.isForeground) {
10332 anyForeground = true;
10333 break;
10334 }
10335 }
10336 if (anyForeground != proc.foregroundServices) {
10337 proc.foregroundServices = anyForeground;
10338 if (oomAdj) {
10339 updateOomAdjLocked();
10340 }
10341 }
10342 }
10343
10344 public int bindService(IApplicationThread caller, IBinder token,
10345 Intent service, String resolvedType,
10346 IServiceConnection connection, int flags) {
10347 // Refuse possible leaked file descriptors
10348 if (service != null && service.hasFileDescriptors() == true) {
10349 throw new IllegalArgumentException("File descriptors passed in Intent");
10350 }
10351
10352 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010353 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 + " type=" + resolvedType + " conn=" + connection.asBinder()
10355 + " flags=0x" + Integer.toHexString(flags));
10356 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10357 if (callerApp == null) {
10358 throw new SecurityException(
10359 "Unable to find app for caller " + caller
10360 + " (pid=" + Binder.getCallingPid()
10361 + ") when binding service " + service);
10362 }
10363
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010364 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010365 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010366 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010368 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010369 return 0;
10370 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010371 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010372 }
10373
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010374 int clientLabel = 0;
10375 PendingIntent clientIntent = null;
10376
10377 if (callerApp.info.uid == Process.SYSTEM_UID) {
10378 // Hacky kind of thing -- allow system stuff to tell us
10379 // what they are, so we can report this elsewhere for
10380 // others to know why certain services are running.
10381 try {
10382 clientIntent = (PendingIntent)service.getParcelableExtra(
10383 Intent.EXTRA_CLIENT_INTENT);
10384 } catch (RuntimeException e) {
10385 }
10386 if (clientIntent != null) {
10387 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10388 if (clientLabel != 0) {
10389 // There are no useful extras in the intent, trash them.
10390 // System code calling with this stuff just needs to know
10391 // this will happen.
10392 service = service.cloneFilter();
10393 }
10394 }
10395 }
10396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010397 ServiceLookupResult res =
10398 retrieveServiceLocked(service, resolvedType,
10399 Binder.getCallingPid(), Binder.getCallingUid());
10400 if (res == null) {
10401 return 0;
10402 }
10403 if (res.record == null) {
10404 return -1;
10405 }
10406 ServiceRecord s = res.record;
10407
10408 final long origId = Binder.clearCallingIdentity();
10409
10410 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010411 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010412 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010413 }
10414
10415 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10416 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010417 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010418
10419 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010420 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10421 if (clist == null) {
10422 clist = new ArrayList<ConnectionRecord>();
10423 s.connections.put(binder, clist);
10424 }
10425 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010426 b.connections.add(c);
10427 if (activity != null) {
10428 if (activity.connections == null) {
10429 activity.connections = new HashSet<ConnectionRecord>();
10430 }
10431 activity.connections.add(c);
10432 }
10433 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010434 clist = mServiceConnections.get(binder);
10435 if (clist == null) {
10436 clist = new ArrayList<ConnectionRecord>();
10437 mServiceConnections.put(binder, clist);
10438 }
10439 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010440
10441 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10442 s.lastActivity = SystemClock.uptimeMillis();
10443 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10444 return 0;
10445 }
10446 }
10447
10448 if (s.app != null) {
10449 // This could have made the service more important.
10450 updateOomAdjLocked(s.app);
10451 }
10452
Joe Onorato8a9b2202010-02-26 18:56:32 -080010453 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010454 + ": received=" + b.intent.received
10455 + " apps=" + b.intent.apps.size()
10456 + " doRebind=" + b.intent.doRebind);
10457
10458 if (s.app != null && b.intent.received) {
10459 // Service is already running, so we can immediately
10460 // publish the connection.
10461 try {
10462 c.conn.connected(s.name, b.intent.binder);
10463 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010464 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010465 + " to connection " + c.conn.asBinder()
10466 + " (in " + c.binding.client.processName + ")", e);
10467 }
10468
10469 // If this is the first app connected back to this binding,
10470 // and the service had previously asked to be told when
10471 // rebound, then do so.
10472 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10473 requestServiceBindingLocked(s, b.intent, true);
10474 }
10475 } else if (!b.intent.requested) {
10476 requestServiceBindingLocked(s, b.intent, false);
10477 }
10478
10479 Binder.restoreCallingIdentity(origId);
10480 }
10481
10482 return 1;
10483 }
10484
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010485 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010486 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010487 IBinder binder = c.conn.asBinder();
10488 AppBindRecord b = c.binding;
10489 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010490 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10491 if (clist != null) {
10492 clist.remove(c);
10493 if (clist.size() == 0) {
10494 s.connections.remove(binder);
10495 }
10496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010497 b.connections.remove(c);
10498 if (c.activity != null && c.activity != skipAct) {
10499 if (c.activity.connections != null) {
10500 c.activity.connections.remove(c);
10501 }
10502 }
10503 if (b.client != skipApp) {
10504 b.client.connections.remove(c);
10505 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010506 clist = mServiceConnections.get(binder);
10507 if (clist != null) {
10508 clist.remove(c);
10509 if (clist.size() == 0) {
10510 mServiceConnections.remove(binder);
10511 }
10512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010513
10514 if (b.connections.size() == 0) {
10515 b.intent.apps.remove(b.client);
10516 }
10517
Joe Onorato8a9b2202010-02-26 18:56:32 -080010518 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010519 + ": shouldUnbind=" + b.intent.hasBound);
10520 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10521 && b.intent.hasBound) {
10522 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010523 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010524 updateOomAdjLocked(s.app);
10525 b.intent.hasBound = false;
10526 // Assume the client doesn't want to know about a rebind;
10527 // we will deal with that later if it asks for one.
10528 b.intent.doRebind = false;
10529 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10530 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010531 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010532 serviceDoneExecutingLocked(s, true);
10533 }
10534 }
10535
10536 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10537 bringDownServiceLocked(s, false);
10538 }
10539 }
10540
10541 public boolean unbindService(IServiceConnection connection) {
10542 synchronized (this) {
10543 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010544 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010545 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10546 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010547 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 + connection.asBinder());
10549 return false;
10550 }
10551
10552 final long origId = Binder.clearCallingIdentity();
10553
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010554 while (clist.size() > 0) {
10555 ConnectionRecord r = clist.get(0);
10556 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010557
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010558 if (r.binding.service.app != null) {
10559 // This could have made the service less important.
10560 updateOomAdjLocked(r.binding.service.app);
10561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010562 }
10563
10564 Binder.restoreCallingIdentity(origId);
10565 }
10566
10567 return true;
10568 }
10569
10570 public void publishService(IBinder token, Intent intent, IBinder service) {
10571 // Refuse possible leaked file descriptors
10572 if (intent != null && intent.hasFileDescriptors() == true) {
10573 throw new IllegalArgumentException("File descriptors passed in Intent");
10574 }
10575
10576 synchronized(this) {
10577 if (!(token instanceof ServiceRecord)) {
10578 throw new IllegalArgumentException("Invalid service token");
10579 }
10580 ServiceRecord r = (ServiceRecord)token;
10581
10582 final long origId = Binder.clearCallingIdentity();
10583
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010584 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 + " " + intent + ": " + service);
10586 if (r != null) {
10587 Intent.FilterComparison filter
10588 = new Intent.FilterComparison(intent);
10589 IntentBindRecord b = r.bindings.get(filter);
10590 if (b != null && !b.received) {
10591 b.binder = service;
10592 b.requested = true;
10593 b.received = true;
10594 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010595 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010596 = r.connections.values().iterator();
10597 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010598 ArrayList<ConnectionRecord> clist = it.next();
10599 for (int i=0; i<clist.size(); i++) {
10600 ConnectionRecord c = clist.get(i);
10601 if (!filter.equals(c.binding.intent.intent)) {
10602 if (DEBUG_SERVICE) Slog.v(
10603 TAG, "Not publishing to: " + c);
10604 if (DEBUG_SERVICE) Slog.v(
10605 TAG, "Bound intent: " + c.binding.intent.intent);
10606 if (DEBUG_SERVICE) Slog.v(
10607 TAG, "Published intent: " + intent);
10608 continue;
10609 }
10610 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10611 try {
10612 c.conn.connected(r.name, service);
10613 } catch (Exception e) {
10614 Slog.w(TAG, "Failure sending service " + r.name +
10615 " to connection " + c.conn.asBinder() +
10616 " (in " + c.binding.client.processName + ")", e);
10617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010618 }
10619 }
10620 }
10621 }
10622
10623 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10624
10625 Binder.restoreCallingIdentity(origId);
10626 }
10627 }
10628 }
10629
10630 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10631 // Refuse possible leaked file descriptors
10632 if (intent != null && intent.hasFileDescriptors() == true) {
10633 throw new IllegalArgumentException("File descriptors passed in Intent");
10634 }
10635
10636 synchronized(this) {
10637 if (!(token instanceof ServiceRecord)) {
10638 throw new IllegalArgumentException("Invalid service token");
10639 }
10640 ServiceRecord r = (ServiceRecord)token;
10641
10642 final long origId = Binder.clearCallingIdentity();
10643
10644 if (r != null) {
10645 Intent.FilterComparison filter
10646 = new Intent.FilterComparison(intent);
10647 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010648 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010649 + " at " + b + ": apps="
10650 + (b != null ? b.apps.size() : 0));
10651 if (b != null) {
10652 if (b.apps.size() > 0) {
10653 // Applications have already bound since the last
10654 // unbind, so just rebind right here.
10655 requestServiceBindingLocked(r, b, true);
10656 } else {
10657 // Note to tell the service the next time there is
10658 // a new client.
10659 b.doRebind = true;
10660 }
10661 }
10662
10663 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10664
10665 Binder.restoreCallingIdentity(origId);
10666 }
10667 }
10668 }
10669
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010670 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010671 synchronized(this) {
10672 if (!(token instanceof ServiceRecord)) {
10673 throw new IllegalArgumentException("Invalid service token");
10674 }
10675 ServiceRecord r = (ServiceRecord)token;
10676 boolean inStopping = mStoppingServices.contains(token);
10677 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010678 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010679 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010680 + " with incorrect token: given " + token
10681 + ", expected " + r);
10682 return;
10683 }
10684
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010685 if (type == 1) {
10686 // This is a call from a service start... take care of
10687 // book-keeping.
10688 r.callStart = true;
10689 switch (res) {
10690 case Service.START_STICKY_COMPATIBILITY:
10691 case Service.START_STICKY: {
10692 // We are done with the associated start arguments.
10693 r.findDeliveredStart(startId, true);
10694 // Don't stop if killed.
10695 r.stopIfKilled = false;
10696 break;
10697 }
10698 case Service.START_NOT_STICKY: {
10699 // We are done with the associated start arguments.
10700 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010701 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010702 // There is no more work, and this service
10703 // doesn't want to hang around if killed.
10704 r.stopIfKilled = true;
10705 }
10706 break;
10707 }
10708 case Service.START_REDELIVER_INTENT: {
10709 // We'll keep this item until they explicitly
10710 // call stop for it, but keep track of the fact
10711 // that it was delivered.
10712 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10713 if (si != null) {
10714 si.deliveryCount = 0;
10715 si.doneExecutingCount++;
10716 // Don't stop if killed.
10717 r.stopIfKilled = true;
10718 }
10719 break;
10720 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010721 case Service.START_TASK_REMOVED_COMPLETE: {
10722 // Special processing for onTaskRemoved(). Don't
10723 // impact normal onStartCommand() processing.
10724 r.findDeliveredStart(startId, true);
10725 break;
10726 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010727 default:
10728 throw new IllegalArgumentException(
10729 "Unknown service start result: " + res);
10730 }
10731 if (res == Service.START_STICKY_COMPATIBILITY) {
10732 r.callStart = false;
10733 }
10734 }
10735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010736 final long origId = Binder.clearCallingIdentity();
10737 serviceDoneExecutingLocked(r, inStopping);
10738 Binder.restoreCallingIdentity(origId);
10739 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010740 Slog.w(TAG, "Done executing unknown service from pid "
10741 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010742 }
10743 }
10744 }
10745
10746 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010747 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10748 + ": nesting=" + r.executeNesting
10749 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010750 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010751 r.executeNesting--;
10752 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010753 if (DEBUG_SERVICE) Slog.v(TAG,
10754 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010755 r.app.executingServices.remove(r);
10756 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010757 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10758 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010759 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10760 }
10761 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010762 if (DEBUG_SERVICE) Slog.v(TAG,
10763 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010764 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010765 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010766 }
10767 updateOomAdjLocked(r.app);
10768 }
10769 }
10770
10771 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010772 String anrMessage = null;
10773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010774 synchronized(this) {
10775 if (proc.executingServices.size() == 0 || proc.thread == null) {
10776 return;
10777 }
10778 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10779 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10780 ServiceRecord timeout = null;
10781 long nextTime = 0;
10782 while (it.hasNext()) {
10783 ServiceRecord sr = it.next();
10784 if (sr.executingStart < maxTime) {
10785 timeout = sr;
10786 break;
10787 }
10788 if (sr.executingStart > nextTime) {
10789 nextTime = sr.executingStart;
10790 }
10791 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010792 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010793 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010794 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010795 } else {
10796 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10797 msg.obj = proc;
10798 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10799 }
10800 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010801
10802 if (anrMessage != null) {
10803 appNotResponding(proc, null, null, anrMessage);
10804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 }
10806
10807 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010808 // BACKUP AND RESTORE
10809 // =========================================================
10810
10811 // Cause the target app to be launched if necessary and its backup agent
10812 // instantiated. The backup agent will invoke backupAgentCreated() on the
10813 // activity manager to announce its creation.
10814 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010815 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010816 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10817
10818 synchronized(this) {
10819 // !!! TODO: currently no check here that we're already bound
10820 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10821 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10822 synchronized (stats) {
10823 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10824 }
10825
Dianne Hackborne7f97212011-02-24 14:40:20 -080010826 // Backup agent is now in use, its package can't be stopped.
10827 try {
10828 AppGlobals.getPackageManager().setPackageStoppedState(
10829 app.packageName, false);
10830 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010831 } catch (IllegalArgumentException e) {
10832 Slog.w(TAG, "Failed trying to unstop package "
10833 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010834 }
10835
Christopher Tate181fafa2009-05-14 11:12:14 -070010836 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070010837 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
10838 ? new ComponentName(app.packageName, app.backupAgentName)
10839 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070010840 // startProcessLocked() returns existing proc's record if it's already running
10841 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010842 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010843 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010844 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010845 return false;
10846 }
10847
10848 r.app = proc;
10849 mBackupTarget = r;
10850 mBackupAppName = app.packageName;
10851
Christopher Tate6fa95972009-06-05 18:43:55 -070010852 // Try not to kill the process during backup
10853 updateOomAdjLocked(proc);
10854
Christopher Tate181fafa2009-05-14 11:12:14 -070010855 // If the process is already attached, schedule the creation of the backup agent now.
10856 // If it is not yet live, this will be done when it attaches to the framework.
10857 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010858 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010859 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010860 proc.thread.scheduleCreateBackupAgent(app,
10861 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010862 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010863 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010864 }
10865 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010866 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010867 }
10868 // Invariants: at this point, the target app process exists and the application
10869 // is either already running or in the process of coming up. mBackupTarget and
10870 // mBackupAppName describe the app, so that when it binds back to the AM we
10871 // know that it's scheduled for a backup-agent operation.
10872 }
10873
10874 return true;
10875 }
10876
10877 // A backup agent has just come up
10878 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010879 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010880 + " = " + agent);
10881
10882 synchronized(this) {
10883 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010884 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010885 return;
10886 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010887 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010888
Dianne Hackborn06740692010-09-22 22:46:21 -070010889 long oldIdent = Binder.clearCallingIdentity();
10890 try {
10891 IBackupManager bm = IBackupManager.Stub.asInterface(
10892 ServiceManager.getService(Context.BACKUP_SERVICE));
10893 bm.agentConnected(agentPackageName, agent);
10894 } catch (RemoteException e) {
10895 // can't happen; the backup manager service is local
10896 } catch (Exception e) {
10897 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10898 e.printStackTrace();
10899 } finally {
10900 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010901 }
10902 }
10903
10904 // done with this agent
10905 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010906 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010907 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010908 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010909 return;
10910 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010911
10912 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010913 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010914 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010915 return;
10916 }
10917
Christopher Tate181fafa2009-05-14 11:12:14 -070010918 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010919 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010920 return;
10921 }
10922
Christopher Tate6fa95972009-06-05 18:43:55 -070010923 ProcessRecord proc = mBackupTarget.app;
10924 mBackupTarget = null;
10925 mBackupAppName = null;
10926
10927 // Not backing this app up any more; reset its OOM adjustment
10928 updateOomAdjLocked(proc);
10929
Christopher Tatec7b31e32009-06-10 15:49:30 -070010930 // If the app crashed during backup, 'thread' will be null here
10931 if (proc.thread != null) {
10932 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010933 proc.thread.scheduleDestroyBackupAgent(appInfo,
10934 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070010935 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010936 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010937 e.printStackTrace();
10938 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010939 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010940 }
10941 }
10942 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010943 // BROADCASTS
10944 // =========================================================
10945
Josh Bartel7f208742010-02-25 11:01:44 -060010946 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010947 List cur) {
10948 final ContentResolver resolver = mContext.getContentResolver();
10949 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10950 if (list == null) {
10951 return cur;
10952 }
10953 int N = list.size();
10954 for (int i=0; i<N; i++) {
10955 Intent intent = list.get(i);
10956 if (filter.match(resolver, intent, true, TAG) >= 0) {
10957 if (cur == null) {
10958 cur = new ArrayList<Intent>();
10959 }
10960 cur.add(intent);
10961 }
10962 }
10963 return cur;
10964 }
10965
10966 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010967 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010968 + mBroadcastsScheduled);
10969
10970 if (mBroadcastsScheduled) {
10971 return;
10972 }
10973 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10974 mBroadcastsScheduled = true;
10975 }
10976
Dianne Hackborn6c418d52011-06-29 14:05:33 -070010977 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010978 IIntentReceiver receiver, IntentFilter filter, String permission) {
10979 synchronized(this) {
10980 ProcessRecord callerApp = null;
10981 if (caller != null) {
10982 callerApp = getRecordForAppLocked(caller);
10983 if (callerApp == null) {
10984 throw new SecurityException(
10985 "Unable to find app for caller " + caller
10986 + " (pid=" + Binder.getCallingPid()
10987 + ") when registering receiver " + receiver);
10988 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070010989 if (callerApp.info.uid != Process.SYSTEM_UID &&
10990 !callerApp.pkgList.contains(callerPackage)) {
10991 throw new SecurityException("Given caller package " + callerPackage
10992 + " is not running in process " + callerApp);
10993 }
10994 } else {
10995 callerPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 }
10997
10998 List allSticky = null;
10999
11000 // Look for any matching sticky broadcasts...
11001 Iterator actions = filter.actionsIterator();
11002 if (actions != null) {
11003 while (actions.hasNext()) {
11004 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060011005 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011006 }
11007 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060011008 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011009 }
11010
11011 // The first sticky in the list is returned directly back to
11012 // the client.
11013 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11014
Joe Onorato8a9b2202010-02-26 18:56:32 -080011015 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016 + ": " + sticky);
11017
11018 if (receiver == null) {
11019 return sticky;
11020 }
11021
11022 ReceiverList rl
11023 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11024 if (rl == null) {
11025 rl = new ReceiverList(this, callerApp,
11026 Binder.getCallingPid(),
11027 Binder.getCallingUid(), receiver);
11028 if (rl.app != null) {
11029 rl.app.receivers.add(rl);
11030 } else {
11031 try {
11032 receiver.asBinder().linkToDeath(rl, 0);
11033 } catch (RemoteException e) {
11034 return sticky;
11035 }
11036 rl.linkedToDeath = true;
11037 }
11038 mRegisteredReceivers.put(receiver.asBinder(), rl);
11039 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011040 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011041 rl.add(bf);
11042 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011043 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 }
11045 mReceiverResolver.addFilter(bf);
11046
11047 // Enqueue broadcasts for all existing stickies that match
11048 // this filter.
11049 if (allSticky != null) {
11050 ArrayList receivers = new ArrayList();
11051 receivers.add(bf);
11052
11053 int N = allSticky.size();
11054 for (int i=0; i<N; i++) {
11055 Intent intent = (Intent)allSticky.get(i);
11056 BroadcastRecord r = new BroadcastRecord(intent, null,
11057 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011058 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011059 if (mParallelBroadcasts.size() == 0) {
11060 scheduleBroadcastsLocked();
11061 }
11062 mParallelBroadcasts.add(r);
11063 }
11064 }
11065
11066 return sticky;
11067 }
11068 }
11069
11070 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011071 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072
11073 boolean doNext = false;
11074
11075 synchronized(this) {
11076 ReceiverList rl
11077 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11078 if (rl != null) {
11079 if (rl.curBroadcast != null) {
11080 BroadcastRecord r = rl.curBroadcast;
11081 doNext = finishReceiverLocked(
11082 receiver.asBinder(), r.resultCode, r.resultData,
11083 r.resultExtras, r.resultAbort, true);
11084 }
11085
11086 if (rl.app != null) {
11087 rl.app.receivers.remove(rl);
11088 }
11089 removeReceiverLocked(rl);
11090 if (rl.linkedToDeath) {
11091 rl.linkedToDeath = false;
11092 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11093 }
11094 }
11095 }
11096
11097 if (!doNext) {
11098 return;
11099 }
11100
11101 final long origId = Binder.clearCallingIdentity();
11102 processNextBroadcast(false);
11103 trimApplications();
11104 Binder.restoreCallingIdentity(origId);
11105 }
11106
11107 void removeReceiverLocked(ReceiverList rl) {
11108 mRegisteredReceivers.remove(rl.receiver.asBinder());
11109 int N = rl.size();
11110 for (int i=0; i<N; i++) {
11111 mReceiverResolver.removeFilter(rl.get(i));
11112 }
11113 }
11114
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011115 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
11116 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11117 ProcessRecord r = mLruProcesses.get(i);
11118 if (r.thread != null) {
11119 try {
11120 r.thread.dispatchPackageBroadcast(cmd, packages);
11121 } catch (RemoteException ex) {
11122 }
11123 }
11124 }
11125 }
11126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011127 private final int broadcastIntentLocked(ProcessRecord callerApp,
11128 String callerPackage, Intent intent, String resolvedType,
11129 IIntentReceiver resultTo, int resultCode, String resultData,
11130 Bundle map, String requiredPermission,
11131 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11132 intent = new Intent(intent);
11133
Dianne Hackborne7f97212011-02-24 14:40:20 -080011134 // By default broadcasts do not go to stopped apps.
11135 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
11136
Joe Onorato8a9b2202010-02-26 18:56:32 -080011137 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011138 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11139 + " ordered=" + ordered);
11140 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011141 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011142 }
11143
11144 // Handle special intents: if this broadcast is from the package
11145 // manager about a package being removed, we need to remove all of
11146 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011147 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011148 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011149 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11150 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011151 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 || uidRemoved) {
11153 if (checkComponentPermission(
11154 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011155 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 == PackageManager.PERMISSION_GRANTED) {
11157 if (uidRemoved) {
11158 final Bundle intentExtras = intent.getExtras();
11159 final int uid = intentExtras != null
11160 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11161 if (uid >= 0) {
11162 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11163 synchronized (bs) {
11164 bs.removeUidStatsLocked(uid);
11165 }
11166 }
11167 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011168 // If resources are unvailble just force stop all
11169 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011170 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011171 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11172 if (list != null && (list.length > 0)) {
11173 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011174 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011175 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011176 sendPackageBroadcastLocked(
11177 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011178 }
11179 } else {
11180 Uri data = intent.getData();
11181 String ssp;
11182 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11183 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11184 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011185 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011186 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011187 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011188 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
11189 new String[] {ssp});
11190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011191 }
11192 }
11193 }
11194 } else {
11195 String msg = "Permission Denial: " + intent.getAction()
11196 + " broadcast from " + callerPackage + " (pid=" + callingPid
11197 + ", uid=" + callingUid + ")"
11198 + " requires "
11199 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011200 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011201 throw new SecurityException(msg);
11202 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011203
11204 // Special case for adding a package: by default turn on compatibility
11205 // mode.
11206 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070011207 Uri data = intent.getData();
11208 String ssp;
11209 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11210 mCompatModePackages.handlePackageAddedLocked(ssp,
11211 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011213 }
11214
11215 /*
11216 * If this is the time zone changed action, queue up a message that will reset the timezone
11217 * of all currently running processes. This message will get queued up before the broadcast
11218 * happens.
11219 */
11220 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11221 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11222 }
11223
Robert Greenwalt03595d02010-11-02 14:08:23 -070011224 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
11225 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
11226 }
11227
Robert Greenwalt434203a2010-10-11 16:00:27 -070011228 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
11229 ProxyProperties proxy = intent.getParcelableExtra("proxy");
11230 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
11231 }
11232
Dianne Hackborn854060af2009-07-09 18:14:31 -070011233 /*
11234 * Prevent non-system code (defined here to be non-persistent
11235 * processes) from sending protected broadcasts.
11236 */
11237 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11238 || callingUid == Process.SHELL_UID || callingUid == 0) {
11239 // Always okay.
11240 } else if (callerApp == null || !callerApp.persistent) {
11241 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011242 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070011243 intent.getAction())) {
11244 String msg = "Permission Denial: not allowed to send broadcast "
11245 + intent.getAction() + " from pid="
11246 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011247 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011248 throw new SecurityException(msg);
11249 }
11250 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011251 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011252 return BROADCAST_SUCCESS;
11253 }
11254 }
11255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011256 // Add to the sticky list if requested.
11257 if (sticky) {
11258 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11259 callingPid, callingUid)
11260 != PackageManager.PERMISSION_GRANTED) {
11261 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11262 + callingPid + ", uid=" + callingUid
11263 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011264 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011265 throw new SecurityException(msg);
11266 }
11267 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011268 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 + " and enforce permission " + requiredPermission);
11270 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11271 }
11272 if (intent.getComponent() != null) {
11273 throw new SecurityException(
11274 "Sticky broadcasts can't target a specific component");
11275 }
11276 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11277 if (list == null) {
11278 list = new ArrayList<Intent>();
11279 mStickyBroadcasts.put(intent.getAction(), list);
11280 }
11281 int N = list.size();
11282 int i;
11283 for (i=0; i<N; i++) {
11284 if (intent.filterEquals(list.get(i))) {
11285 // This sticky already exists, replace it.
11286 list.set(i, new Intent(intent));
11287 break;
11288 }
11289 }
11290 if (i >= N) {
11291 list.add(new Intent(intent));
11292 }
11293 }
11294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 // Figure out who all will receive this broadcast.
11296 List receivers = null;
11297 List<BroadcastFilter> registeredReceivers = null;
11298 try {
11299 if (intent.getComponent() != null) {
11300 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011301 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011302 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011303 if (ai != null) {
11304 receivers = new ArrayList();
11305 ResolveInfo ri = new ResolveInfo();
11306 ri.activityInfo = ai;
11307 receivers.add(ri);
11308 }
11309 } else {
11310 // Need to resolve the intent to interested receivers...
11311 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11312 == 0) {
11313 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011314 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011315 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011316 }
Mihai Preda074edef2009-05-18 17:13:31 +020011317 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011318 }
11319 } catch (RemoteException ex) {
11320 // pm is in same process, this will never happen.
11321 }
11322
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011323 final boolean replacePending =
11324 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11325
Joe Onorato8a9b2202010-02-26 18:56:32 -080011326 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011327 + " replacePending=" + replacePending);
11328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11330 if (!ordered && NR > 0) {
11331 // If we are not serializing this broadcast, then send the
11332 // registered receivers separately so they don't wait for the
11333 // components to be launched.
11334 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11335 callerPackage, callingPid, callingUid, requiredPermission,
11336 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011337 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011338 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011339 TAG, "Enqueueing parallel broadcast " + r
11340 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011341 boolean replaced = false;
11342 if (replacePending) {
11343 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11344 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011345 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011346 "***** DROPPING PARALLEL: " + intent);
11347 mParallelBroadcasts.set(i, r);
11348 replaced = true;
11349 break;
11350 }
11351 }
11352 }
11353 if (!replaced) {
11354 mParallelBroadcasts.add(r);
11355 scheduleBroadcastsLocked();
11356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 registeredReceivers = null;
11358 NR = 0;
11359 }
11360
11361 // Merge into one list.
11362 int ir = 0;
11363 if (receivers != null) {
11364 // A special case for PACKAGE_ADDED: do not allow the package
11365 // being added to see this broadcast. This prevents them from
11366 // using this as a back door to get run as soon as they are
11367 // installed. Maybe in the future we want to have a special install
11368 // broadcast or such for apps, but we'd like to deliberately make
11369 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011370 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011371 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11372 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11373 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011374 Uri data = intent.getData();
11375 if (data != null) {
11376 String pkgName = data.getSchemeSpecificPart();
11377 if (pkgName != null) {
11378 skipPackages = new String[] { pkgName };
11379 }
11380 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011381 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011382 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011383 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011384 if (skipPackages != null && (skipPackages.length > 0)) {
11385 for (String skipPackage : skipPackages) {
11386 if (skipPackage != null) {
11387 int NT = receivers.size();
11388 for (int it=0; it<NT; it++) {
11389 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11390 if (curt.activityInfo.packageName.equals(skipPackage)) {
11391 receivers.remove(it);
11392 it--;
11393 NT--;
11394 }
11395 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011396 }
11397 }
11398 }
11399
11400 int NT = receivers != null ? receivers.size() : 0;
11401 int it = 0;
11402 ResolveInfo curt = null;
11403 BroadcastFilter curr = null;
11404 while (it < NT && ir < NR) {
11405 if (curt == null) {
11406 curt = (ResolveInfo)receivers.get(it);
11407 }
11408 if (curr == null) {
11409 curr = registeredReceivers.get(ir);
11410 }
11411 if (curr.getPriority() >= curt.priority) {
11412 // Insert this broadcast record into the final list.
11413 receivers.add(it, curr);
11414 ir++;
11415 curr = null;
11416 it++;
11417 NT++;
11418 } else {
11419 // Skip to the next ResolveInfo in the final list.
11420 it++;
11421 curt = null;
11422 }
11423 }
11424 }
11425 while (ir < NR) {
11426 if (receivers == null) {
11427 receivers = new ArrayList();
11428 }
11429 receivers.add(registeredReceivers.get(ir));
11430 ir++;
11431 }
11432
11433 if ((receivers != null && receivers.size() > 0)
11434 || resultTo != null) {
11435 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11436 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011437 receivers, resultTo, resultCode, resultData, map, ordered,
11438 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011439 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011440 TAG, "Enqueueing ordered broadcast " + r
11441 + ": prev had " + mOrderedBroadcasts.size());
11442 if (DEBUG_BROADCAST) {
11443 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011444 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011445 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011446 boolean replaced = false;
11447 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011448 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011449 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011450 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011451 "***** DROPPING ORDERED: " + intent);
11452 mOrderedBroadcasts.set(i, r);
11453 replaced = true;
11454 break;
11455 }
11456 }
11457 }
11458 if (!replaced) {
11459 mOrderedBroadcasts.add(r);
11460 scheduleBroadcastsLocked();
11461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011462 }
11463
11464 return BROADCAST_SUCCESS;
11465 }
11466
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011467 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011468 // Refuse possible leaked file descriptors
11469 if (intent != null && intent.hasFileDescriptors() == true) {
11470 throw new IllegalArgumentException("File descriptors passed in Intent");
11471 }
11472
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011473 int flags = intent.getFlags();
11474
11475 if (!mProcessesReady) {
11476 // if the caller really truly claims to know what they're doing, go
11477 // ahead and allow the broadcast without launching any receivers
11478 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11479 intent = new Intent(intent);
11480 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11481 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11482 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11483 + " before boot completion");
11484 throw new IllegalStateException("Cannot broadcast before boot completed");
11485 }
11486 }
11487
11488 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11489 throw new IllegalArgumentException(
11490 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11491 }
11492
11493 return intent;
11494 }
11495
11496 public final int broadcastIntent(IApplicationThread caller,
11497 Intent intent, String resolvedType, IIntentReceiver resultTo,
11498 int resultCode, String resultData, Bundle map,
11499 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011501 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11504 final int callingPid = Binder.getCallingPid();
11505 final int callingUid = Binder.getCallingUid();
11506 final long origId = Binder.clearCallingIdentity();
11507 int res = broadcastIntentLocked(callerApp,
11508 callerApp != null ? callerApp.info.packageName : null,
11509 intent, resolvedType, resultTo,
11510 resultCode, resultData, map, requiredPermission, serialized,
11511 sticky, callingPid, callingUid);
11512 Binder.restoreCallingIdentity(origId);
11513 return res;
11514 }
11515 }
11516
11517 int broadcastIntentInPackage(String packageName, int uid,
11518 Intent intent, String resolvedType, IIntentReceiver resultTo,
11519 int resultCode, String resultData, Bundle map,
11520 String requiredPermission, boolean serialized, boolean sticky) {
11521 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011522 intent = verifyBroadcastLocked(intent);
11523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011524 final long origId = Binder.clearCallingIdentity();
11525 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11526 resultTo, resultCode, resultData, map, requiredPermission,
11527 serialized, sticky, -1, uid);
11528 Binder.restoreCallingIdentity(origId);
11529 return res;
11530 }
11531 }
11532
11533 public final void unbroadcastIntent(IApplicationThread caller,
11534 Intent intent) {
11535 // Refuse possible leaked file descriptors
11536 if (intent != null && intent.hasFileDescriptors() == true) {
11537 throw new IllegalArgumentException("File descriptors passed in Intent");
11538 }
11539
11540 synchronized(this) {
11541 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11542 != PackageManager.PERMISSION_GRANTED) {
11543 String msg = "Permission Denial: unbroadcastIntent() from pid="
11544 + Binder.getCallingPid()
11545 + ", uid=" + Binder.getCallingUid()
11546 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011547 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011548 throw new SecurityException(msg);
11549 }
11550 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11551 if (list != null) {
11552 int N = list.size();
11553 int i;
11554 for (i=0; i<N; i++) {
11555 if (intent.filterEquals(list.get(i))) {
11556 list.remove(i);
11557 break;
11558 }
11559 }
11560 }
11561 }
11562 }
11563
11564 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11565 String resultData, Bundle resultExtras, boolean resultAbort,
11566 boolean explicit) {
11567 if (mOrderedBroadcasts.size() == 0) {
11568 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011569 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011570 }
11571 return false;
11572 }
11573 BroadcastRecord r = mOrderedBroadcasts.get(0);
11574 if (r.receiver == null) {
11575 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011576 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011577 }
11578 return false;
11579 }
11580 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011581 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011582 return false;
11583 }
11584 int state = r.state;
11585 r.state = r.IDLE;
11586 if (state == r.IDLE) {
11587 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011588 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011589 }
11590 }
11591 r.receiver = null;
11592 r.intent.setComponent(null);
11593 if (r.curApp != null) {
11594 r.curApp.curReceiver = null;
11595 }
11596 if (r.curFilter != null) {
11597 r.curFilter.receiverList.curBroadcast = null;
11598 }
11599 r.curFilter = null;
11600 r.curApp = null;
11601 r.curComponent = null;
11602 r.curReceiver = null;
11603 mPendingBroadcast = null;
11604
11605 r.resultCode = resultCode;
11606 r.resultData = resultData;
11607 r.resultExtras = resultExtras;
11608 r.resultAbort = resultAbort;
11609
11610 // We will process the next receiver right now if this is finishing
11611 // an app receiver (which is always asynchronous) or after we have
11612 // come back from calling a receiver.
11613 return state == BroadcastRecord.APP_RECEIVE
11614 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11615 }
11616
11617 public void finishReceiver(IBinder who, int resultCode, String resultData,
11618 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011619 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620
11621 // Refuse possible leaked file descriptors
11622 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11623 throw new IllegalArgumentException("File descriptors passed in Bundle");
11624 }
11625
11626 boolean doNext;
11627
11628 final long origId = Binder.clearCallingIdentity();
11629
11630 synchronized(this) {
11631 doNext = finishReceiverLocked(
11632 who, resultCode, resultData, resultExtras, resultAbort, true);
11633 }
11634
11635 if (doNext) {
11636 processNextBroadcast(false);
11637 }
11638 trimApplications();
11639
11640 Binder.restoreCallingIdentity(origId);
11641 }
11642
Jeff Brown4d94a762010-09-23 11:33:28 -070011643 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011644 if (r.nextReceiver > 0) {
11645 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11646 if (curReceiver instanceof BroadcastFilter) {
11647 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011648 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011649 System.identityHashCode(r),
11650 r.intent.getAction(),
11651 r.nextReceiver - 1,
11652 System.identityHashCode(bf));
11653 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011654 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011655 System.identityHashCode(r),
11656 r.intent.getAction(),
11657 r.nextReceiver - 1,
11658 ((ResolveInfo)curReceiver).toString());
11659 }
11660 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011661 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011662 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011663 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011664 System.identityHashCode(r),
11665 r.intent.getAction(),
11666 r.nextReceiver,
11667 "NONE");
11668 }
11669 }
11670
Jeff Brown4d94a762010-09-23 11:33:28 -070011671 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11672 if (! mPendingBroadcastTimeoutMessage) {
11673 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11674 mHandler.sendMessageAtTime(msg, timeoutTime);
11675 mPendingBroadcastTimeoutMessage = true;
11676 }
11677 }
11678
11679 private final void cancelBroadcastTimeoutLocked() {
11680 if (mPendingBroadcastTimeoutMessage) {
11681 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11682 mPendingBroadcastTimeoutMessage = false;
11683 }
11684 }
11685
11686 private final void broadcastTimeoutLocked(boolean fromMsg) {
11687 if (fromMsg) {
11688 mPendingBroadcastTimeoutMessage = false;
11689 }
11690
11691 if (mOrderedBroadcasts.size() == 0) {
11692 return;
11693 }
11694
11695 long now = SystemClock.uptimeMillis();
11696 BroadcastRecord r = mOrderedBroadcasts.get(0);
11697 if (fromMsg) {
11698 if (mDidDexOpt) {
11699 // Delay timeouts until dexopt finishes.
11700 mDidDexOpt = false;
11701 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11702 setBroadcastTimeoutLocked(timeoutTime);
11703 return;
11704 }
11705 if (! mProcessesReady) {
11706 // Only process broadcast timeouts if the system is ready. That way
11707 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11708 // to do heavy lifting for system up.
11709 return;
11710 }
11711
11712 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11713 if (timeoutTime > now) {
11714 // We can observe premature timeouts because we do not cancel and reset the
11715 // broadcast timeout message after each receiver finishes. Instead, we set up
11716 // an initial timeout then kick it down the road a little further as needed
11717 // when it expires.
11718 if (DEBUG_BROADCAST) Slog.v(TAG,
11719 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11720 + timeoutTime);
11721 setBroadcastTimeoutLocked(timeoutTime);
11722 return;
11723 }
11724 }
11725
11726 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11727 + ", started " + (now - r.receiverTime) + "ms ago");
11728 r.receiverTime = now;
11729 r.anrCount++;
11730
11731 // Current receiver has passed its expiration date.
11732 if (r.nextReceiver <= 0) {
11733 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11734 return;
11735 }
11736
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011737 ProcessRecord app = null;
11738 String anrMessage = null;
11739
Jeff Brown4d94a762010-09-23 11:33:28 -070011740 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11741 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11742 logBroadcastReceiverDiscardLocked(r);
11743 if (curReceiver instanceof BroadcastFilter) {
11744 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11745 if (bf.receiverList.pid != 0
11746 && bf.receiverList.pid != MY_PID) {
11747 synchronized (this.mPidsSelfLocked) {
11748 app = this.mPidsSelfLocked.get(
11749 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011751 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011752 } else {
11753 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011754 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011755
Jeff Brown4d94a762010-09-23 11:33:28 -070011756 if (app != null) {
11757 anrMessage = "Broadcast of " + r.intent.toString();
11758 }
11759
11760 if (mPendingBroadcast == r) {
11761 mPendingBroadcast = null;
11762 }
11763
11764 // Move on to the next receiver.
11765 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11766 r.resultExtras, r.resultAbort, true);
11767 scheduleBroadcastsLocked();
11768
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011769 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011770 // Post the ANR to the handler since we do not want to process ANRs while
11771 // potentially holding our lock.
11772 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011774 }
11775
11776 private final void processCurBroadcastLocked(BroadcastRecord r,
11777 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011778 if (DEBUG_BROADCAST) Slog.v(TAG,
11779 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011780 if (app.thread == null) {
11781 throw new RemoteException();
11782 }
11783 r.receiver = app.thread.asBinder();
11784 r.curApp = app;
11785 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011786 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011787
11788 // Tell the application to launch this receiver.
11789 r.intent.setComponent(r.curComponent);
11790
11791 boolean started = false;
11792 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011793 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011794 "Delivering to component " + r.curComponent
11795 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011796 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011798 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011799 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011800 if (DEBUG_BROADCAST) Slog.v(TAG,
11801 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011802 started = true;
11803 } finally {
11804 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011805 if (DEBUG_BROADCAST) Slog.v(TAG,
11806 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011807 r.receiver = null;
11808 r.curApp = null;
11809 app.curReceiver = null;
11810 }
11811 }
11812
11813 }
11814
Jeff Brown4d94a762010-09-23 11:33:28 -070011815 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011816 Intent intent, int resultCode, String data, Bundle extras,
11817 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011818 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011819 if (app != null && app.thread != null) {
11820 // If we have an app thread, do the call through that so it is
11821 // correctly ordered with other one-way calls.
11822 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011823 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011824 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011825 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011826 }
11827 }
11828
Jeff Brown4d94a762010-09-23 11:33:28 -070011829 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011830 BroadcastFilter filter, boolean ordered) {
11831 boolean skip = false;
11832 if (filter.requiredPermission != null) {
11833 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011834 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011835 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011836 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011837 + r.intent.toString()
11838 + " from " + r.callerPackage + " (pid="
11839 + r.callingPid + ", uid=" + r.callingUid + ")"
11840 + " requires " + filter.requiredPermission
11841 + " due to registered receiver " + filter);
11842 skip = true;
11843 }
11844 }
11845 if (r.requiredPermission != null) {
11846 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011847 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011848 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011849 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011850 + r.intent.toString()
11851 + " to " + filter.receiverList.app
11852 + " (pid=" + filter.receiverList.pid
11853 + ", uid=" + filter.receiverList.uid + ")"
11854 + " requires " + r.requiredPermission
11855 + " due to sender " + r.callerPackage
11856 + " (uid " + r.callingUid + ")");
11857 skip = true;
11858 }
11859 }
11860
11861 if (!skip) {
11862 // If this is not being sent as an ordered broadcast, then we
11863 // don't want to touch the fields that keep track of the current
11864 // state of ordered broadcasts.
11865 if (ordered) {
11866 r.receiver = filter.receiverList.receiver.asBinder();
11867 r.curFilter = filter;
11868 filter.receiverList.curBroadcast = r;
11869 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011870 if (filter.receiverList.app != null) {
11871 // Bump hosting application to no longer be in background
11872 // scheduling class. Note that we can't do that if there
11873 // isn't an app... but we can only be in that case for
11874 // things that directly call the IActivityManager API, which
11875 // are already core system stuff so don't matter for this.
11876 r.curApp = filter.receiverList.app;
11877 filter.receiverList.app.curReceiver = r;
11878 updateOomAdjLocked();
11879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011880 }
11881 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011882 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011883 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011884 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011885 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011886 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011887 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011888 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011889 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011890 if (ordered) {
11891 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11892 }
11893 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011894 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011895 if (ordered) {
11896 r.receiver = null;
11897 r.curFilter = null;
11898 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011899 if (filter.receiverList.app != null) {
11900 filter.receiverList.app.curReceiver = null;
11901 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011902 }
11903 }
11904 }
11905 }
11906
Dianne Hackborn12527f92009-11-11 17:39:50 -080011907 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11908 if (r.callingUid < 0) {
11909 // This was from a registerReceiver() call; ignore it.
11910 return;
11911 }
11912 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11913 MAX_BROADCAST_HISTORY-1);
11914 r.finishTime = SystemClock.uptimeMillis();
11915 mBroadcastHistory[0] = r;
11916 }
11917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011918 private final void processNextBroadcast(boolean fromMsg) {
11919 synchronized(this) {
11920 BroadcastRecord r;
11921
Joe Onorato8a9b2202010-02-26 18:56:32 -080011922 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011923 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011924 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011925
11926 updateCpuStats();
11927
11928 if (fromMsg) {
11929 mBroadcastsScheduled = false;
11930 }
11931
11932 // First, deliver any non-serialized broadcasts right away.
11933 while (mParallelBroadcasts.size() > 0) {
11934 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011935 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011936 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011937 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011938 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011939 for (int i=0; i<N; i++) {
11940 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011941 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011942 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011943 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011944 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011945 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011946 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011947 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011948 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011949 }
11950
11951 // Now take care of the next serialized one...
11952
11953 // If we are waiting for a process to come up to handle the next
11954 // broadcast, then do nothing at this point. Just in case, we
11955 // check that the process we're waiting for still exists.
11956 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011957 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011958 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011959 + mPendingBroadcast.curApp);
11960 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011961
11962 boolean isDead;
11963 synchronized (mPidsSelfLocked) {
11964 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11965 }
11966 if (!isDead) {
11967 // It's still alive, so keep waiting
11968 return;
11969 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011970 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011971 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011972 mPendingBroadcast.state = BroadcastRecord.IDLE;
11973 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011974 mPendingBroadcast = null;
11975 }
11976 }
11977
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011978 boolean looped = false;
11979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011980 do {
11981 if (mOrderedBroadcasts.size() == 0) {
11982 // No more broadcasts pending, so all done!
11983 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011984 if (looped) {
11985 // If we had finished the last ordered broadcast, then
11986 // make sure all processes have correct oom and sched
11987 // adjustments.
11988 updateOomAdjLocked();
11989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011990 return;
11991 }
11992 r = mOrderedBroadcasts.get(0);
11993 boolean forceReceive = false;
11994
11995 // Ensure that even if something goes awry with the timeout
11996 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011997 // and continue to make progress.
11998 //
11999 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070012000 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012001 // one time heavy lifting after system upgrades and can take
12002 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012003 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012004 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012005 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012006 if ((numReceivers > 0) &&
12007 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012008 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012009 + " now=" + now
12010 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012011 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012012 + " intent=" + r.intent
12013 + " numReceivers=" + numReceivers
12014 + " nextReceiver=" + r.nextReceiver
12015 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070012016 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 forceReceive = true;
12018 r.state = BroadcastRecord.IDLE;
12019 }
12020 }
12021
12022 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012023 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012024 "processNextBroadcast() called when not idle (state="
12025 + r.state + ")");
12026 return;
12027 }
12028
12029 if (r.receivers == null || r.nextReceiver >= numReceivers
12030 || r.resultAbort || forceReceive) {
12031 // No more receivers for this broadcast! Send the final
12032 // result if requested...
12033 if (r.resultTo != null) {
12034 try {
12035 if (DEBUG_BROADCAST) {
12036 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012037 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012038 + " seq=" + seq + " app=" + r.callerApp);
12039 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012040 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012041 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012042 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020012043 // Set this to null so that the reference
12044 // (local and remote) isnt kept in the mBroadcastHistory.
12045 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012046 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012047 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012048 }
12049 }
12050
Joe Onorato8a9b2202010-02-26 18:56:32 -080012051 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070012052 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012053
Joe Onorato8a9b2202010-02-26 18:56:32 -080012054 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012055 + r);
12056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012057 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012058 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012059 mOrderedBroadcasts.remove(0);
12060 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012061 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012062 continue;
12063 }
12064 } while (r == null);
12065
12066 // Get the next receiver...
12067 int recIdx = r.nextReceiver++;
12068
12069 // Keep track of when this receiver started, and make sure there
12070 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012071 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012072 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012073 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012074
Joe Onorato8a9b2202010-02-26 18:56:32 -080012075 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012076 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012077 }
12078 if (! mPendingBroadcastTimeoutMessage) {
12079 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012080 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070012081 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
12082 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012083 }
12084
12085 Object nextReceiver = r.receivers.get(recIdx);
12086 if (nextReceiver instanceof BroadcastFilter) {
12087 // Simple case: this is a registered receiver who gets
12088 // a direct call.
12089 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012090 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012091 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012092 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012093 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012094 if (r.receiver == null || !r.ordered) {
12095 // The receiver has already finished, so schedule to
12096 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012097 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
12098 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012099 r.state = BroadcastRecord.IDLE;
12100 scheduleBroadcastsLocked();
12101 }
12102 return;
12103 }
12104
12105 // Hard case: need to instantiate the receiver, possibly
12106 // starting its application process to host it.
12107
12108 ResolveInfo info =
12109 (ResolveInfo)nextReceiver;
12110
12111 boolean skip = false;
12112 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012113 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
12114 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012115 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012116 if (!info.activityInfo.exported) {
12117 Slog.w(TAG, "Permission Denial: broadcasting "
12118 + r.intent.toString()
12119 + " from " + r.callerPackage + " (pid=" + r.callingPid
12120 + ", uid=" + r.callingUid + ")"
12121 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
12122 + " due to receiver " + info.activityInfo.packageName
12123 + "/" + info.activityInfo.name);
12124 } else {
12125 Slog.w(TAG, "Permission Denial: broadcasting "
12126 + r.intent.toString()
12127 + " from " + r.callerPackage + " (pid=" + r.callingPid
12128 + ", uid=" + r.callingUid + ")"
12129 + " requires " + info.activityInfo.permission
12130 + " due to receiver " + info.activityInfo.packageName
12131 + "/" + info.activityInfo.name);
12132 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012133 skip = true;
12134 }
12135 if (r.callingUid != Process.SYSTEM_UID &&
12136 r.requiredPermission != null) {
12137 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012138 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012139 checkPermission(r.requiredPermission,
12140 info.activityInfo.applicationInfo.packageName);
12141 } catch (RemoteException e) {
12142 perm = PackageManager.PERMISSION_DENIED;
12143 }
12144 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012145 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012146 + r.intent + " to "
12147 + info.activityInfo.applicationInfo.packageName
12148 + " requires " + r.requiredPermission
12149 + " due to sender " + r.callerPackage
12150 + " (uid " + r.callingUid + ")");
12151 skip = true;
12152 }
12153 }
12154 if (r.curApp != null && r.curApp.crashing) {
12155 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012156 if (DEBUG_BROADCAST) Slog.v(TAG,
12157 "Skipping deliver ordered " + r + " to " + r.curApp
12158 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012159 skip = true;
12160 }
12161
12162 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012163 if (DEBUG_BROADCAST) Slog.v(TAG,
12164 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012165 r.receiver = null;
12166 r.curFilter = null;
12167 r.state = BroadcastRecord.IDLE;
12168 scheduleBroadcastsLocked();
12169 return;
12170 }
12171
12172 r.state = BroadcastRecord.APP_RECEIVE;
12173 String targetProcess = info.activityInfo.processName;
12174 r.curComponent = new ComponentName(
12175 info.activityInfo.applicationInfo.packageName,
12176 info.activityInfo.name);
12177 r.curReceiver = info.activityInfo;
12178
Dianne Hackborne7f97212011-02-24 14:40:20 -080012179 // Broadcast is being executed, its package can't be stopped.
12180 try {
12181 AppGlobals.getPackageManager().setPackageStoppedState(
12182 r.curComponent.getPackageName(), false);
12183 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012184 } catch (IllegalArgumentException e) {
12185 Slog.w(TAG, "Failed trying to unstop package "
12186 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012187 }
12188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012189 // Is this receiver's application already running?
12190 ProcessRecord app = getProcessRecordLocked(targetProcess,
12191 info.activityInfo.applicationInfo.uid);
12192 if (app != null && app.thread != null) {
12193 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012194 app.addPackage(info.activityInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012195 processCurBroadcastLocked(r, app);
12196 return;
12197 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012198 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012199 + r.curComponent, e);
12200 }
12201
12202 // If a dead object exception was thrown -- fall through to
12203 // restart the application.
12204 }
12205
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012206 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012207 if (DEBUG_BROADCAST) Slog.v(TAG,
12208 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012209 if ((r.curApp=startProcessLocked(targetProcess,
12210 info.activityInfo.applicationInfo, true,
12211 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012212 "broadcast", r.curComponent,
12213 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12214 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012215 // Ah, this recipient is unavailable. Finish it if necessary,
12216 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012217 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012218 + info.activityInfo.applicationInfo.packageName + "/"
12219 + info.activityInfo.applicationInfo.uid + " for broadcast "
12220 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070012221 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012222 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12223 r.resultExtras, r.resultAbort, true);
12224 scheduleBroadcastsLocked();
12225 r.state = BroadcastRecord.IDLE;
12226 return;
12227 }
12228
12229 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012230 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012231 }
12232 }
12233
12234 // =========================================================
12235 // INSTRUMENTATION
12236 // =========================================================
12237
12238 public boolean startInstrumentation(ComponentName className,
12239 String profileFile, int flags, Bundle arguments,
12240 IInstrumentationWatcher watcher) {
12241 // Refuse possible leaked file descriptors
12242 if (arguments != null && arguments.hasFileDescriptors()) {
12243 throw new IllegalArgumentException("File descriptors passed in Bundle");
12244 }
12245
12246 synchronized(this) {
12247 InstrumentationInfo ii = null;
12248 ApplicationInfo ai = null;
12249 try {
12250 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012251 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012252 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012253 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012254 } catch (PackageManager.NameNotFoundException e) {
12255 }
12256 if (ii == null) {
12257 reportStartInstrumentationFailure(watcher, className,
12258 "Unable to find instrumentation info for: " + className);
12259 return false;
12260 }
12261 if (ai == null) {
12262 reportStartInstrumentationFailure(watcher, className,
12263 "Unable to find instrumentation target package: " + ii.targetPackage);
12264 return false;
12265 }
12266
12267 int match = mContext.getPackageManager().checkSignatures(
12268 ii.targetPackage, ii.packageName);
12269 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12270 String msg = "Permission Denial: starting instrumentation "
12271 + className + " from pid="
12272 + Binder.getCallingPid()
12273 + ", uid=" + Binder.getCallingPid()
12274 + " not allowed because package " + ii.packageName
12275 + " does not have a signature matching the target "
12276 + ii.targetPackage;
12277 reportStartInstrumentationFailure(watcher, className, msg);
12278 throw new SecurityException(msg);
12279 }
12280
12281 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012282 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012283 ProcessRecord app = addAppLocked(ai);
12284 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012285 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012286 app.instrumentationProfileFile = profileFile;
12287 app.instrumentationArguments = arguments;
12288 app.instrumentationWatcher = watcher;
12289 app.instrumentationResultClass = className;
12290 Binder.restoreCallingIdentity(origId);
12291 }
12292
12293 return true;
12294 }
12295
12296 /**
12297 * Report errors that occur while attempting to start Instrumentation. Always writes the
12298 * error to the logs, but if somebody is watching, send the report there too. This enables
12299 * the "am" command to report errors with more information.
12300 *
12301 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12302 * @param cn The component name of the instrumentation.
12303 * @param report The error report.
12304 */
12305 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12306 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012307 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012308 try {
12309 if (watcher != null) {
12310 Bundle results = new Bundle();
12311 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12312 results.putString("Error", report);
12313 watcher.instrumentationStatus(cn, -1, results);
12314 }
12315 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012316 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012317 }
12318 }
12319
12320 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12321 if (app.instrumentationWatcher != null) {
12322 try {
12323 // NOTE: IInstrumentationWatcher *must* be oneway here
12324 app.instrumentationWatcher.instrumentationFinished(
12325 app.instrumentationClass,
12326 resultCode,
12327 results);
12328 } catch (RemoteException e) {
12329 }
12330 }
12331 app.instrumentationWatcher = null;
12332 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012333 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012334 app.instrumentationProfileFile = null;
12335 app.instrumentationArguments = null;
12336
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012337 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012338 }
12339
12340 public void finishInstrumentation(IApplicationThread target,
12341 int resultCode, Bundle results) {
12342 // Refuse possible leaked file descriptors
12343 if (results != null && results.hasFileDescriptors()) {
12344 throw new IllegalArgumentException("File descriptors passed in Intent");
12345 }
12346
12347 synchronized(this) {
12348 ProcessRecord app = getRecordForAppLocked(target);
12349 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012350 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012351 return;
12352 }
12353 final long origId = Binder.clearCallingIdentity();
12354 finishInstrumentationLocked(app, resultCode, results);
12355 Binder.restoreCallingIdentity(origId);
12356 }
12357 }
12358
12359 // =========================================================
12360 // CONFIGURATION
12361 // =========================================================
12362
12363 public ConfigurationInfo getDeviceConfigurationInfo() {
12364 ConfigurationInfo config = new ConfigurationInfo();
12365 synchronized (this) {
12366 config.reqTouchScreen = mConfiguration.touchscreen;
12367 config.reqKeyboardType = mConfiguration.keyboard;
12368 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012369 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12370 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012371 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12372 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012373 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12374 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012375 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12376 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012377 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012378 }
12379 return config;
12380 }
12381
12382 public Configuration getConfiguration() {
12383 Configuration ci;
12384 synchronized(this) {
12385 ci = new Configuration(mConfiguration);
12386 }
12387 return ci;
12388 }
12389
12390 public void updateConfiguration(Configuration values) {
12391 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12392 "updateConfiguration()");
12393
12394 synchronized(this) {
12395 if (values == null && mWindowManager != null) {
12396 // sentinel: fetch the current configuration from the window manager
12397 values = mWindowManager.computeNewConfiguration();
12398 }
12399
12400 final long origId = Binder.clearCallingIdentity();
12401 updateConfigurationLocked(values, null);
12402 Binder.restoreCallingIdentity(origId);
12403 }
12404 }
12405
12406 /**
12407 * Do either or both things: (1) change the current configuration, and (2)
12408 * make sure the given activity is running with the (now) current
12409 * configuration. Returns true if the activity has been left running, or
12410 * false if <var>starting</var> is being destroyed to match the new
12411 * configuration.
12412 */
12413 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012414 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012415 int changes = 0;
12416
12417 boolean kept = true;
12418
12419 if (values != null) {
12420 Configuration newConfig = new Configuration(mConfiguration);
12421 changes = newConfig.updateFrom(values);
12422 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012423 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012424 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012425 }
12426
Doug Zongker2bec3d42009-12-04 12:52:44 -080012427 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012428
12429 if (values.locale != null) {
12430 saveLocaleLocked(values.locale,
12431 !values.locale.equals(mConfiguration.locale),
12432 values.userSetLocale);
12433 }
12434
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012435 mConfigurationSeq++;
12436 if (mConfigurationSeq <= 0) {
12437 mConfigurationSeq = 1;
12438 }
12439 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012440 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012441 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012442
12443 AttributeCache ac = AttributeCache.instance();
12444 if (ac != null) {
12445 ac.updateConfiguration(mConfiguration);
12446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012447
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070012448 // Make sure all resources in our process are updated
12449 // right now, so that anyone who is going to retrieve
12450 // resource values after we return will be sure to get
12451 // the new ones. This is especially important during
12452 // boot, where the first config change needs to guarantee
12453 // all resources have that config before following boot
12454 // code is executed.
12455 mSystemThread.applyConfigurationToResources(newConfig);
12456
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012457 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
12458 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12459 msg.obj = new Configuration(mConfiguration);
12460 mHandler.sendMessage(msg);
12461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012462
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012463 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12464 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012465 try {
12466 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012467 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012468 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012469 app.thread.scheduleConfigurationChanged(mConfiguration);
12470 }
12471 } catch (Exception e) {
12472 }
12473 }
12474 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012475 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12476 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012477 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12478 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012479 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12480 broadcastIntentLocked(null, null,
12481 new Intent(Intent.ACTION_LOCALE_CHANGED),
12482 null, null, 0, null, null,
12483 null, false, false, MY_PID, Process.SYSTEM_UID);
12484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012485 }
12486 }
12487
12488 if (changes != 0 && starting == null) {
12489 // If the configuration changed, and the caller is not already
12490 // in the process of starting an activity, then find the top
12491 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012492 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012493 }
12494
12495 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012496 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012497 // And we need to make sure at this point that all other activities
12498 // are made visible with the correct configuration.
12499 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012500 }
12501
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012502 if (values != null && mWindowManager != null) {
12503 mWindowManager.setNewConfiguration(mConfiguration);
12504 }
12505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012506 return kept;
12507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012508
12509 /**
12510 * Save the locale. You must be inside a synchronized (this) block.
12511 */
12512 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12513 if(isDiff) {
12514 SystemProperties.set("user.language", l.getLanguage());
12515 SystemProperties.set("user.region", l.getCountry());
12516 }
12517
12518 if(isPersist) {
12519 SystemProperties.set("persist.sys.language", l.getLanguage());
12520 SystemProperties.set("persist.sys.country", l.getCountry());
12521 SystemProperties.set("persist.sys.localevar", l.getVariant());
12522 }
12523 }
12524
12525 // =========================================================
12526 // LIFETIME MANAGEMENT
12527 // =========================================================
12528
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012529 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12530 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012531 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012532 // This adjustment has already been computed. If we are calling
12533 // from the top, we may have already computed our adjustment with
12534 // an earlier hidden adjustment that isn't really for us... if
12535 // so, use the new hidden adjustment.
12536 if (!recursed && app.hidden) {
12537 app.curAdj = hiddenAdj;
12538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012539 return app.curAdj;
12540 }
12541
12542 if (app.thread == null) {
12543 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012544 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012545 return (app.curAdj=EMPTY_APP_ADJ);
12546 }
12547
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012548 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12549 // The max adjustment doesn't allow this app to be anything
12550 // below foreground, so it is not worth doing work for it.
12551 app.adjType = "fixed";
12552 app.adjSeq = mAdjSeq;
12553 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012554 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012555 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12556 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012557 }
12558
12559 final boolean hadForegroundActivities = app.foregroundActivities;
12560
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012561 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012562 app.adjSource = null;
12563 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012564 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012565 app.empty = false;
12566 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012567 app.foregroundActivities = false;
12568
12569 final int activitiesSize = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012570
The Android Open Source Project4df24232009-03-05 14:34:35 -080012571 // Determine the importance of the process, starting with most
12572 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012573 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012574 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012575 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012576 // The last app on the list is the foreground app.
12577 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012578 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012579 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012580 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012581 } else if (app.instrumentationClass != null) {
12582 // Don't want to kill running instrumentation.
12583 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012584 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012585 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012586 } else if (app.curReceiver != null ||
12587 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12588 // An app that is currently receiving a broadcast also
12589 // counts as being in the foreground.
12590 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012591 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012592 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012593 } else if (app.executingServices.size() > 0) {
12594 // An app that is currently executing a service callback also
12595 // counts as being in the foreground.
12596 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012597 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012598 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012599 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012600 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012601 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012602 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012603 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012604 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012605 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012606 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012607 // A very not-needed process. If this is lower in the lru list,
12608 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012609 adj = hiddenAdj;
12610 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012611 app.hidden = true;
12612 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012613 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012614 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012615
12616 // Examine all activities if not already foreground.
12617 if (!app.foregroundActivities && activitiesSize > 0) {
12618 for (int j = 0; j < activitiesSize; j++) {
12619 final ActivityRecord r = app.activities.get(j);
12620 if (r.visible) {
12621 // App has a visible activity; only upgrade adjustment.
12622 if (adj > VISIBLE_APP_ADJ) {
12623 adj = VISIBLE_APP_ADJ;
12624 app.adjType = "visible";
12625 }
12626 schedGroup = Process.THREAD_GROUP_DEFAULT;
12627 app.hidden = false;
12628 app.foregroundActivities = true;
12629 break;
12630 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
12631 || r.state == ActivityState.STOPPING) {
12632 // Only upgrade adjustment.
12633 if (adj > PERCEPTIBLE_APP_ADJ) {
12634 adj = PERCEPTIBLE_APP_ADJ;
12635 app.adjType = "stopping";
12636 }
12637 app.foregroundActivities = true;
12638 }
12639 }
12640 }
12641
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012642 if (adj > PERCEPTIBLE_APP_ADJ) {
12643 if (app.foregroundServices) {
12644 // The user is aware of this app, so make it visible.
12645 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012646 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012647 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012648 } else if (app.forcingToForeground != null) {
12649 // The user is aware of this app, so make it visible.
12650 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012651 app.adjType = "force-foreground";
12652 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012653 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012654 }
12655 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012656
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012657 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12658 // We don't want to kill the current heavy-weight process.
12659 adj = HEAVY_WEIGHT_APP_ADJ;
12660 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12661 app.adjType = "heavy";
12662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012663
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012664 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12665 // This process is hosting what we currently consider to be the
12666 // home app, so we don't want to let it go into the background.
12667 adj = HOME_APP_ADJ;
12668 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12669 app.adjType = "home";
12670 }
12671
Joe Onorato8a9b2202010-02-26 18:56:32 -080012672 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012673
The Android Open Source Project4df24232009-03-05 14:34:35 -080012674 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012675 // there are applications dependent on our services or providers, but
12676 // this gives us a baseline and makes sure we don't get into an
12677 // infinite recursion.
12678 app.adjSeq = mAdjSeq;
12679 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012680
Christopher Tate6fa95972009-06-05 18:43:55 -070012681 if (mBackupTarget != null && app == mBackupTarget.app) {
12682 // If possible we want to avoid killing apps while they're being backed up
12683 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012684 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012685 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012686 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012687 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012688 }
12689 }
12690
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012691 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12692 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012693 final long now = SystemClock.uptimeMillis();
12694 // This process is more important if the top activity is
12695 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012696 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012697 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012698 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012699 if (s.startRequested) {
12700 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12701 // This service has seen some activity within
12702 // recent memory, so we will keep its process ahead
12703 // of the background processes.
12704 if (adj > SECONDARY_SERVER_ADJ) {
12705 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012706 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012707 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012708 }
12709 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012710 // If we have let the service slide into the background
12711 // state, still have some text describing what it is doing
12712 // even though the service no longer has an impact.
12713 if (adj > SECONDARY_SERVER_ADJ) {
12714 app.adjType = "started-bg-services";
12715 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012716 // Don't kill this process because it is doing work; it
12717 // has said it is doing work.
12718 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012719 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012720 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12721 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012722 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012723 = s.connections.values().iterator();
12724 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012725 ArrayList<ConnectionRecord> clist = kt.next();
12726 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12727 // XXX should compute this based on the max of
12728 // all connected clients.
12729 ConnectionRecord cr = clist.get(i);
12730 if (cr.binding.client == app) {
12731 // Binding to ourself is not interesting.
12732 continue;
12733 }
12734 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12735 ProcessRecord client = cr.binding.client;
12736 int myHiddenAdj = hiddenAdj;
12737 if (myHiddenAdj > client.hiddenAdj) {
12738 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12739 myHiddenAdj = client.hiddenAdj;
12740 } else {
12741 myHiddenAdj = VISIBLE_APP_ADJ;
12742 }
12743 }
12744 int clientAdj = computeOomAdjLocked(
12745 client, myHiddenAdj, TOP_APP, true);
12746 if (adj > clientAdj) {
12747 adj = clientAdj >= VISIBLE_APP_ADJ
12748 ? clientAdj : VISIBLE_APP_ADJ;
12749 if (!client.hidden) {
12750 app.hidden = false;
12751 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012752 if (client.keeping) {
12753 app.keeping = true;
12754 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012755 app.adjType = "service";
12756 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12757 .REASON_SERVICE_IN_USE;
12758 app.adjSource = cr.binding.client;
12759 app.adjTarget = s.name;
12760 }
12761 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12762 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12763 schedGroup = Process.THREAD_GROUP_DEFAULT;
12764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012765 }
12766 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012767 ActivityRecord a = cr.activity;
12768 //if (a != null) {
12769 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12770 //}
12771 if (a != null && adj > FOREGROUND_APP_ADJ &&
12772 (a.state == ActivityState.RESUMED
12773 || a.state == ActivityState.PAUSING)) {
12774 adj = FOREGROUND_APP_ADJ;
12775 schedGroup = Process.THREAD_GROUP_DEFAULT;
12776 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012777 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012778 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12779 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012780 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012781 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012782 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012783 }
12784 }
12785 }
12786 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012787
Dianne Hackborn287952c2010-09-22 22:34:31 -070012788 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012789 // would like to avoid killing it unless it would prevent the current
12790 // application from running. By default we put the process in
12791 // with the rest of the background processes; as we scan through
12792 // its services we may bump it up from there.
12793 if (adj > hiddenAdj) {
12794 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012795 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012796 app.adjType = "bg-services";
12797 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012798 }
12799
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012800 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12801 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012802 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012803 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12804 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012805 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012806 if (cpr.clients.size() != 0) {
12807 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12808 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12809 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012810 if (client == app) {
12811 // Being our own client is not interesting.
12812 continue;
12813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012814 int myHiddenAdj = hiddenAdj;
12815 if (myHiddenAdj > client.hiddenAdj) {
12816 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12817 myHiddenAdj = client.hiddenAdj;
12818 } else {
12819 myHiddenAdj = FOREGROUND_APP_ADJ;
12820 }
12821 }
12822 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012823 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012824 if (adj > clientAdj) {
12825 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012826 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012827 if (!client.hidden) {
12828 app.hidden = false;
12829 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012830 if (client.keeping) {
12831 app.keeping = true;
12832 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012833 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012834 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12835 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012836 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012837 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012838 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012839 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12840 schedGroup = Process.THREAD_GROUP_DEFAULT;
12841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012842 }
12843 }
12844 // If the provider has external (non-framework) process
12845 // dependencies, ensure that its adjustment is at least
12846 // FOREGROUND_APP_ADJ.
12847 if (cpr.externals != 0) {
12848 if (adj > FOREGROUND_APP_ADJ) {
12849 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012850 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012851 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012852 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012853 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012854 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012855 }
12856 }
12857 }
12858 }
12859
12860 app.curRawAdj = adj;
12861
Joe Onorato8a9b2202010-02-26 18:56:32 -080012862 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012863 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12864 if (adj > app.maxAdj) {
12865 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012866 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012867 schedGroup = Process.THREAD_GROUP_DEFAULT;
12868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012869 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012870 if (adj < HIDDEN_APP_MIN_ADJ) {
12871 app.keeping = true;
12872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012873
12874 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012875 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012876
12877 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070012878 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
12879 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012880 }
12881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012882 return adj;
12883 }
12884
12885 /**
12886 * Ask a given process to GC right now.
12887 */
12888 final void performAppGcLocked(ProcessRecord app) {
12889 try {
12890 app.lastRequestedGc = SystemClock.uptimeMillis();
12891 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012892 if (app.reportLowMemory) {
12893 app.reportLowMemory = false;
12894 app.thread.scheduleLowMemory();
12895 } else {
12896 app.thread.processInBackground();
12897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012898 }
12899 } catch (Exception e) {
12900 // whatever.
12901 }
12902 }
12903
12904 /**
12905 * Returns true if things are idle enough to perform GCs.
12906 */
Josh Bartel7f208742010-02-25 11:01:44 -060012907 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012908 return mParallelBroadcasts.size() == 0
12909 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012910 && (mSleeping || (mMainStack.mResumedActivity != null &&
12911 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012912 }
12913
12914 /**
12915 * Perform GCs on all processes that are waiting for it, but only
12916 * if things are idle.
12917 */
12918 final void performAppGcsLocked() {
12919 final int N = mProcessesToGc.size();
12920 if (N <= 0) {
12921 return;
12922 }
Josh Bartel7f208742010-02-25 11:01:44 -060012923 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012924 while (mProcessesToGc.size() > 0) {
12925 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012926 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012927 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12928 <= SystemClock.uptimeMillis()) {
12929 // To avoid spamming the system, we will GC processes one
12930 // at a time, waiting a few seconds between each.
12931 performAppGcLocked(proc);
12932 scheduleAppGcsLocked();
12933 return;
12934 } else {
12935 // It hasn't been long enough since we last GCed this
12936 // process... put it in the list to wait for its time.
12937 addProcessToGcListLocked(proc);
12938 break;
12939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012940 }
12941 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012942
12943 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012944 }
12945 }
12946
12947 /**
12948 * If all looks good, perform GCs on all processes waiting for them.
12949 */
12950 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012951 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012952 performAppGcsLocked();
12953 return;
12954 }
12955 // Still not idle, wait some more.
12956 scheduleAppGcsLocked();
12957 }
12958
12959 /**
12960 * Schedule the execution of all pending app GCs.
12961 */
12962 final void scheduleAppGcsLocked() {
12963 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012964
12965 if (mProcessesToGc.size() > 0) {
12966 // Schedule a GC for the time to the next process.
12967 ProcessRecord proc = mProcessesToGc.get(0);
12968 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12969
12970 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12971 long now = SystemClock.uptimeMillis();
12972 if (when < (now+GC_TIMEOUT)) {
12973 when = now + GC_TIMEOUT;
12974 }
12975 mHandler.sendMessageAtTime(msg, when);
12976 }
12977 }
12978
12979 /**
12980 * Add a process to the array of processes waiting to be GCed. Keeps the
12981 * list in sorted order by the last GC time. The process can't already be
12982 * on the list.
12983 */
12984 final void addProcessToGcListLocked(ProcessRecord proc) {
12985 boolean added = false;
12986 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12987 if (mProcessesToGc.get(i).lastRequestedGc <
12988 proc.lastRequestedGc) {
12989 added = true;
12990 mProcessesToGc.add(i+1, proc);
12991 break;
12992 }
12993 }
12994 if (!added) {
12995 mProcessesToGc.add(0, proc);
12996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012997 }
12998
12999 /**
13000 * Set up to ask a process to GC itself. This will either do it
13001 * immediately, or put it on the list of processes to gc the next
13002 * time things are idle.
13003 */
13004 final void scheduleAppGcLocked(ProcessRecord app) {
13005 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013006 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013007 return;
13008 }
13009 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013010 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013011 scheduleAppGcsLocked();
13012 }
13013 }
13014
Dianne Hackborn287952c2010-09-22 22:34:31 -070013015 final void checkExcessivePowerUsageLocked(boolean doKills) {
13016 updateCpuStatsNow();
13017
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013018 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013019 boolean doWakeKills = doKills;
13020 boolean doCpuKills = doKills;
13021 if (mLastPowerCheckRealtime == 0) {
13022 doWakeKills = false;
13023 }
13024 if (mLastPowerCheckUptime == 0) {
13025 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013026 }
13027 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070013028 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013029 }
13030 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013031 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
13032 final long curUptime = SystemClock.uptimeMillis();
13033 final long uptimeSince = curUptime - mLastPowerCheckUptime;
13034 mLastPowerCheckRealtime = curRealtime;
13035 mLastPowerCheckUptime = curUptime;
13036 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
13037 doWakeKills = false;
13038 }
13039 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
13040 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013041 }
13042 int i = mLruProcesses.size();
13043 while (i > 0) {
13044 i--;
13045 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013046 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013047 long wtime;
13048 synchronized (stats) {
13049 wtime = stats.getProcessWakeTime(app.info.uid,
13050 app.pid, curRealtime);
13051 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013052 long wtimeUsed = wtime - app.lastWakeTime;
13053 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
13054 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013055 StringBuilder sb = new StringBuilder(128);
13056 sb.append("Wake for ");
13057 app.toShortString(sb);
13058 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013059 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013060 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013061 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013062 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013063 sb.append((wtimeUsed*100)/realtimeSince);
13064 sb.append("%)");
13065 Slog.i(TAG, sb.toString());
13066 sb.setLength(0);
13067 sb.append("CPU for ");
13068 app.toShortString(sb);
13069 sb.append(": over ");
13070 TimeUtils.formatDuration(uptimeSince, sb);
13071 sb.append(" used ");
13072 TimeUtils.formatDuration(cputimeUsed, sb);
13073 sb.append(" (");
13074 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013075 sb.append("%)");
13076 Slog.i(TAG, sb.toString());
13077 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013078 // If a process has held a wake lock for more
13079 // than 50% of the time during this period,
13080 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070013081 if (doWakeKills && realtimeSince > 0
13082 && ((wtimeUsed*100)/realtimeSince) >= 50) {
13083 synchronized (stats) {
13084 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
13085 realtimeSince, wtimeUsed);
13086 }
13087 Slog.w(TAG, "Excessive wake lock in " + app.processName
13088 + " (pid " + app.pid + "): held " + wtimeUsed
13089 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013090 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13091 app.processName, app.setAdj, "excessive wake lock");
13092 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013093 } else if (doCpuKills && uptimeSince > 0
13094 && ((cputimeUsed*100)/uptimeSince) >= 50) {
13095 synchronized (stats) {
13096 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
13097 uptimeSince, cputimeUsed);
13098 }
13099 Slog.w(TAG, "Excessive CPU in " + app.processName
13100 + " (pid " + app.pid + "): used " + cputimeUsed
13101 + " during " + uptimeSince);
13102 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13103 app.processName, app.setAdj, "excessive cpu");
13104 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013105 } else {
13106 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013107 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013108 }
13109 }
13110 }
13111 }
13112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013113 private final boolean updateOomAdjLocked(
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013114 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013115 app.hiddenAdj = hiddenAdj;
13116
13117 if (app.thread == null) {
13118 return true;
13119 }
13120
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013121 boolean success = true;
13122
Dianne Hackborn287952c2010-09-22 22:34:31 -070013123 final boolean wasKeeping = app.keeping;
13124
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013125 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013126
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013127 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013128 if (app.curRawAdj != app.setRawAdj) {
13129 if (app.curRawAdj > FOREGROUND_APP_ADJ
13130 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13131 // If this app is transitioning from foreground to
13132 // non-foreground, have it do a gc.
13133 scheduleAppGcLocked(app);
13134 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13135 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13136 // Likewise do a gc when an app is moving in to the
13137 // background (such as a service stopping).
13138 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013139 }
13140
13141 if (wasKeeping && !app.keeping) {
13142 // This app is no longer something we want to keep. Note
13143 // its current wake lock time to later know to kill it if
13144 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013145 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
13146 synchronized (stats) {
13147 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
13148 app.pid, SystemClock.elapsedRealtime());
13149 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013150 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013151 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013153 app.setRawAdj = app.curRawAdj;
13154 }
13155 if (adj != app.setAdj) {
13156 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013157 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013158 TAG, "Set app " + app.processName +
13159 " oom adj to " + adj);
13160 app.setAdj = adj;
13161 } else {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013162 success = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013163 }
13164 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013165 if (app.setSchedGroup != app.curSchedGroup) {
13166 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013167 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013168 "Setting process group of " + app.processName
13169 + " to " + app.curSchedGroup);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013170 if (app.waitingToKill != null &&
13171 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -070013172 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013173 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13174 app.processName, app.setAdj, app.waitingToKill);
13175 Process.killProcessQuiet(app.pid);
13176 } else {
13177 if (true) {
13178 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013179 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013180 Process.setProcessGroup(app.pid, app.curSchedGroup);
13181 } catch (Exception e) {
13182 Slog.w(TAG, "Failed setting process group of " + app.pid
13183 + " to " + app.curSchedGroup);
13184 e.printStackTrace();
13185 } finally {
13186 Binder.restoreCallingIdentity(oldId);
13187 }
13188 }
13189 if (false) {
13190 if (app.thread != null) {
13191 try {
13192 app.thread.setSchedulingGroup(app.curSchedGroup);
13193 } catch (RemoteException e) {
13194 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013195 }
13196 }
13197 }
13198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013199 }
13200
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013201 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013202 }
13203
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013204 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013205 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013206 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013207 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013208 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013209 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013210 }
13211 }
13212 return resumedActivity;
13213 }
13214
13215 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013216 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013217 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13218 int curAdj = app.curAdj;
13219 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13220 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13221
13222 mAdjSeq++;
13223
13224 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13225 if (res) {
13226 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13227 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13228 if (nowHidden != wasHidden) {
13229 // Changed to/from hidden state, so apps after it in the LRU
13230 // list may also be changed.
13231 updateOomAdjLocked();
13232 }
13233 }
13234 return res;
13235 }
13236
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013237 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013238 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013239 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013240 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13241
13242 if (false) {
13243 RuntimeException e = new RuntimeException();
13244 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013245 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013246 }
13247
13248 mAdjSeq++;
13249
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013250 // Let's determine how many processes we have running vs.
13251 // how many slots we have for background processes; we may want
13252 // to put multiple processes in a slot of there are enough of
13253 // them.
13254 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13255 int factor = (mLruProcesses.size()-4)/numSlots;
13256 if (factor < 1) factor = 1;
13257 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013258 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013260 // First try updating the OOM adjustment for each of the
13261 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013262 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013263 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
13264 while (i > 0) {
13265 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013266 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013267 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013268 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013269 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013270 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013271 step++;
13272 if (step >= factor) {
13273 step = 0;
13274 curHiddenAdj++;
13275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013276 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013277 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070013278 if (!app.killedBackground) {
13279 numHidden++;
13280 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070013281 Slog.i(TAG, "No longer want " + app.processName
13282 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013283 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13284 app.processName, app.setAdj, "too many background");
13285 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070013286 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013287 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013288 }
13289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013290 } else {
13291 didOomAdj = false;
13292 }
13293 }
13294
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013295 // If we return false, we will fall back on killing processes to
13296 // have a fixed limit. Do this if a limit has been requested; else
13297 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013298 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13299 }
13300
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013301 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013302 synchronized (this) {
13303 int i;
13304
13305 // First remove any unused application processes whose package
13306 // has been removed.
13307 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13308 final ProcessRecord app = mRemovedProcesses.get(i);
13309 if (app.activities.size() == 0
13310 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013311 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013312 TAG, "Exiting empty application process "
13313 + app.processName + " ("
13314 + (app.thread != null ? app.thread.asBinder() : null)
13315 + ")\n");
13316 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013317 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13318 app.processName, app.setAdj, "empty");
13319 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013320 } else {
13321 try {
13322 app.thread.scheduleExit();
13323 } catch (Exception e) {
13324 // Ignore exceptions.
13325 }
13326 }
13327 cleanUpApplicationRecordLocked(app, false, -1);
13328 mRemovedProcesses.remove(i);
13329
13330 if (app.persistent) {
13331 if (app.persistent) {
13332 addAppLocked(app.info);
13333 }
13334 }
13335 }
13336 }
13337
13338 // Now try updating the OOM adjustment for each of the
13339 // application processes based on their current state.
13340 // If the setOomAdj() API is not supported, then go with our
13341 // back-up plan...
13342 if (!updateOomAdjLocked()) {
13343
13344 // Count how many processes are running services.
13345 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013346 for (i=mLruProcesses.size()-1; i>=0; i--) {
13347 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013348
13349 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013350 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013351 // Don't count processes holding services against our
13352 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013353 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013354 TAG, "Not trimming app " + app + " with services: "
13355 + app.services);
13356 numServiceProcs++;
13357 }
13358 }
13359
13360 int curMaxProcs = mProcessLimit;
13361 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13362 if (mAlwaysFinishActivities) {
13363 curMaxProcs = 1;
13364 }
13365 curMaxProcs += numServiceProcs;
13366
13367 // Quit as many processes as we can to get down to the desired
13368 // process count. First remove any processes that no longer
13369 // have activites running in them.
13370 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013371 i<mLruProcesses.size()
13372 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013373 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013374 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013375 // Quit an application only if it is not currently
13376 // running any activities.
13377 if (!app.persistent && app.activities.size() == 0
13378 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013379 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013380 TAG, "Exiting empty application process "
13381 + app.processName + " ("
13382 + (app.thread != null ? app.thread.asBinder() : null)
13383 + ")\n");
13384 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013385 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13386 app.processName, app.setAdj, "empty");
13387 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013388 } else {
13389 try {
13390 app.thread.scheduleExit();
13391 } catch (Exception e) {
13392 // Ignore exceptions.
13393 }
13394 }
13395 // todo: For now we assume the application is not buggy
13396 // or evil, and will quit as a result of our request.
13397 // Eventually we need to drive this off of the death
13398 // notification, and kill the process if it takes too long.
13399 cleanUpApplicationRecordLocked(app, false, i);
13400 i--;
13401 }
13402 }
13403
13404 // If we still have too many processes, now from the least
13405 // recently used process we start finishing activities.
Joe Onorato43a17652011-04-06 19:22:23 -070013406 if (false) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013407 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013408 " of " + curMaxProcs + " processes");
13409 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013410 i<mLruProcesses.size()
13411 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013412 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013413 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013414 // Quit the application only if we have a state saved for
13415 // all of its activities.
13416 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013417 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013418 int NUMA = app.activities.size();
13419 int j;
Joe Onorato43a17652011-04-06 19:22:23 -070013420 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013421 TAG, "Looking to quit " + app.processName);
13422 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013423 ActivityRecord r = app.activities.get(j);
Joe Onorato43a17652011-04-06 19:22:23 -070013424 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013425 TAG, " " + r.intent.getComponent().flattenToShortString()
13426 + ": frozen=" + r.haveState + ", visible=" + r.visible);
13427 canQuit = (r.haveState || !r.stateNotNeeded)
13428 && !r.visible && r.stopped;
13429 }
13430 if (canQuit) {
13431 // Finish all of the activities, and then the app itself.
13432 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013433 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013434 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013435 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013436 }
13437 r.resultTo = null;
13438 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013439 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013440 + app.processName + " ("
13441 + (app.thread != null ? app.thread.asBinder() : null)
13442 + ")\n");
13443 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013444 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13445 app.processName, app.setAdj, "old background");
13446 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013447 } else {
13448 try {
13449 app.thread.scheduleExit();
13450 } catch (Exception e) {
13451 // Ignore exceptions.
13452 }
13453 }
13454 // todo: For now we assume the application is not buggy
13455 // or evil, and will quit as a result of our request.
13456 // Eventually we need to drive this off of the death
13457 // notification, and kill the process if it takes too long.
13458 cleanUpApplicationRecordLocked(app, false, i);
13459 i--;
13460 //dump();
13461 }
13462 }
13463
13464 }
13465
13466 int curMaxActivities = MAX_ACTIVITIES;
13467 if (mAlwaysFinishActivities) {
13468 curMaxActivities = 1;
13469 }
13470
13471 // Finally, if there are too many activities now running, try to
13472 // finish as many as we can to get back down to the limit.
13473 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013474 i<mMainStack.mLRUActivities.size()
13475 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013476 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013477 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013478 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013479
13480 // We can finish this one if we have its icicle saved and
13481 // it is not persistent.
13482 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013483 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013484 final int origSize = mMainStack.mLRUActivities.size();
13485 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013486
13487 // This will remove it from the LRU list, so keep
13488 // our index at the same value. Note that this check to
13489 // see if the size changes is just paranoia -- if
13490 // something unexpected happens, we don't want to end up
13491 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013492 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013493 i--;
13494 }
13495 }
13496 }
13497 }
13498 }
13499
13500 /** This method sends the specified signal to each of the persistent apps */
13501 public void signalPersistentProcesses(int sig) throws RemoteException {
13502 if (sig != Process.SIGNAL_USR1) {
13503 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13504 }
13505
13506 synchronized (this) {
13507 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13508 != PackageManager.PERMISSION_GRANTED) {
13509 throw new SecurityException("Requires permission "
13510 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13511 }
13512
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013513 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13514 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013515 if (r.thread != null && r.persistent) {
13516 Process.sendSignal(r.pid, sig);
13517 }
13518 }
13519 }
13520 }
13521
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013522 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013523 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013524
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013525 try {
13526 synchronized (this) {
13527 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13528 // its own permission.
13529 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13530 != PackageManager.PERMISSION_GRANTED) {
13531 throw new SecurityException("Requires permission "
13532 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013533 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013534
13535 if (start && fd == null) {
13536 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013537 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013538
13539 ProcessRecord proc = null;
13540 try {
13541 int pid = Integer.parseInt(process);
13542 synchronized (mPidsSelfLocked) {
13543 proc = mPidsSelfLocked.get(pid);
13544 }
13545 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013546 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013547
13548 if (proc == null) {
13549 HashMap<String, SparseArray<ProcessRecord>> all
13550 = mProcessNames.getMap();
13551 SparseArray<ProcessRecord> procs = all.get(process);
13552 if (procs != null && procs.size() > 0) {
13553 proc = procs.valueAt(0);
13554 }
13555 }
13556
13557 if (proc == null || proc.thread == null) {
13558 throw new IllegalArgumentException("Unknown process: " + process);
13559 }
13560
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013561 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13562 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013563 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13564 throw new SecurityException("Process not debuggable: " + proc);
13565 }
13566 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013567
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013568 proc.thread.profilerControl(start, path, fd);
13569 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013570 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013571 }
13572 } catch (RemoteException e) {
13573 throw new IllegalStateException("Process disappeared");
13574 } finally {
13575 if (fd != null) {
13576 try {
13577 fd.close();
13578 } catch (IOException e) {
13579 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013580 }
13581 }
13582 }
Andy McFadden824c5102010-07-09 16:26:57 -070013583
13584 public boolean dumpHeap(String process, boolean managed,
13585 String path, ParcelFileDescriptor fd) throws RemoteException {
13586
13587 try {
13588 synchronized (this) {
13589 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13590 // its own permission (same as profileControl).
13591 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13592 != PackageManager.PERMISSION_GRANTED) {
13593 throw new SecurityException("Requires permission "
13594 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13595 }
13596
13597 if (fd == null) {
13598 throw new IllegalArgumentException("null fd");
13599 }
13600
13601 ProcessRecord proc = null;
13602 try {
13603 int pid = Integer.parseInt(process);
13604 synchronized (mPidsSelfLocked) {
13605 proc = mPidsSelfLocked.get(pid);
13606 }
13607 } catch (NumberFormatException e) {
13608 }
13609
13610 if (proc == null) {
13611 HashMap<String, SparseArray<ProcessRecord>> all
13612 = mProcessNames.getMap();
13613 SparseArray<ProcessRecord> procs = all.get(process);
13614 if (procs != null && procs.size() > 0) {
13615 proc = procs.valueAt(0);
13616 }
13617 }
13618
13619 if (proc == null || proc.thread == null) {
13620 throw new IllegalArgumentException("Unknown process: " + process);
13621 }
13622
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013623 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13624 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013625 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13626 throw new SecurityException("Process not debuggable: " + proc);
13627 }
13628 }
13629
13630 proc.thread.dumpHeap(managed, path, fd);
13631 fd = null;
13632 return true;
13633 }
13634 } catch (RemoteException e) {
13635 throw new IllegalStateException("Process disappeared");
13636 } finally {
13637 if (fd != null) {
13638 try {
13639 fd.close();
13640 } catch (IOException e) {
13641 }
13642 }
13643 }
13644 }
13645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013646 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13647 public void monitor() {
13648 synchronized (this) { }
13649 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013650
13651 public void onCoreSettingsChange(Bundle settings) {
13652 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13653 ProcessRecord processRecord = mLruProcesses.get(i);
13654 try {
13655 if (processRecord.thread != null) {
13656 processRecord.thread.setCoreSettings(settings);
13657 }
13658 } catch (RemoteException re) {
13659 /* ignore */
13660 }
13661 }
13662 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070013663
13664 // Multi-user methods
13665
13666 public boolean switchUser(int userid) {
13667 // TODO
13668 return true;
13669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013670}