blob: 9471eff95f3f5ab67dc6a3e648c607ccdc536340 [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
19import com.android.internal.os.BatteryStatsImpl;
20import com.android.internal.os.RuntimeInit;
21import com.android.server.IntentResolver;
22import com.android.server.ProcessMap;
23import com.android.server.ProcessStats;
24import com.android.server.SystemServer;
25import com.android.server.Watchdog;
26import com.android.server.WindowManagerService;
27
28import android.app.Activity;
29import android.app.ActivityManager;
30import android.app.ActivityManagerNative;
31import android.app.ActivityThread;
32import android.app.AlertDialog;
33import android.app.Dialog;
34import android.app.IActivityWatcher;
35import android.app.IApplicationThread;
36import android.app.IInstrumentationWatcher;
37import android.app.IIntentReceiver;
38import android.app.IIntentSender;
39import android.app.IServiceConnection;
40import android.app.IThumbnailReceiver;
41import android.app.Instrumentation;
42import android.app.PendingIntent;
43import android.app.ResultInfo;
44import android.content.ComponentName;
45import android.content.ContentResolver;
46import android.content.Context;
47import android.content.Intent;
48import android.content.IntentFilter;
49import android.content.pm.ActivityInfo;
50import android.content.pm.ApplicationInfo;
51import android.content.pm.ConfigurationInfo;
52import android.content.pm.IPackageDataObserver;
53import android.content.pm.IPackageManager;
54import android.content.pm.InstrumentationInfo;
55import android.content.pm.PackageManager;
56import android.content.pm.ProviderInfo;
57import android.content.pm.ResolveInfo;
58import android.content.pm.ServiceInfo;
59import android.content.res.Configuration;
60import android.graphics.Bitmap;
61import android.net.Uri;
62import android.os.Binder;
63import android.os.Bundle;
64import android.os.Environment;
65import android.os.FileUtils;
66import android.os.Handler;
67import android.os.IBinder;
68import android.os.IPermissionController;
69import android.os.Looper;
70import android.os.Message;
71import android.os.Parcel;
72import android.os.ParcelFileDescriptor;
73import android.os.PowerManager;
74import android.os.Process;
75import android.os.RemoteException;
76import android.os.ServiceManager;
77import android.os.SystemClock;
78import android.os.SystemProperties;
79import android.provider.Checkin;
80import android.provider.Settings;
81import android.text.TextUtils;
82import android.util.Config;
83import android.util.EventLog;
84import android.util.Log;
85import android.util.PrintWriterPrinter;
86import android.util.SparseArray;
87import android.view.Gravity;
88import android.view.LayoutInflater;
89import android.view.View;
90import android.view.WindowManager;
91import android.view.WindowManagerPolicy;
92
93import dalvik.system.Zygote;
94
95import java.io.File;
96import java.io.FileDescriptor;
97import java.io.FileInputStream;
98import java.io.FileNotFoundException;
99import java.io.PrintWriter;
100import java.lang.IllegalStateException;
101import java.lang.ref.WeakReference;
102import java.util.ArrayList;
103import java.util.HashMap;
104import java.util.HashSet;
105import java.util.Iterator;
106import java.util.List;
107import java.util.Locale;
108import java.util.Map;
109
110public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
111 static final String TAG = "ActivityManager";
112 static final boolean DEBUG = false;
113 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
114 static final boolean DEBUG_SWITCH = localLOGV || false;
115 static final boolean DEBUG_TASKS = localLOGV || false;
116 static final boolean DEBUG_PAUSE = localLOGV || false;
117 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
118 static final boolean DEBUG_TRANSITION = localLOGV || false;
119 static final boolean DEBUG_BROADCAST = localLOGV || false;
120 static final boolean DEBUG_SERVICE = localLOGV || false;
121 static final boolean DEBUG_VISBILITY = localLOGV || false;
122 static final boolean DEBUG_PROCESSES = localLOGV || false;
123 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700124 static final boolean DEBUG_RESULTS = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 static final boolean VALIDATE_TOKENS = false;
126 static final boolean SHOW_ACTIVITY_START_TIME = true;
127
128 // Control over CPU and battery monitoring.
129 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
130 static final boolean MONITOR_CPU_USAGE = true;
131 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
132 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
133 static final boolean MONITOR_THREAD_CPU_USAGE = false;
134
135 // Event log tags
136 static final int LOG_CONFIGURATION_CHANGED = 2719;
137 static final int LOG_CPU = 2721;
138 static final int LOG_AM_FINISH_ACTIVITY = 30001;
139 static final int LOG_TASK_TO_FRONT = 30002;
140 static final int LOG_AM_NEW_INTENT = 30003;
141 static final int LOG_AM_CREATE_TASK = 30004;
142 static final int LOG_AM_CREATE_ACTIVITY = 30005;
143 static final int LOG_AM_RESTART_ACTIVITY = 30006;
144 static final int LOG_AM_RESUME_ACTIVITY = 30007;
145 static final int LOG_ANR = 30008;
146 static final int LOG_ACTIVITY_LAUNCH_TIME = 30009;
147 static final int LOG_AM_PROCESS_BOUND = 30010;
148 static final int LOG_AM_PROCESS_DIED = 30011;
149 static final int LOG_AM_FAILED_TO_PAUSE_ACTIVITY = 30012;
150 static final int LOG_AM_PAUSE_ACTIVITY = 30013;
151 static final int LOG_AM_PROCESS_START = 30014;
152 static final int LOG_AM_PROCESS_BAD = 30015;
153 static final int LOG_AM_PROCESS_GOOD = 30016;
154 static final int LOG_AM_LOW_MEMORY = 30017;
155 static final int LOG_AM_DESTROY_ACTIVITY = 30018;
156 static final int LOG_AM_RELAUNCH_RESUME_ACTIVITY = 30019;
157 static final int LOG_AM_RELAUNCH_ACTIVITY = 30020;
158 static final int LOG_AM_KILL_FOR_MEMORY = 30023;
159 static final int LOG_AM_BROADCAST_DISCARD_FILTER = 30024;
160 static final int LOG_AM_BROADCAST_DISCARD_APP = 30025;
161 static final int LOG_AM_CREATE_SERVICE = 30030;
162 static final int LOG_AM_DESTROY_SERVICE = 30031;
163 static final int LOG_AM_PROCESS_CRASHED_TOO_MUCH = 30032;
164 static final int LOG_AM_DROP_PROCESS = 30033;
165 static final int LOG_AM_SERVICE_CRASHED_TOO_MUCH = 30034;
166 static final int LOG_AM_SCHEDULE_SERVICE_RESTART = 30035;
167 static final int LOG_AM_PROVIDER_LOST_PROCESS = 30036;
168
169 static final int LOG_BOOT_PROGRESS_AMS_READY = 3040;
170 static final int LOG_BOOT_PROGRESS_ENABLE_SCREEN = 3050;
171
Dianne Hackborn1655be42009-05-08 14:29:01 -0700172 // The flags that are set for all calls we make to the package manager.
173 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES
174 | PackageManager.GET_SUPPORTS_DENSITIES;
175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 private static final String SYSTEM_SECURE = "ro.secure";
177
178 // This is the maximum number of application processes we would like
179 // to have running. Due to the asynchronous nature of things, we can
180 // temporarily go beyond this limit.
181 static final int MAX_PROCESSES = 2;
182
183 // Set to false to leave processes running indefinitely, relying on
184 // the kernel killing them as resources are required.
185 static final boolean ENFORCE_PROCESS_LIMIT = false;
186
187 // This is the maximum number of activities that we would like to have
188 // running at a given time.
189 static final int MAX_ACTIVITIES = 20;
190
191 // Maximum number of recent tasks that we can remember.
192 static final int MAX_RECENT_TASKS = 20;
193
194 // How long until we reset a task when the user returns to it. Currently
195 // 30 minutes.
196 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
197
198 // Set to true to disable the icon that is shown while a new activity
199 // is being started.
200 static final boolean SHOW_APP_STARTING_ICON = true;
201
202 // How long we wait until giving up on the last activity to pause. This
203 // is short because it directly impacts the responsiveness of starting the
204 // next activity.
205 static final int PAUSE_TIMEOUT = 500;
206
207 /**
208 * How long we can hold the launch wake lock before giving up.
209 */
210 static final int LAUNCH_TIMEOUT = 10*1000;
211
212 // How long we wait for a launched process to attach to the activity manager
213 // before we decide it's never going to come up for real.
214 static final int PROC_START_TIMEOUT = 10*1000;
215
216 // How long we wait until giving up on the last activity telling us it
217 // is idle.
218 static final int IDLE_TIMEOUT = 10*1000;
219
220 // How long to wait after going idle before forcing apps to GC.
221 static final int GC_TIMEOUT = 5*1000;
222
223 // How long we wait until giving up on an activity telling us it has
224 // finished destroying itself.
225 static final int DESTROY_TIMEOUT = 10*1000;
226
227 // How long we allow a receiver to run before giving up on it.
228 static final int BROADCAST_TIMEOUT = 10*1000;
229
230 // How long we wait for a service to finish executing.
231 static final int SERVICE_TIMEOUT = 20*1000;
232
233 // How long a service needs to be running until restarting its process
234 // is no longer considered to be a relaunch of the service.
235 static final int SERVICE_RESTART_DURATION = 5*1000;
236
237 // Maximum amount of time for there to be no activity on a service before
238 // we consider it non-essential and allow its process to go on the
239 // LRU background list.
240 static final int MAX_SERVICE_INACTIVITY = 10*60*1000;
241
242 // How long we wait until we timeout on key dispatching.
243 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
244
245 // The minimum time we allow between crashes, for us to consider this
246 // application to be bad and stop and its services and reject broadcasts.
247 static final int MIN_CRASH_INTERVAL = 60*1000;
248
249 // How long we wait until we timeout on key dispatching during instrumentation.
250 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
251
252 // OOM adjustments for processes in various states:
253
254 // This is a process without anything currently running in it. Definitely
255 // the first to go! Value set in system/rootdir/init.rc on startup.
256 // This value is initalized in the constructor, careful when refering to
257 // this static variable externally.
258 static int EMPTY_APP_ADJ;
259
260 // This is a process with a content provider that does not have any clients
261 // attached to it. If it did have any clients, its adjustment would be the
262 // one for the highest-priority of those processes.
263 static int CONTENT_PROVIDER_ADJ;
264
265 // This is a process only hosting activities that are not visible,
266 // so it can be killed without any disruption. Value set in
267 // system/rootdir/init.rc on startup.
268 final int HIDDEN_APP_MAX_ADJ;
269 static int HIDDEN_APP_MIN_ADJ;
270
The Android Open Source Project4df24232009-03-05 14:34:35 -0800271 // This is a process holding the home application -- we want to try
272 // avoiding killing it, even if it would normally be in the background,
273 // because the user interacts with it so much.
274 final int HOME_APP_ADJ;
275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 // This is a process holding a secondary server -- killing it will not
277 // have much of an impact as far as the user is concerned. Value set in
278 // system/rootdir/init.rc on startup.
279 final int SECONDARY_SERVER_ADJ;
280
281 // This is a process only hosting activities that are visible to the
282 // user, so we'd prefer they don't disappear. Value set in
283 // system/rootdir/init.rc on startup.
284 final int VISIBLE_APP_ADJ;
285
286 // This is the process running the current foreground app. We'd really
287 // rather not kill it! Value set in system/rootdir/init.rc on startup.
288 final int FOREGROUND_APP_ADJ;
289
290 // This is a process running a core server, such as telephony. Definitely
291 // don't want to kill it, but doing so is not completely fatal.
292 static final int CORE_SERVER_ADJ = -12;
293
294 // The system process runs at the default adjustment.
295 static final int SYSTEM_ADJ = -16;
296
297 // Memory pages are 4K.
298 static final int PAGE_SIZE = 4*1024;
299
300 // Corresponding memory levels for above adjustments.
301 final int EMPTY_APP_MEM;
302 final int HIDDEN_APP_MEM;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800303 final int HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 final int SECONDARY_SERVER_MEM;
305 final int VISIBLE_APP_MEM;
306 final int FOREGROUND_APP_MEM;
307
308 final int MY_PID;
309
310 static final String[] EMPTY_STRING_ARRAY = new String[0];
311
312 enum ActivityState {
313 INITIALIZING,
314 RESUMED,
315 PAUSING,
316 PAUSED,
317 STOPPING,
318 STOPPED,
319 FINISHING,
320 DESTROYING,
321 DESTROYED
322 }
323
324 /**
325 * The back history of all previous (and possibly still
326 * running) activities. It contains HistoryRecord objects.
327 */
328 final ArrayList mHistory = new ArrayList();
329
330 /**
331 * List of all active broadcasts that are to be executed immediately
332 * (without waiting for another broadcast to finish). Currently this only
333 * contains broadcasts to registered receivers, to avoid spinning up
334 * a bunch of processes to execute IntentReceiver components.
335 */
336 final ArrayList<BroadcastRecord> mParallelBroadcasts
337 = new ArrayList<BroadcastRecord>();
338
339 /**
340 * List of all active broadcasts that are to be executed one at a time.
341 * The object at the top of the list is the currently activity broadcasts;
342 * those after it are waiting for the top to finish..
343 */
344 final ArrayList<BroadcastRecord> mOrderedBroadcasts
345 = new ArrayList<BroadcastRecord>();
346
347 /**
348 * Set when we current have a BROADCAST_INTENT_MSG in flight.
349 */
350 boolean mBroadcastsScheduled = false;
351
352 /**
353 * Set to indicate whether to issue an onUserLeaving callback when a
354 * newly launched activity is being brought in front of us.
355 */
356 boolean mUserLeaving = false;
357
358 /**
359 * When we are in the process of pausing an activity, before starting the
360 * next one, this variable holds the activity that is currently being paused.
361 */
362 HistoryRecord mPausingActivity = null;
363
364 /**
365 * Current activity that is resumed, or null if there is none.
366 */
367 HistoryRecord mResumedActivity = null;
368
369 /**
370 * Activity we have told the window manager to have key focus.
371 */
372 HistoryRecord mFocusedActivity = null;
373
374 /**
375 * This is the last activity that we put into the paused state. This is
376 * used to determine if we need to do an activity transition while sleeping,
377 * when we normally hold the top activity paused.
378 */
379 HistoryRecord mLastPausedActivity = null;
380
381 /**
382 * List of activities that are waiting for a new activity
383 * to become visible before completing whatever operation they are
384 * supposed to do.
385 */
386 final ArrayList mWaitingVisibleActivities = new ArrayList();
387
388 /**
389 * List of activities that are ready to be stopped, but waiting
390 * for the next activity to settle down before doing so. It contains
391 * HistoryRecord objects.
392 */
393 final ArrayList<HistoryRecord> mStoppingActivities
394 = new ArrayList<HistoryRecord>();
395
396 /**
397 * List of intents that were used to start the most recent tasks.
398 */
399 final ArrayList<TaskRecord> mRecentTasks
400 = new ArrayList<TaskRecord>();
401
402 /**
403 * List of activities that are ready to be finished, but waiting
404 * for the previous activity to settle down before doing so. It contains
405 * HistoryRecord objects.
406 */
407 final ArrayList mFinishingActivities = new ArrayList();
408
409 /**
410 * All of the applications we currently have running organized by name.
411 * The keys are strings of the application package name (as
412 * returned by the package manager), and the keys are ApplicationRecord
413 * objects.
414 */
415 final ProcessMap<ProcessRecord> mProcessNames
416 = new ProcessMap<ProcessRecord>();
417
418 /**
419 * The last time that various processes have crashed.
420 */
421 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
422
423 /**
424 * Set of applications that we consider to be bad, and will reject
425 * incoming broadcasts from (which the user has no control over).
426 * Processes are added to this set when they have crashed twice within
427 * a minimum amount of time; they are removed from it when they are
428 * later restarted (hopefully due to some user action). The value is the
429 * time it was added to the list.
430 */
431 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
432
433 /**
434 * All of the processes we currently have running organized by pid.
435 * The keys are the pid running the application.
436 *
437 * <p>NOTE: This object is protected by its own lock, NOT the global
438 * activity manager lock!
439 */
440 final SparseArray<ProcessRecord> mPidsSelfLocked
441 = new SparseArray<ProcessRecord>();
442
443 /**
444 * All of the processes that have been forced to be foreground. The key
445 * is the pid of the caller who requested it (we hold a death
446 * link on it).
447 */
448 abstract class ForegroundToken implements IBinder.DeathRecipient {
449 int pid;
450 IBinder token;
451 }
452 final SparseArray<ForegroundToken> mForegroundProcesses
453 = new SparseArray<ForegroundToken>();
454
455 /**
456 * List of records for processes that someone had tried to start before the
457 * system was ready. We don't start them at that point, but ensure they
458 * are started by the time booting is complete.
459 */
460 final ArrayList<ProcessRecord> mProcessesOnHold
461 = new ArrayList<ProcessRecord>();
462
463 /**
464 * List of records for processes that we have started and are waiting
465 * for them to call back. This is really only needed when running in
466 * single processes mode, in which case we do not have a unique pid for
467 * each process.
468 */
469 final ArrayList<ProcessRecord> mStartingProcesses
470 = new ArrayList<ProcessRecord>();
471
472 /**
473 * List of persistent applications that are in the process
474 * of being started.
475 */
476 final ArrayList<ProcessRecord> mPersistentStartingProcesses
477 = new ArrayList<ProcessRecord>();
478
479 /**
480 * Processes that are being forcibly torn down.
481 */
482 final ArrayList<ProcessRecord> mRemovedProcesses
483 = new ArrayList<ProcessRecord>();
484
485 /**
486 * List of running applications, sorted by recent usage.
487 * The first entry in the list is the least recently used.
488 * It contains ApplicationRecord objects. This list does NOT include
489 * any persistent application records (since we never want to exit them).
490 */
491 final ArrayList<ProcessRecord> mLRUProcesses
492 = new ArrayList<ProcessRecord>();
493
494 /**
495 * List of processes that should gc as soon as things are idle.
496 */
497 final ArrayList<ProcessRecord> mProcessesToGc
498 = new ArrayList<ProcessRecord>();
499
500 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800501 * This is the process holding what we currently consider to be
502 * the "home" activity.
503 */
504 private ProcessRecord mHomeProcess;
505
506 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 * List of running activities, sorted by recent usage.
508 * The first entry in the list is the least recently used.
509 * It contains HistoryRecord objects.
510 */
511 private final ArrayList mLRUActivities = new ArrayList();
512
513 /**
514 * Set of PendingResultRecord objects that are currently active.
515 */
516 final HashSet mPendingResultRecords = new HashSet();
517
518 /**
519 * Set of IntentSenderRecord objects that are currently active.
520 */
521 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
522 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
523
524 /**
525 * Intent broadcast that we have tried to start, but are
526 * waiting for its application's process to be created. We only
527 * need one (instead of a list) because we always process broadcasts
528 * one at a time, so no others can be started while waiting for this
529 * one.
530 */
531 BroadcastRecord mPendingBroadcast = null;
532
533 /**
534 * Keeps track of all IIntentReceivers that have been registered for
535 * broadcasts. Hash keys are the receiver IBinder, hash value is
536 * a ReceiverList.
537 */
538 final HashMap mRegisteredReceivers = new HashMap();
539
540 /**
541 * Resolver for broadcast intents to registered receivers.
542 * Holds BroadcastFilter (subclass of IntentFilter).
543 */
544 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
545 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
546 @Override
547 protected boolean allowFilterResult(
548 BroadcastFilter filter, List<BroadcastFilter> dest) {
549 IBinder target = filter.receiverList.receiver.asBinder();
550 for (int i=dest.size()-1; i>=0; i--) {
551 if (dest.get(i).receiverList.receiver.asBinder() == target) {
552 return false;
553 }
554 }
555 return true;
556 }
557 };
558
559 /**
560 * State of all active sticky broadcasts. Keys are the action of the
561 * sticky Intent, values are an ArrayList of all broadcasted intents with
562 * that action (which should usually be one).
563 */
564 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
565 new HashMap<String, ArrayList<Intent>>();
566
567 /**
568 * All currently running services.
569 */
570 final HashMap<ComponentName, ServiceRecord> mServices =
571 new HashMap<ComponentName, ServiceRecord>();
572
573 /**
574 * All currently running services indexed by the Intent used to start them.
575 */
576 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
577 new HashMap<Intent.FilterComparison, ServiceRecord>();
578
579 /**
580 * All currently bound service connections. Keys are the IBinder of
581 * the client's IServiceConnection.
582 */
583 final HashMap<IBinder, ConnectionRecord> mServiceConnections
584 = new HashMap<IBinder, ConnectionRecord>();
585
586 /**
587 * List of services that we have been asked to start,
588 * but haven't yet been able to. It is used to hold start requests
589 * while waiting for their corresponding application thread to get
590 * going.
591 */
592 final ArrayList<ServiceRecord> mPendingServices
593 = new ArrayList<ServiceRecord>();
594
595 /**
596 * List of services that are scheduled to restart following a crash.
597 */
598 final ArrayList<ServiceRecord> mRestartingServices
599 = new ArrayList<ServiceRecord>();
600
601 /**
602 * List of services that are in the process of being stopped.
603 */
604 final ArrayList<ServiceRecord> mStoppingServices
605 = new ArrayList<ServiceRecord>();
606
607 /**
608 * List of PendingThumbnailsRecord objects of clients who are still
609 * waiting to receive all of the thumbnails for a task.
610 */
611 final ArrayList mPendingThumbnails = new ArrayList();
612
613 /**
614 * List of HistoryRecord objects that have been finished and must
615 * still report back to a pending thumbnail receiver.
616 */
617 final ArrayList mCancelledThumbnails = new ArrayList();
618
619 /**
620 * All of the currently running global content providers. Keys are a
621 * string containing the provider name and values are a
622 * ContentProviderRecord object containing the data about it. Note
623 * that a single provider may be published under multiple names, so
624 * there may be multiple entries here for a single one in mProvidersByClass.
625 */
626 final HashMap mProvidersByName = new HashMap();
627
628 /**
629 * All of the currently running global content providers. Keys are a
630 * string containing the provider's implementation class and values are a
631 * ContentProviderRecord object containing the data about it.
632 */
633 final HashMap mProvidersByClass = new HashMap();
634
635 /**
636 * List of content providers who have clients waiting for them. The
637 * application is currently being launched and the provider will be
638 * removed from this list once it is published.
639 */
640 final ArrayList mLaunchingProviders = new ArrayList();
641
642 /**
643 * Global set of specific Uri permissions that have been granted.
644 */
645 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
646 = new SparseArray<HashMap<Uri, UriPermission>>();
647
648 /**
649 * Thread-local storage used to carry caller permissions over through
650 * indirect content-provider access.
651 * @see #ActivityManagerService.openContentUri()
652 */
653 private class Identity {
654 public int pid;
655 public int uid;
656
657 Identity(int _pid, int _uid) {
658 pid = _pid;
659 uid = _uid;
660 }
661 }
662 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
663
664 /**
665 * All information we have collected about the runtime performance of
666 * any user id that can impact battery performance.
667 */
668 final BatteryStatsService mBatteryStatsService;
669
670 /**
671 * information about component usage
672 */
673 final UsageStatsService mUsageStatsService;
674
675 /**
676 * Current configuration information. HistoryRecord objects are given
677 * a reference to this object to indicate which configuration they are
678 * currently running in, so this object must be kept immutable.
679 */
680 Configuration mConfiguration = new Configuration();
681
682 /**
683 * List of initialization arguments to pass to all processes when binding applications to them.
684 * For example, references to the commonly used services.
685 */
686 HashMap<String, IBinder> mAppBindArgs;
687
688 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700689 * Temporary to avoid allocations. Protected by main lock.
690 */
691 final StringBuilder mStringBuilder = new StringBuilder(256);
692
693 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 * Used to control how we initialize the service.
695 */
696 boolean mStartRunning = false;
697 ComponentName mTopComponent;
698 String mTopAction;
699 String mTopData;
700 boolean mSystemReady = false;
701 boolean mBooting = false;
702
703 Context mContext;
704
705 int mFactoryTest;
706
707 /**
708 * Set while we are wanting to sleep, to prevent any
709 * activities from being started/resumed.
710 */
711 boolean mSleeping = false;
712
713 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700714 * Set if we are shutting down the system, similar to sleeping.
715 */
716 boolean mShuttingDown = false;
717
718 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 * Set when the system is going to sleep, until we have
720 * successfully paused the current activity and released our wake lock.
721 * At that point the system is allowed to actually sleep.
722 */
723 PowerManager.WakeLock mGoingToSleep;
724
725 /**
726 * We don't want to allow the device to go to sleep while in the process
727 * of launching an activity. This is primarily to allow alarm intent
728 * receivers to launch an activity and get that to run before the device
729 * goes back to sleep.
730 */
731 PowerManager.WakeLock mLaunchingActivity;
732
733 /**
734 * Task identifier that activities are currently being started
735 * in. Incremented each time a new task is created.
736 * todo: Replace this with a TokenSpace class that generates non-repeating
737 * integers that won't wrap.
738 */
739 int mCurTask = 1;
740
741 /**
742 * Current sequence id for oom_adj computation traversal.
743 */
744 int mAdjSeq = 0;
745
746 /**
747 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
748 * is set, indicating the user wants processes started in such a way
749 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
750 * running in each process (thus no pre-initialized process, etc).
751 */
752 boolean mSimpleProcessManagement = false;
753
754 /**
755 * System monitoring: number of processes that died since the last
756 * N procs were started.
757 */
758 int[] mProcDeaths = new int[20];
759
760 String mDebugApp = null;
761 boolean mWaitForDebugger = false;
762 boolean mDebugTransient = false;
763 String mOrigDebugApp = null;
764 boolean mOrigWaitForDebugger = false;
765 boolean mAlwaysFinishActivities = false;
766 IActivityWatcher mWatcher = null;
767
768 /**
769 * Callback of last caller to {@link #requestPss}.
770 */
771 Runnable mRequestPssCallback;
772
773 /**
774 * Remaining processes for which we are waiting results from the last
775 * call to {@link #requestPss}.
776 */
777 final ArrayList<ProcessRecord> mRequestPssList
778 = new ArrayList<ProcessRecord>();
779
780 /**
781 * Runtime statistics collection thread. This object's lock is used to
782 * protect all related state.
783 */
784 final Thread mProcessStatsThread;
785
786 /**
787 * Used to collect process stats when showing not responding dialog.
788 * Protected by mProcessStatsThread.
789 */
790 final ProcessStats mProcessStats = new ProcessStats(
791 MONITOR_THREAD_CPU_USAGE);
792 long mLastCpuTime = 0;
793 long mLastWriteTime = 0;
794
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700795 long mInitialStartTime = 0;
796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 /**
798 * Set to true after the system has finished booting.
799 */
800 boolean mBooted = false;
801
802 int mProcessLimit = 0;
803
804 WindowManagerService mWindowManager;
805
806 static ActivityManagerService mSelf;
807 static ActivityThread mSystemThread;
808
809 private final class AppDeathRecipient implements IBinder.DeathRecipient {
810 final ProcessRecord mApp;
811 final int mPid;
812 final IApplicationThread mAppThread;
813
814 AppDeathRecipient(ProcessRecord app, int pid,
815 IApplicationThread thread) {
816 if (localLOGV) Log.v(
817 TAG, "New death recipient " + this
818 + " for thread " + thread.asBinder());
819 mApp = app;
820 mPid = pid;
821 mAppThread = thread;
822 }
823
824 public void binderDied() {
825 if (localLOGV) Log.v(
826 TAG, "Death received in " + this
827 + " for thread " + mAppThread.asBinder());
828 removeRequestedPss(mApp);
829 synchronized(ActivityManagerService.this) {
830 appDiedLocked(mApp, mPid, mAppThread);
831 }
832 }
833 }
834
835 static final int SHOW_ERROR_MSG = 1;
836 static final int SHOW_NOT_RESPONDING_MSG = 2;
837 static final int SHOW_FACTORY_ERROR_MSG = 3;
838 static final int UPDATE_CONFIGURATION_MSG = 4;
839 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
840 static final int WAIT_FOR_DEBUGGER_MSG = 6;
841 static final int BROADCAST_INTENT_MSG = 7;
842 static final int BROADCAST_TIMEOUT_MSG = 8;
843 static final int PAUSE_TIMEOUT_MSG = 9;
844 static final int IDLE_TIMEOUT_MSG = 10;
845 static final int IDLE_NOW_MSG = 11;
846 static final int SERVICE_TIMEOUT_MSG = 12;
847 static final int UPDATE_TIME_ZONE = 13;
848 static final int SHOW_UID_ERROR_MSG = 14;
849 static final int IM_FEELING_LUCKY_MSG = 15;
850 static final int LAUNCH_TIMEOUT_MSG = 16;
851 static final int DESTROY_TIMEOUT_MSG = 17;
852 static final int SERVICE_ERROR_MSG = 18;
853 static final int RESUME_TOP_ACTIVITY_MSG = 19;
854 static final int PROC_START_TIMEOUT_MSG = 20;
855
856 AlertDialog mUidAlert;
857
858 final Handler mHandler = new Handler() {
859 //public Handler() {
860 // if (localLOGV) Log.v(TAG, "Handler started!");
861 //}
862
863 public void handleMessage(Message msg) {
864 switch (msg.what) {
865 case SHOW_ERROR_MSG: {
866 HashMap data = (HashMap) msg.obj;
867 byte[] crashData = (byte[])data.get("crashData");
868 if (crashData != null) {
869 // This needs to be *un*synchronized to avoid deadlock.
870 ContentResolver resolver = mContext.getContentResolver();
871 Checkin.reportCrash(resolver, crashData);
872 }
873 synchronized (ActivityManagerService.this) {
874 ProcessRecord proc = (ProcessRecord)data.get("app");
875 if (proc != null && proc.crashDialog != null) {
876 Log.e(TAG, "App already has crash dialog: " + proc);
877 return;
878 }
879 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700880 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 Dialog d = new AppErrorDialog(
882 mContext, res, proc,
883 (Integer)data.get("flags"),
884 (String)data.get("shortMsg"),
885 (String)data.get("longMsg"));
886 d.show();
887 proc.crashDialog = d;
888 } else {
889 // The device is asleep, so just pretend that the user
890 // saw a crash dialog and hit "force quit".
891 res.set(0);
892 }
893 }
894 } break;
895 case SHOW_NOT_RESPONDING_MSG: {
896 synchronized (ActivityManagerService.this) {
897 HashMap data = (HashMap) msg.obj;
898 ProcessRecord proc = (ProcessRecord)data.get("app");
899 if (proc != null && proc.anrDialog != null) {
900 Log.e(TAG, "App already has anr dialog: " + proc);
901 return;
902 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800903
904 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
905 null, null, 0, null, null, null,
906 false, false, MY_PID, Process.SYSTEM_UID);
907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
909 mContext, proc, (HistoryRecord)data.get("activity"));
910 d.show();
911 proc.anrDialog = d;
912 }
913 } break;
914 case SHOW_FACTORY_ERROR_MSG: {
915 Dialog d = new FactoryErrorDialog(
916 mContext, msg.getData().getCharSequence("msg"));
917 d.show();
918 enableScreenAfterBoot();
919 } break;
920 case UPDATE_CONFIGURATION_MSG: {
921 final ContentResolver resolver = mContext.getContentResolver();
922 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
923 } break;
924 case GC_BACKGROUND_PROCESSES_MSG: {
925 synchronized (ActivityManagerService.this) {
926 performAppGcsIfAppropriateLocked();
927 }
928 } break;
929 case WAIT_FOR_DEBUGGER_MSG: {
930 synchronized (ActivityManagerService.this) {
931 ProcessRecord app = (ProcessRecord)msg.obj;
932 if (msg.arg1 != 0) {
933 if (!app.waitedForDebugger) {
934 Dialog d = new AppWaitingForDebuggerDialog(
935 ActivityManagerService.this,
936 mContext, app);
937 app.waitDialog = d;
938 app.waitedForDebugger = true;
939 d.show();
940 }
941 } else {
942 if (app.waitDialog != null) {
943 app.waitDialog.dismiss();
944 app.waitDialog = null;
945 }
946 }
947 }
948 } break;
949 case BROADCAST_INTENT_MSG: {
950 if (DEBUG_BROADCAST) Log.v(
951 TAG, "Received BROADCAST_INTENT_MSG");
952 processNextBroadcast(true);
953 } break;
954 case BROADCAST_TIMEOUT_MSG: {
955 broadcastTimeout();
956 } break;
957 case PAUSE_TIMEOUT_MSG: {
958 IBinder token = (IBinder)msg.obj;
959 // We don't at this point know if the activity is fullscreen,
960 // so we need to be conservative and assume it isn't.
961 Log.w(TAG, "Activity pause timeout for " + token);
962 activityPaused(token, null, true);
963 } break;
964 case IDLE_TIMEOUT_MSG: {
965 IBinder token = (IBinder)msg.obj;
966 // We don't at this point know if the activity is fullscreen,
967 // so we need to be conservative and assume it isn't.
968 Log.w(TAG, "Activity idle timeout for " + token);
969 activityIdleInternal(token, true);
970 } break;
971 case DESTROY_TIMEOUT_MSG: {
972 IBinder token = (IBinder)msg.obj;
973 // We don't at this point know if the activity is fullscreen,
974 // so we need to be conservative and assume it isn't.
975 Log.w(TAG, "Activity destroy timeout for " + token);
976 activityDestroyed(token);
977 } break;
978 case IDLE_NOW_MSG: {
979 IBinder token = (IBinder)msg.obj;
980 activityIdle(token);
981 } break;
982 case SERVICE_TIMEOUT_MSG: {
983 serviceTimeout((ProcessRecord)msg.obj);
984 } break;
985 case UPDATE_TIME_ZONE: {
986 synchronized (ActivityManagerService.this) {
987 for (int i = mLRUProcesses.size() - 1 ; i >= 0 ; i--) {
988 ProcessRecord r = mLRUProcesses.get(i);
989 if (r.thread != null) {
990 try {
991 r.thread.updateTimeZone();
992 } catch (RemoteException ex) {
993 Log.w(TAG, "Failed to update time zone for: " + r.info.processName);
994 }
995 }
996 }
997 }
998 break;
999 }
1000 case SHOW_UID_ERROR_MSG: {
1001 // XXX This is a temporary dialog, no need to localize.
1002 AlertDialog d = new BaseErrorDialog(mContext);
1003 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1004 d.setCancelable(false);
1005 d.setTitle("System UIDs Inconsistent");
1006 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1007 d.setButton("I'm Feeling Lucky",
1008 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1009 mUidAlert = d;
1010 d.show();
1011 } break;
1012 case IM_FEELING_LUCKY_MSG: {
1013 if (mUidAlert != null) {
1014 mUidAlert.dismiss();
1015 mUidAlert = null;
1016 }
1017 } break;
1018 case LAUNCH_TIMEOUT_MSG: {
1019 synchronized (ActivityManagerService.this) {
1020 if (mLaunchingActivity.isHeld()) {
1021 Log.w(TAG, "Launch timeout has expired, giving up wake lock!");
1022 mLaunchingActivity.release();
1023 }
1024 }
1025 } break;
1026 case SERVICE_ERROR_MSG: {
1027 ServiceRecord srv = (ServiceRecord)msg.obj;
1028 // This needs to be *un*synchronized to avoid deadlock.
1029 Checkin.logEvent(mContext.getContentResolver(),
1030 Checkin.Events.Tag.SYSTEM_SERVICE_LOOPING,
1031 srv.name.toShortString());
1032 } break;
1033 case RESUME_TOP_ACTIVITY_MSG: {
1034 synchronized (ActivityManagerService.this) {
1035 resumeTopActivityLocked(null);
1036 }
1037 }
1038 case PROC_START_TIMEOUT_MSG: {
1039 ProcessRecord app = (ProcessRecord)msg.obj;
1040 synchronized (ActivityManagerService.this) {
1041 processStartTimedOutLocked(app);
1042 }
1043 }
1044 }
1045 }
1046 };
1047
1048 public static void setSystemProcess() {
1049 try {
1050 ActivityManagerService m = mSelf;
1051
1052 ServiceManager.addService("activity", m);
1053 ServiceManager.addService("meminfo", new MemBinder(m));
1054 if (MONITOR_CPU_USAGE) {
1055 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1056 }
1057 ServiceManager.addService("activity.broadcasts", new BroadcastsBinder(m));
1058 ServiceManager.addService("activity.services", new ServicesBinder(m));
1059 ServiceManager.addService("activity.senders", new SendersBinder(m));
1060 ServiceManager.addService("activity.providers", new ProvidersBinder(m));
1061 ServiceManager.addService("permission", new PermissionController(m));
1062
1063 ApplicationInfo info =
1064 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001065 "android", STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 synchronized (mSelf) {
1067 ProcessRecord app = mSelf.newProcessRecordLocked(
1068 mSystemThread.getApplicationThread(), info,
1069 info.processName);
1070 app.persistent = true;
1071 app.pid = Process.myPid();
1072 app.maxAdj = SYSTEM_ADJ;
1073 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1074 synchronized (mSelf.mPidsSelfLocked) {
1075 mSelf.mPidsSelfLocked.put(app.pid, app);
1076 }
1077 mSelf.updateLRUListLocked(app, true);
1078 }
1079 } catch (PackageManager.NameNotFoundException e) {
1080 throw new RuntimeException(
1081 "Unable to find android system package", e);
1082 }
1083 }
1084
1085 public void setWindowManager(WindowManagerService wm) {
1086 mWindowManager = wm;
1087 }
1088
1089 public static final Context main(int factoryTest) {
1090 AThread thr = new AThread();
1091 thr.start();
1092
1093 synchronized (thr) {
1094 while (thr.mService == null) {
1095 try {
1096 thr.wait();
1097 } catch (InterruptedException e) {
1098 }
1099 }
1100 }
1101
1102 ActivityManagerService m = thr.mService;
1103 mSelf = m;
1104 ActivityThread at = ActivityThread.systemMain();
1105 mSystemThread = at;
1106 Context context = at.getSystemContext();
1107 m.mContext = context;
1108 m.mFactoryTest = factoryTest;
1109 PowerManager pm =
1110 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1111 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1112 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1113 m.mLaunchingActivity.setReferenceCounted(false);
1114
1115 m.mBatteryStatsService.publish(context);
1116 m.mUsageStatsService.publish(context);
1117
1118 synchronized (thr) {
1119 thr.mReady = true;
1120 thr.notifyAll();
1121 }
1122
1123 m.startRunning(null, null, null, null);
1124
1125 return context;
1126 }
1127
1128 public static ActivityManagerService self() {
1129 return mSelf;
1130 }
1131
1132 static class AThread extends Thread {
1133 ActivityManagerService mService;
1134 boolean mReady = false;
1135
1136 public AThread() {
1137 super("ActivityManager");
1138 }
1139
1140 public void run() {
1141 Looper.prepare();
1142
1143 android.os.Process.setThreadPriority(
1144 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1145
1146 ActivityManagerService m = new ActivityManagerService();
1147
1148 synchronized (this) {
1149 mService = m;
1150 notifyAll();
1151 }
1152
1153 synchronized (this) {
1154 while (!mReady) {
1155 try {
1156 wait();
1157 } catch (InterruptedException e) {
1158 }
1159 }
1160 }
1161
1162 Looper.loop();
1163 }
1164 }
1165
1166 static class BroadcastsBinder extends Binder {
1167 ActivityManagerService mActivityManagerService;
1168 BroadcastsBinder(ActivityManagerService activityManagerService) {
1169 mActivityManagerService = activityManagerService;
1170 }
1171
1172 @Override
1173 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1174 mActivityManagerService.dumpBroadcasts(pw);
1175 }
1176 }
1177
1178 static class ServicesBinder extends Binder {
1179 ActivityManagerService mActivityManagerService;
1180 ServicesBinder(ActivityManagerService activityManagerService) {
1181 mActivityManagerService = activityManagerService;
1182 }
1183
1184 @Override
1185 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1186 mActivityManagerService.dumpServices(pw);
1187 }
1188 }
1189
1190 static class SendersBinder extends Binder {
1191 ActivityManagerService mActivityManagerService;
1192 SendersBinder(ActivityManagerService activityManagerService) {
1193 mActivityManagerService = activityManagerService;
1194 }
1195
1196 @Override
1197 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1198 mActivityManagerService.dumpSenders(pw);
1199 }
1200 }
1201
1202 static class ProvidersBinder extends Binder {
1203 ActivityManagerService mActivityManagerService;
1204 ProvidersBinder(ActivityManagerService activityManagerService) {
1205 mActivityManagerService = activityManagerService;
1206 }
1207
1208 @Override
1209 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1210 mActivityManagerService.dumpProviders(pw);
1211 }
1212 }
1213
1214 static class MemBinder extends Binder {
1215 ActivityManagerService mActivityManagerService;
1216 MemBinder(ActivityManagerService activityManagerService) {
1217 mActivityManagerService = activityManagerService;
1218 }
1219
1220 @Override
1221 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1222 ActivityManagerService service = mActivityManagerService;
1223 ArrayList<ProcessRecord> procs;
1224 synchronized (mActivityManagerService) {
1225 if (args != null && args.length > 0
1226 && args[0].charAt(0) != '-') {
1227 procs = new ArrayList<ProcessRecord>();
1228 int pid = -1;
1229 try {
1230 pid = Integer.parseInt(args[0]);
1231 } catch (NumberFormatException e) {
1232
1233 }
1234 for (int i=0; i<service.mLRUProcesses.size(); i++) {
1235 ProcessRecord proc = service.mLRUProcesses.get(i);
1236 if (proc.pid == pid) {
1237 procs.add(proc);
1238 } else if (proc.processName.equals(args[0])) {
1239 procs.add(proc);
1240 }
1241 }
1242 if (procs.size() <= 0) {
1243 pw.println("No process found for: " + args[0]);
1244 return;
1245 }
1246 } else {
1247 procs = service.mLRUProcesses;
1248 }
1249 }
1250 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1251 }
1252 }
1253
1254 static class CpuBinder extends Binder {
1255 ActivityManagerService mActivityManagerService;
1256 CpuBinder(ActivityManagerService activityManagerService) {
1257 mActivityManagerService = activityManagerService;
1258 }
1259
1260 @Override
1261 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1262 synchronized (mActivityManagerService.mProcessStatsThread) {
1263 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1264 }
1265 }
1266 }
1267
1268 private ActivityManagerService() {
1269 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1270 if (v != null && Integer.getInteger(v) != 0) {
1271 mSimpleProcessManagement = true;
1272 }
1273 v = System.getenv("ANDROID_DEBUG_APP");
1274 if (v != null) {
1275 mSimpleProcessManagement = true;
1276 }
1277
1278 MY_PID = Process.myPid();
1279
1280 File dataDir = Environment.getDataDirectory();
1281 File systemDir = new File(dataDir, "system");
1282 systemDir.mkdirs();
1283 mBatteryStatsService = new BatteryStatsService(new File(
1284 systemDir, "batterystats.bin").toString());
1285 mBatteryStatsService.getActiveStatistics().readLocked();
1286 mBatteryStatsService.getActiveStatistics().writeLocked();
1287
1288 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001289 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001290
1291 mConfiguration.makeDefault();
1292 mProcessStats.init();
1293
1294 // Add ourself to the Watchdog monitors.
1295 Watchdog.getInstance().addMonitor(this);
1296
1297 // These values are set in system/rootdir/init.rc on startup.
1298 FOREGROUND_APP_ADJ =
1299 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
1300 VISIBLE_APP_ADJ =
1301 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
1302 SECONDARY_SERVER_ADJ =
1303 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
The Android Open Source Project4df24232009-03-05 14:34:35 -08001304 HOME_APP_ADJ =
1305 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001306 HIDDEN_APP_MIN_ADJ =
1307 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
1308 CONTENT_PROVIDER_ADJ =
1309 Integer.valueOf(SystemProperties.get("ro.CONTENT_PROVIDER_ADJ"));
1310 HIDDEN_APP_MAX_ADJ = CONTENT_PROVIDER_ADJ-1;
1311 EMPTY_APP_ADJ =
1312 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
1313 FOREGROUND_APP_MEM =
1314 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
1315 VISIBLE_APP_MEM =
1316 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
1317 SECONDARY_SERVER_MEM =
1318 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
The Android Open Source Project4df24232009-03-05 14:34:35 -08001319 HOME_APP_MEM =
1320 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001321 HIDDEN_APP_MEM =
1322 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
1323 EMPTY_APP_MEM =
1324 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
1325
1326 mProcessStatsThread = new Thread("ProcessStats") {
1327 public void run() {
1328 while (true) {
1329 try {
1330 try {
1331 synchronized(this) {
1332 final long now = SystemClock.uptimeMillis();
1333 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1334 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
1335 //Log.i(TAG, "Cpu delay=" + nextCpuDelay
1336 // + ", write delay=" + nextWriteDelay);
1337 if (nextWriteDelay < nextCpuDelay) {
1338 nextCpuDelay = nextWriteDelay;
1339 }
1340 if (nextCpuDelay > 0) {
1341 this.wait(nextCpuDelay);
1342 }
1343 }
1344 } catch (InterruptedException e) {
1345 }
1346
1347 updateCpuStatsNow();
1348 } catch (Exception e) {
1349 Log.e(TAG, "Unexpected exception collecting process stats", e);
1350 }
1351 }
1352 }
1353 };
1354 mProcessStatsThread.start();
1355 }
1356
1357 @Override
1358 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1359 throws RemoteException {
1360 try {
1361 return super.onTransact(code, data, reply, flags);
1362 } catch (RuntimeException e) {
1363 // The activity manager only throws security exceptions, so let's
1364 // log all others.
1365 if (!(e instanceof SecurityException)) {
1366 Log.e(TAG, "Activity Manager Crash", e);
1367 }
1368 throw e;
1369 }
1370 }
1371
1372 void updateCpuStats() {
1373 synchronized (mProcessStatsThread) {
1374 final long now = SystemClock.uptimeMillis();
1375 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1376 mProcessStatsThread.notify();
1377 }
1378 }
1379 }
1380
1381 void updateCpuStatsNow() {
1382 synchronized (mProcessStatsThread) {
1383 final long now = SystemClock.uptimeMillis();
1384 boolean haveNewCpuStats = false;
1385
1386 if (MONITOR_CPU_USAGE &&
1387 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1388 mLastCpuTime = now;
1389 haveNewCpuStats = true;
1390 mProcessStats.update();
1391 //Log.i(TAG, mProcessStats.printCurrentState());
1392 //Log.i(TAG, "Total CPU usage: "
1393 // + mProcessStats.getTotalCpuPercent() + "%");
1394
1395 // Log the cpu usage if the property is set.
1396 if ("true".equals(SystemProperties.get("events.cpu"))) {
1397 int user = mProcessStats.getLastUserTime();
1398 int system = mProcessStats.getLastSystemTime();
1399 int iowait = mProcessStats.getLastIoWaitTime();
1400 int irq = mProcessStats.getLastIrqTime();
1401 int softIrq = mProcessStats.getLastSoftIrqTime();
1402 int idle = mProcessStats.getLastIdleTime();
1403
1404 int total = user + system + iowait + irq + softIrq + idle;
1405 if (total == 0) total = 1;
1406
1407 EventLog.writeEvent(LOG_CPU,
1408 ((user+system+iowait+irq+softIrq) * 100) / total,
1409 (user * 100) / total,
1410 (system * 100) / total,
1411 (iowait * 100) / total,
1412 (irq * 100) / total,
1413 (softIrq * 100) / total);
1414 }
1415 }
1416
1417 synchronized(mBatteryStatsService.getActiveStatistics()) {
1418 synchronized(mPidsSelfLocked) {
1419 if (haveNewCpuStats) {
1420 if (mBatteryStatsService.isOnBattery()) {
1421 final int N = mProcessStats.countWorkingStats();
1422 for (int i=0; i<N; i++) {
1423 ProcessStats.Stats st
1424 = mProcessStats.getWorkingStats(i);
1425 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1426 if (pr != null) {
1427 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1428 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
1429 }
1430 }
1431 }
1432 }
1433 }
1434
1435 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1436 mLastWriteTime = now;
1437 mBatteryStatsService.getActiveStatistics().writeLocked();
1438 }
1439 }
1440 }
1441 }
1442
1443 /**
1444 * Initialize the application bind args. These are passed to each
1445 * process when the bindApplication() IPC is sent to the process. They're
1446 * lazily setup to make sure the services are running when they're asked for.
1447 */
1448 private HashMap<String, IBinder> getCommonServicesLocked() {
1449 if (mAppBindArgs == null) {
1450 mAppBindArgs = new HashMap<String, IBinder>();
1451
1452 // Setup the application init args
1453 mAppBindArgs.put("package", ServiceManager.getService("package"));
1454 mAppBindArgs.put("window", ServiceManager.getService("window"));
1455 mAppBindArgs.put(Context.ALARM_SERVICE,
1456 ServiceManager.getService(Context.ALARM_SERVICE));
1457 }
1458 return mAppBindArgs;
1459 }
1460
1461 private final void setFocusedActivityLocked(HistoryRecord r) {
1462 if (mFocusedActivity != r) {
1463 mFocusedActivity = r;
1464 mWindowManager.setFocusedApp(r, true);
1465 }
1466 }
1467
1468 private final void updateLRUListLocked(ProcessRecord app,
1469 boolean oomAdj) {
1470 // put it on the LRU to keep track of when it should be exited.
1471 int lrui = mLRUProcesses.indexOf(app);
1472 if (lrui >= 0) mLRUProcesses.remove(lrui);
1473 mLRUProcesses.add(app);
1474 //Log.i(TAG, "Putting proc to front: " + app.processName);
1475 if (oomAdj) {
1476 updateOomAdjLocked();
1477 }
1478 }
1479
1480 private final boolean updateLRUListLocked(HistoryRecord r) {
1481 final boolean hadit = mLRUActivities.remove(r);
1482 mLRUActivities.add(r);
1483 return hadit;
1484 }
1485
1486 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1487 int i = mHistory.size()-1;
1488 while (i >= 0) {
1489 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1490 if (!r.finishing && r != notTop) {
1491 return r;
1492 }
1493 i--;
1494 }
1495 return null;
1496 }
1497
1498 /**
1499 * This is a simplified version of topRunningActivityLocked that provides a number of
1500 * optional skip-over modes. It is intended for use with the ActivityWatcher hook only.
1501 *
1502 * @param token If non-null, any history records matching this token will be skipped.
1503 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1504 *
1505 * @return Returns the HistoryRecord of the next activity on the stack.
1506 */
1507 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1508 int i = mHistory.size()-1;
1509 while (i >= 0) {
1510 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1511 // Note: the taskId check depends on real taskId fields being non-zero
1512 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1513 return r;
1514 }
1515 i--;
1516 }
1517 return null;
1518 }
1519
1520 private final ProcessRecord getProcessRecordLocked(
1521 String processName, int uid) {
1522 if (uid == Process.SYSTEM_UID) {
1523 // The system gets to run in any process. If there are multiple
1524 // processes with the same uid, just pick the first (this
1525 // should never happen).
1526 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1527 processName);
1528 return procs != null ? procs.valueAt(0) : null;
1529 }
1530 ProcessRecord proc = mProcessNames.get(processName, uid);
1531 return proc;
1532 }
1533
1534 private boolean isNextTransitionForward() {
1535 int transit = mWindowManager.getPendingAppTransition();
1536 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1537 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1538 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1539 }
1540
1541 private final boolean realStartActivityLocked(HistoryRecord r,
1542 ProcessRecord app, boolean andResume, boolean checkConfig)
1543 throws RemoteException {
1544
1545 r.startFreezingScreenLocked(app, 0);
1546 mWindowManager.setAppVisibility(r, true);
1547
1548 // Have the window manager re-evaluate the orientation of
1549 // the screen based on the new activity order. Note that
1550 // as a result of this, it can call back into the activity
1551 // manager with a new orientation. We don't care about that,
1552 // because the activity is not currently running so we are
1553 // just restarting it anyway.
1554 if (checkConfig) {
1555 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001556 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 r.mayFreezeScreenLocked(app) ? r : null);
1558 updateConfigurationLocked(config, r);
1559 }
1560
1561 r.app = app;
1562
1563 if (localLOGV) Log.v(TAG, "Launching: " + r);
1564
1565 int idx = app.activities.indexOf(r);
1566 if (idx < 0) {
1567 app.activities.add(r);
1568 }
1569 updateLRUListLocked(app, true);
1570
1571 try {
1572 if (app.thread == null) {
1573 throw new RemoteException();
1574 }
1575 List<ResultInfo> results = null;
1576 List<Intent> newIntents = null;
1577 if (andResume) {
1578 results = r.results;
1579 newIntents = r.newIntents;
1580 }
1581 if (DEBUG_SWITCH) Log.v(TAG, "Launching: " + r
1582 + " icicle=" + r.icicle
1583 + " with results=" + results + " newIntents=" + newIntents
1584 + " andResume=" + andResume);
1585 if (andResume) {
1586 EventLog.writeEvent(LOG_AM_RESTART_ACTIVITY,
1587 System.identityHashCode(r),
1588 r.task.taskId, r.shortComponentName);
1589 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001590 if (r.isHomeActivity) {
1591 mHomeProcess = app;
1592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
1594 r.info, r.icicle, results, newIntents, !andResume,
1595 isNextTransitionForward());
1596 // Update usage stats for launched activity
1597 updateUsageStats(r, true);
1598 } catch (RemoteException e) {
1599 if (r.launchFailed) {
1600 // This is the second time we failed -- finish activity
1601 // and give up.
1602 Log.e(TAG, "Second failure launching "
1603 + r.intent.getComponent().flattenToShortString()
1604 + ", giving up", e);
1605 appDiedLocked(app, app.pid, app.thread);
1606 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1607 "2nd-crash");
1608 return false;
1609 }
1610
1611 // This is the first time we failed -- restart process and
1612 // retry.
1613 app.activities.remove(r);
1614 throw e;
1615 }
1616
1617 r.launchFailed = false;
1618 if (updateLRUListLocked(r)) {
1619 Log.w(TAG, "Activity " + r
1620 + " being launched, but already in LRU list");
1621 }
1622
1623 if (andResume) {
1624 // As part of the process of launching, ActivityThread also performs
1625 // a resume.
1626 r.state = ActivityState.RESUMED;
1627 r.icicle = null;
1628 r.haveState = false;
1629 r.stopped = false;
1630 mResumedActivity = r;
1631 r.task.touchActiveTime();
1632 completeResumeLocked(r);
1633 pauseIfSleepingLocked();
1634 } else {
1635 // This activity is not starting in the resumed state... which
1636 // should look like we asked it to pause+stop (but remain visible),
1637 // and it has done so and reported back the current icicle and
1638 // other state.
1639 r.state = ActivityState.STOPPED;
1640 r.stopped = true;
1641 }
1642
1643 return true;
1644 }
1645
1646 private final void startSpecificActivityLocked(HistoryRecord r,
1647 boolean andResume, boolean checkConfig) {
1648 // Is this activity's application already running?
1649 ProcessRecord app = getProcessRecordLocked(r.processName,
1650 r.info.applicationInfo.uid);
1651
1652 if (r.startTime == 0) {
1653 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001654 if (mInitialStartTime == 0) {
1655 mInitialStartTime = r.startTime;
1656 }
1657 } else if (mInitialStartTime == 0) {
1658 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 }
1660
1661 if (app != null && app.thread != null) {
1662 try {
1663 realStartActivityLocked(r, app, andResume, checkConfig);
1664 return;
1665 } catch (RemoteException e) {
1666 Log.w(TAG, "Exception when starting activity "
1667 + r.intent.getComponent().flattenToShortString(), e);
1668 }
1669
1670 // If a dead object exception was thrown -- fall through to
1671 // restart the application.
1672 }
1673
1674 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
1675 "activity", r.intent.getComponent());
1676 }
1677
1678 private final ProcessRecord startProcessLocked(String processName,
1679 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
1680 String hostingType, ComponentName hostingName) {
1681 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1682 // We don't have to do anything more if:
1683 // (1) There is an existing application record; and
1684 // (2) The caller doesn't think it is dead, OR there is no thread
1685 // object attached to it so we know it couldn't have crashed; and
1686 // (3) There is a pid assigned to it, so it is either starting or
1687 // already running.
1688 if (DEBUG_PROCESSES) Log.v(TAG, "startProcess: name=" + processName
1689 + " app=" + app + " knownToBeDead=" + knownToBeDead
1690 + " thread=" + (app != null ? app.thread : null)
1691 + " pid=" + (app != null ? app.pid : -1));
1692 if (app != null &&
1693 (!knownToBeDead || app.thread == null) && app.pid > 0) {
1694 return app;
1695 }
1696
1697 String hostingNameStr = hostingName != null
1698 ? hostingName.flattenToShortString() : null;
1699
1700 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1701 // If we are in the background, then check to see if this process
1702 // is bad. If so, we will just silently fail.
1703 if (mBadProcesses.get(info.processName, info.uid) != null) {
1704 return null;
1705 }
1706 } else {
1707 // When the user is explicitly starting a process, then clear its
1708 // crash count so that we won't make it bad until they see at
1709 // least one crash dialog again, and make the process good again
1710 // if it had been bad.
1711 mProcessCrashTimes.remove(info.processName, info.uid);
1712 if (mBadProcesses.get(info.processName, info.uid) != null) {
1713 EventLog.writeEvent(LOG_AM_PROCESS_GOOD, info.uid,
1714 info.processName);
1715 mBadProcesses.remove(info.processName, info.uid);
1716 if (app != null) {
1717 app.bad = false;
1718 }
1719 }
1720 }
1721
1722 if (app == null) {
1723 app = newProcessRecordLocked(null, info, processName);
1724 mProcessNames.put(processName, info.uid, app);
1725 } else {
1726 // If this is a new package in the process, add the package to the list
1727 app.addPackage(info.packageName);
1728 }
1729
1730 // If the system is not ready yet, then hold off on starting this
1731 // process until it is.
1732 if (!mSystemReady
1733 && (info.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
1734 if (!mProcessesOnHold.contains(app)) {
1735 mProcessesOnHold.add(app);
1736 }
1737 return app;
1738 }
1739
1740 startProcessLocked(app, hostingType, hostingNameStr);
1741 return (app.pid != 0) ? app : null;
1742 }
1743
1744 private final void startProcessLocked(ProcessRecord app,
1745 String hostingType, String hostingNameStr) {
1746 if (app.pid > 0 && app.pid != MY_PID) {
1747 synchronized (mPidsSelfLocked) {
1748 mPidsSelfLocked.remove(app.pid);
1749 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1750 }
1751 app.pid = 0;
1752 }
1753
1754 mProcessesOnHold.remove(app);
1755
1756 updateCpuStats();
1757
1758 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1759 mProcDeaths[0] = 0;
1760
1761 try {
1762 int uid = app.info.uid;
1763 int[] gids = null;
1764 try {
1765 gids = mContext.getPackageManager().getPackageGids(
1766 app.info.packageName);
1767 } catch (PackageManager.NameNotFoundException e) {
1768 Log.w(TAG, "Unable to retrieve gids", e);
1769 }
1770 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1771 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1772 && mTopComponent != null
1773 && app.processName.equals(mTopComponent.getPackageName())) {
1774 uid = 0;
1775 }
1776 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1777 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1778 uid = 0;
1779 }
1780 }
1781 int debugFlags = 0;
1782 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1783 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1784 }
1785 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1786 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1787 }
1788 if ("1".equals(SystemProperties.get("debug.assert"))) {
1789 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1790 }
1791 int pid = Process.start("android.app.ActivityThread",
1792 mSimpleProcessManagement ? app.processName : null, uid, uid,
1793 gids, debugFlags, null);
1794 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1795 synchronized (bs) {
1796 if (bs.isOnBattery()) {
1797 app.batteryStats.incStartsLocked();
1798 }
1799 }
1800
1801 EventLog.writeEvent(LOG_AM_PROCESS_START, pid, uid,
1802 app.processName, hostingType,
1803 hostingNameStr != null ? hostingNameStr : "");
1804
1805 if (app.persistent) {
1806 Watchdog.getInstance().processStarted(app, app.processName, pid);
1807 }
1808
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001809 StringBuilder buf = mStringBuilder;
1810 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 buf.append("Start proc ");
1812 buf.append(app.processName);
1813 buf.append(" for ");
1814 buf.append(hostingType);
1815 if (hostingNameStr != null) {
1816 buf.append(" ");
1817 buf.append(hostingNameStr);
1818 }
1819 buf.append(": pid=");
1820 buf.append(pid);
1821 buf.append(" uid=");
1822 buf.append(uid);
1823 buf.append(" gids={");
1824 if (gids != null) {
1825 for (int gi=0; gi<gids.length; gi++) {
1826 if (gi != 0) buf.append(", ");
1827 buf.append(gids[gi]);
1828
1829 }
1830 }
1831 buf.append("}");
1832 Log.i(TAG, buf.toString());
1833 if (pid == 0 || pid == MY_PID) {
1834 // Processes are being emulated with threads.
1835 app.pid = MY_PID;
1836 app.removed = false;
1837 mStartingProcesses.add(app);
1838 } else if (pid > 0) {
1839 app.pid = pid;
1840 app.removed = false;
1841 synchronized (mPidsSelfLocked) {
1842 this.mPidsSelfLocked.put(pid, app);
1843 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1844 msg.obj = app;
1845 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1846 }
1847 } else {
1848 app.pid = 0;
1849 RuntimeException e = new RuntimeException(
1850 "Failure starting process " + app.processName
1851 + ": returned pid=" + pid);
1852 Log.e(TAG, e.getMessage(), e);
1853 }
1854 } catch (RuntimeException e) {
1855 // XXX do better error recovery.
1856 app.pid = 0;
1857 Log.e(TAG, "Failure starting process " + app.processName, e);
1858 }
1859 }
1860
1861 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
1862 if (mPausingActivity != null) {
1863 RuntimeException e = new RuntimeException();
1864 Log.e(TAG, "Trying to pause when pause is already pending for "
1865 + mPausingActivity, e);
1866 }
1867 HistoryRecord prev = mResumedActivity;
1868 if (prev == null) {
1869 RuntimeException e = new RuntimeException();
1870 Log.e(TAG, "Trying to pause when nothing is resumed", e);
1871 resumeTopActivityLocked(null);
1872 return;
1873 }
1874 if (DEBUG_PAUSE) Log.v(TAG, "Start pausing: " + prev);
1875 mResumedActivity = null;
1876 mPausingActivity = prev;
1877 mLastPausedActivity = prev;
1878 prev.state = ActivityState.PAUSING;
1879 prev.task.touchActiveTime();
1880
1881 updateCpuStats();
1882
1883 if (prev.app != null && prev.app.thread != null) {
1884 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending pause: " + prev);
1885 try {
1886 EventLog.writeEvent(LOG_AM_PAUSE_ACTIVITY,
1887 System.identityHashCode(prev),
1888 prev.shortComponentName);
1889 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
1890 prev.configChangeFlags);
1891 updateUsageStats(prev, false);
1892 } catch (Exception e) {
1893 // Ignore exception, if process died other code will cleanup.
1894 Log.w(TAG, "Exception thrown during pause", e);
1895 mPausingActivity = null;
1896 mLastPausedActivity = null;
1897 }
1898 } else {
1899 mPausingActivity = null;
1900 mLastPausedActivity = null;
1901 }
1902
1903 // If we are not going to sleep, we want to ensure the device is
1904 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07001905 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906 mLaunchingActivity.acquire();
1907 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1908 // To be safe, don't allow the wake lock to be held for too long.
1909 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1910 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
1911 }
1912 }
1913
1914
1915 if (mPausingActivity != null) {
1916 // Have the window manager pause its key dispatching until the new
1917 // activity has started. If we're pausing the activity just because
1918 // the screen is being turned off and the UI is sleeping, don't interrupt
1919 // key dispatch; the same activity will pick it up again on wakeup.
1920 if (!uiSleeping) {
1921 prev.pauseKeyDispatchingLocked();
1922 } else {
1923 if (DEBUG_PAUSE) Log.v(TAG, "Key dispatch not paused for screen off");
1924 }
1925
1926 // Schedule a pause timeout in case the app doesn't respond.
1927 // We don't give it much time because this directly impacts the
1928 // responsiveness seen by the user.
1929 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
1930 msg.obj = prev;
1931 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
1932 if (DEBUG_PAUSE) Log.v(TAG, "Waiting for pause to complete...");
1933 } else {
1934 // This activity failed to schedule the
1935 // pause, so just treat it as being paused now.
1936 if (DEBUG_PAUSE) Log.v(TAG, "Activity not running, resuming next.");
1937 resumeTopActivityLocked(null);
1938 }
1939 }
1940
1941 private final void completePauseLocked() {
1942 HistoryRecord prev = mPausingActivity;
1943 if (DEBUG_PAUSE) Log.v(TAG, "Complete pause: " + prev);
1944
1945 if (prev != null) {
1946 if (prev.finishing) {
1947 if (DEBUG_PAUSE) Log.v(TAG, "Executing finish of activity: " + prev);
1948 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
1949 } else if (prev.app != null) {
1950 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending stop: " + prev);
1951 if (prev.waitingVisible) {
1952 prev.waitingVisible = false;
1953 mWaitingVisibleActivities.remove(prev);
1954 if (DEBUG_SWITCH || DEBUG_PAUSE) Log.v(
1955 TAG, "Complete pause, no longer waiting: " + prev);
1956 }
1957 if (prev.configDestroy) {
1958 // The previous is being paused because the configuration
1959 // is changing, which means it is actually stopping...
1960 // To juggle the fact that we are also starting a new
1961 // instance right now, we need to first completely stop
1962 // the current instance before starting the new one.
1963 if (DEBUG_PAUSE) Log.v(TAG, "Destroying after pause: " + prev);
1964 destroyActivityLocked(prev, true);
1965 } else {
1966 mStoppingActivities.add(prev);
1967 if (mStoppingActivities.size() > 3) {
1968 // If we already have a few activities waiting to stop,
1969 // then give up on things going idle and start clearing
1970 // them out.
1971 if (DEBUG_PAUSE) Log.v(TAG, "To many pending stops, forcing idle");
1972 Message msg = Message.obtain();
1973 msg.what = ActivityManagerService.IDLE_NOW_MSG;
1974 mHandler.sendMessage(msg);
1975 }
1976 }
1977 } else {
1978 if (DEBUG_PAUSE) Log.v(TAG, "App died during pause, not stopping: " + prev);
1979 prev = null;
1980 }
1981 mPausingActivity = null;
1982 }
1983
Dianne Hackborn55280a92009-05-07 15:53:46 -07001984 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 resumeTopActivityLocked(prev);
1986 } else {
1987 if (mGoingToSleep.isHeld()) {
1988 mGoingToSleep.release();
1989 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07001990 if (mShuttingDown) {
1991 notifyAll();
1992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 }
1994
1995 if (prev != null) {
1996 prev.resumeKeyDispatchingLocked();
1997 }
1998 }
1999
2000 /**
2001 * Once we know that we have asked an application to put an activity in
2002 * the resumed state (either by launching it or explicitly telling it),
2003 * this function updates the rest of our state to match that fact.
2004 */
2005 private final void completeResumeLocked(HistoryRecord next) {
2006 next.idle = false;
2007 next.results = null;
2008 next.newIntents = null;
2009
2010 // schedule an idle timeout in case the app doesn't do it for us.
2011 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2012 msg.obj = next;
2013 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2014
2015 if (false) {
2016 // The activity was never told to pause, so just keep
2017 // things going as-is. To maintain our own state,
2018 // we need to emulate it coming back and saying it is
2019 // idle.
2020 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2021 msg.obj = next;
2022 mHandler.sendMessage(msg);
2023 }
2024
2025 next.thumbnail = null;
2026 setFocusedActivityLocked(next);
2027 next.resumeKeyDispatchingLocked();
2028 ensureActivitiesVisibleLocked(null, 0);
2029 mWindowManager.executeAppTransition();
2030 }
2031
2032 /**
2033 * Make sure that all activities that need to be visible (that is, they
2034 * currently can be seen by the user) actually are.
2035 */
2036 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2037 HistoryRecord starting, String onlyThisProcess, int configChanges) {
2038 if (DEBUG_VISBILITY) Log.v(
2039 TAG, "ensureActivitiesVisible behind " + top
2040 + " configChanges=0x" + Integer.toHexString(configChanges));
2041
2042 // If the top activity is not fullscreen, then we need to
2043 // make sure any activities under it are now visible.
2044 final int count = mHistory.size();
2045 int i = count-1;
2046 while (mHistory.get(i) != top) {
2047 i--;
2048 }
2049 HistoryRecord r;
2050 boolean behindFullscreen = false;
2051 for (; i>=0; i--) {
2052 r = (HistoryRecord)mHistory.get(i);
2053 if (DEBUG_VISBILITY) Log.v(
2054 TAG, "Make visible? " + r + " finishing=" + r.finishing
2055 + " state=" + r.state);
2056 if (r.finishing) {
2057 continue;
2058 }
2059
2060 final boolean doThisProcess = onlyThisProcess == null
2061 || onlyThisProcess.equals(r.processName);
2062
2063 // First: if this is not the current activity being started, make
2064 // sure it matches the current configuration.
2065 if (r != starting && doThisProcess) {
2066 ensureActivityConfigurationLocked(r, 0);
2067 }
2068
2069 if (r.app == null || r.app.thread == null) {
2070 if (onlyThisProcess == null
2071 || onlyThisProcess.equals(r.processName)) {
2072 // This activity needs to be visible, but isn't even
2073 // running... get it started, but don't resume it
2074 // at this point.
2075 if (DEBUG_VISBILITY) Log.v(
2076 TAG, "Start and freeze screen for " + r);
2077 if (r != starting) {
2078 r.startFreezingScreenLocked(r.app, configChanges);
2079 }
2080 if (!r.visible) {
2081 if (DEBUG_VISBILITY) Log.v(
2082 TAG, "Starting and making visible: " + r);
2083 mWindowManager.setAppVisibility(r, true);
2084 }
2085 if (r != starting) {
2086 startSpecificActivityLocked(r, false, false);
2087 }
2088 }
2089
2090 } else if (r.visible) {
2091 // If this activity is already visible, then there is nothing
2092 // else to do here.
2093 if (DEBUG_VISBILITY) Log.v(
2094 TAG, "Skipping: already visible at " + r);
2095 r.stopFreezingScreenLocked(false);
2096
2097 } else if (onlyThisProcess == null) {
2098 // This activity is not currently visible, but is running.
2099 // Tell it to become visible.
2100 r.visible = true;
2101 if (r.state != ActivityState.RESUMED && r != starting) {
2102 // If this activity is paused, tell it
2103 // to now show its window.
2104 if (DEBUG_VISBILITY) Log.v(
2105 TAG, "Making visible and scheduling visibility: " + r);
2106 try {
2107 mWindowManager.setAppVisibility(r, true);
2108 r.app.thread.scheduleWindowVisibility(r, true);
2109 r.stopFreezingScreenLocked(false);
2110 } catch (Exception e) {
2111 // Just skip on any failure; we'll make it
2112 // visible when it next restarts.
2113 Log.w(TAG, "Exception thrown making visibile: "
2114 + r.intent.getComponent(), e);
2115 }
2116 }
2117 }
2118
2119 // Aggregate current change flags.
2120 configChanges |= r.configChangeFlags;
2121
2122 if (r.fullscreen) {
2123 // At this point, nothing else needs to be shown
2124 if (DEBUG_VISBILITY) Log.v(
2125 TAG, "Stopping: fullscreen at " + r);
2126 behindFullscreen = true;
2127 i--;
2128 break;
2129 }
2130 }
2131
2132 // Now for any activities that aren't visible to the user, make
2133 // sure they no longer are keeping the screen frozen.
2134 while (i >= 0) {
2135 r = (HistoryRecord)mHistory.get(i);
2136 if (DEBUG_VISBILITY) Log.v(
2137 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2138 + " state=" + r.state
2139 + " behindFullscreen=" + behindFullscreen);
2140 if (!r.finishing) {
2141 if (behindFullscreen) {
2142 if (r.visible) {
2143 if (DEBUG_VISBILITY) Log.v(
2144 TAG, "Making invisible: " + r);
2145 r.visible = false;
2146 try {
2147 mWindowManager.setAppVisibility(r, false);
2148 if ((r.state == ActivityState.STOPPING
2149 || r.state == ActivityState.STOPPED)
2150 && r.app != null && r.app.thread != null) {
2151 if (DEBUG_VISBILITY) Log.v(
2152 TAG, "Scheduling invisibility: " + r);
2153 r.app.thread.scheduleWindowVisibility(r, false);
2154 }
2155 } catch (Exception e) {
2156 // Just skip on any failure; we'll make it
2157 // visible when it next restarts.
2158 Log.w(TAG, "Exception thrown making hidden: "
2159 + r.intent.getComponent(), e);
2160 }
2161 } else {
2162 if (DEBUG_VISBILITY) Log.v(
2163 TAG, "Already invisible: " + r);
2164 }
2165 } else if (r.fullscreen) {
2166 if (DEBUG_VISBILITY) Log.v(
2167 TAG, "Now behindFullscreen: " + r);
2168 behindFullscreen = true;
2169 }
2170 }
2171 i--;
2172 }
2173 }
2174
2175 /**
2176 * Version of ensureActivitiesVisible that can easily be called anywhere.
2177 */
2178 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2179 int configChanges) {
2180 HistoryRecord r = topRunningActivityLocked(null);
2181 if (r != null) {
2182 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2183 }
2184 }
2185
2186 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2187 if (resumed) {
2188 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2189 } else {
2190 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2191 }
2192 }
2193
2194 /**
2195 * Ensure that the top activity in the stack is resumed.
2196 *
2197 * @param prev The previously resumed activity, for when in the process
2198 * of pausing; can be null to call from elsewhere.
2199 *
2200 * @return Returns true if something is being resumed, or false if
2201 * nothing happened.
2202 */
2203 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2204 // Find the first activity that is not finishing.
2205 HistoryRecord next = topRunningActivityLocked(null);
2206
2207 // Remember how we'll process this pause/resume situation, and ensure
2208 // that the state is reset however we wind up proceeding.
2209 final boolean userLeaving = mUserLeaving;
2210 mUserLeaving = false;
2211
2212 if (next == null) {
2213 // There are no more activities! Let's just start up the
2214 // Launcher...
2215 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2216 && mTopAction == null) {
2217 // We are running in factory test mode, but unable to find
2218 // the factory test app, so just sit around displaying the
2219 // error message and don't try to start anything.
2220 return false;
2221 }
2222 Intent intent = new Intent(
2223 mTopAction,
2224 mTopData != null ? Uri.parse(mTopData) : null);
2225 intent.setComponent(mTopComponent);
2226 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2227 intent.addCategory(Intent.CATEGORY_HOME);
2228 }
2229 ActivityInfo aInfo =
2230 intent.resolveActivityInfo(mContext.getPackageManager(),
Dianne Hackborn1655be42009-05-08 14:29:01 -07002231 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002232 if (aInfo != null) {
2233 intent.setComponent(new ComponentName(
2234 aInfo.applicationInfo.packageName, aInfo.name));
2235 // Don't do this if the home app is currently being
2236 // instrumented.
2237 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2238 aInfo.applicationInfo.uid);
2239 if (app == null || app.instrumentationClass == null) {
2240 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2241 startActivityLocked(null, intent, null, null, 0, aInfo,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002242 null, null, 0, 0, 0, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243 }
2244 }
2245 return true;
2246 }
2247
2248 // If the top activity is the resumed one, nothing to do.
2249 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2250 // Make sure we have executed any pending transitions, since there
2251 // should be nothing left to do at this point.
2252 mWindowManager.executeAppTransition();
2253 return false;
2254 }
2255
2256 // If we are sleeping, and there is no resumed activity, and the top
2257 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002258 if ((mSleeping || mShuttingDown)
2259 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002260 // Make sure we have executed any pending transitions, since there
2261 // should be nothing left to do at this point.
2262 mWindowManager.executeAppTransition();
2263 return false;
2264 }
2265
2266 // The activity may be waiting for stop, but that is no longer
2267 // appropriate for it.
2268 mStoppingActivities.remove(next);
2269 mWaitingVisibleActivities.remove(next);
2270
2271 if (DEBUG_SWITCH) Log.v(TAG, "Resuming " + next);
2272
2273 // If we are currently pausing an activity, then don't do anything
2274 // until that is done.
2275 if (mPausingActivity != null) {
2276 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: pausing=" + mPausingActivity);
2277 return false;
2278 }
2279
2280 // We need to start pausing the current activity so the top one
2281 // can be resumed...
2282 if (mResumedActivity != null) {
2283 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: need to start pausing");
2284 startPausingLocked(userLeaving, false);
2285 return true;
2286 }
2287
2288 if (prev != null && prev != next) {
2289 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2290 prev.waitingVisible = true;
2291 mWaitingVisibleActivities.add(prev);
2292 if (DEBUG_SWITCH) Log.v(
2293 TAG, "Resuming top, waiting visible to hide: " + prev);
2294 } else {
2295 // The next activity is already visible, so hide the previous
2296 // activity's windows right now so we can show the new one ASAP.
2297 // We only do this if the previous is finishing, which should mean
2298 // it is on top of the one being resumed so hiding it quickly
2299 // is good. Otherwise, we want to do the normal route of allowing
2300 // the resumed activity to be shown so we can decide if the
2301 // previous should actually be hidden depending on whether the
2302 // new one is found to be full-screen or not.
2303 if (prev.finishing) {
2304 mWindowManager.setAppVisibility(prev, false);
2305 if (DEBUG_SWITCH) Log.v(TAG, "Not waiting for visible to hide: "
2306 + prev + ", waitingVisible="
2307 + (prev != null ? prev.waitingVisible : null)
2308 + ", nowVisible=" + next.nowVisible);
2309 } else {
2310 if (DEBUG_SWITCH) Log.v(TAG, "Previous already visible but still waiting to hide: "
2311 + prev + ", waitingVisible="
2312 + (prev != null ? prev.waitingVisible : null)
2313 + ", nowVisible=" + next.nowVisible);
2314 }
2315 }
2316 }
2317
2318 // We are starting up the next activity, so tell the window manager
2319 // that the previous one will be hidden soon. This way it can know
2320 // to ignore it when computing the desired screen orientation.
2321 if (prev != null) {
2322 if (prev.finishing) {
2323 if (DEBUG_TRANSITION) Log.v(TAG,
2324 "Prepare close transition: prev=" + prev);
2325 mWindowManager.prepareAppTransition(prev.task == next.task
2326 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2327 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2328 mWindowManager.setAppWillBeHidden(prev);
2329 mWindowManager.setAppVisibility(prev, false);
2330 } else {
2331 if (DEBUG_TRANSITION) Log.v(TAG,
2332 "Prepare open transition: prev=" + prev);
2333 mWindowManager.prepareAppTransition(prev.task == next.task
2334 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2335 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2336 }
2337 if (false) {
2338 mWindowManager.setAppWillBeHidden(prev);
2339 mWindowManager.setAppVisibility(prev, false);
2340 }
2341 } else if (mHistory.size() > 1) {
2342 if (DEBUG_TRANSITION) Log.v(TAG,
2343 "Prepare open transition: no previous");
2344 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2345 }
2346
2347 if (next.app != null && next.app.thread != null) {
2348 if (DEBUG_SWITCH) Log.v(TAG, "Resume running: " + next);
2349
2350 // This activity is now becoming visible.
2351 mWindowManager.setAppVisibility(next, true);
2352
2353 HistoryRecord lastResumedActivity = mResumedActivity;
2354 ActivityState lastState = next.state;
2355
2356 updateCpuStats();
2357
2358 next.state = ActivityState.RESUMED;
2359 mResumedActivity = next;
2360 next.task.touchActiveTime();
2361 updateLRUListLocked(next.app, true);
2362 updateLRUListLocked(next);
2363
2364 // Have the window manager re-evaluate the orientation of
2365 // the screen based on the new activity order.
2366 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002367 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 next.mayFreezeScreenLocked(next.app) ? next : null);
2369 if (config != null) {
2370 next.frozenBeforeDestroy = true;
2371 }
2372 if (!updateConfigurationLocked(config, next)) {
2373 // The configuration update wasn't able to keep the existing
2374 // instance of the activity, and instead started a new one.
2375 // We should be all done, but let's just make sure our activity
2376 // is still at the top and schedule another run if something
2377 // weird happened.
2378 HistoryRecord nextNext = topRunningActivityLocked(null);
2379 if (DEBUG_SWITCH) Log.i(TAG,
2380 "Activity config changed during resume: " + next
2381 + ", new next: " + nextNext);
2382 if (nextNext != next) {
2383 // Do over!
2384 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2385 }
2386 mWindowManager.executeAppTransition();
2387 return true;
2388 }
2389
2390 try {
2391 // Deliver all pending results.
2392 ArrayList a = next.results;
2393 if (a != null) {
2394 final int N = a.size();
2395 if (!next.finishing && N > 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002396 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397 TAG, "Delivering results to " + next
2398 + ": " + a);
2399 next.app.thread.scheduleSendResult(next, a);
2400 }
2401 }
2402
2403 if (next.newIntents != null) {
2404 next.app.thread.scheduleNewIntent(next.newIntents, next);
2405 }
2406
2407 EventLog.writeEvent(LOG_AM_RESUME_ACTIVITY,
2408 System.identityHashCode(next),
2409 next.task.taskId, next.shortComponentName);
2410 updateUsageStats(next, true);
2411
2412 next.app.thread.scheduleResumeActivity(next,
2413 isNextTransitionForward());
2414 pauseIfSleepingLocked();
2415
2416 } catch (Exception e) {
2417 // Whoops, need to restart this activity!
2418 next.state = lastState;
2419 mResumedActivity = lastResumedActivity;
2420 if (Config.LOGD) Log.d(TAG,
2421 "Restarting because process died: " + next);
2422 if (!next.hasBeenLaunched) {
2423 next.hasBeenLaunched = true;
2424 } else {
2425 if (SHOW_APP_STARTING_ICON) {
2426 mWindowManager.setAppStartingWindow(
2427 next, next.packageName, next.theme,
2428 next.nonLocalizedLabel,
2429 next.labelRes, next.icon, null, true);
2430 }
2431 }
2432 startSpecificActivityLocked(next, true, false);
2433 return true;
2434 }
2435
2436 // From this point on, if something goes wrong there is no way
2437 // to recover the activity.
2438 try {
2439 next.visible = true;
2440 completeResumeLocked(next);
2441 } catch (Exception e) {
2442 // If any exception gets thrown, toss away this
2443 // activity and try the next one.
2444 Log.w(TAG, "Exception thrown during resume of " + next, e);
2445 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2446 "resume-exception");
2447 return true;
2448 }
2449
2450 // Didn't need to use the icicle, and it is now out of date.
2451 next.icicle = null;
2452 next.haveState = false;
2453 next.stopped = false;
2454
2455 } else {
2456 // Whoops, need to restart this activity!
2457 if (!next.hasBeenLaunched) {
2458 next.hasBeenLaunched = true;
2459 } else {
2460 if (SHOW_APP_STARTING_ICON) {
2461 mWindowManager.setAppStartingWindow(
2462 next, next.packageName, next.theme,
2463 next.nonLocalizedLabel,
2464 next.labelRes, next.icon, null, true);
2465 }
2466 if (DEBUG_SWITCH) Log.v(TAG, "Restarting: " + next);
2467 }
2468 startSpecificActivityLocked(next, true, true);
2469 }
2470
2471 return true;
2472 }
2473
2474 private final void startActivityLocked(HistoryRecord r, boolean newTask) {
2475 final int NH = mHistory.size();
2476
2477 int addPos = -1;
2478
2479 if (!newTask) {
2480 // If starting in an existing task, find where that is...
2481 HistoryRecord next = null;
2482 boolean startIt = true;
2483 for (int i = NH-1; i >= 0; i--) {
2484 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2485 if (p.finishing) {
2486 continue;
2487 }
2488 if (p.task == r.task) {
2489 // Here it is! Now, if this is not yet visible to the
2490 // user, then just add it without starting; it will
2491 // get started when the user navigates back to it.
2492 addPos = i+1;
2493 if (!startIt) {
2494 mHistory.add(addPos, r);
2495 r.inHistory = true;
2496 r.task.numActivities++;
2497 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2498 r.info.screenOrientation, r.fullscreen);
2499 if (VALIDATE_TOKENS) {
2500 mWindowManager.validateAppTokens(mHistory);
2501 }
2502 return;
2503 }
2504 break;
2505 }
2506 if (p.fullscreen) {
2507 startIt = false;
2508 }
2509 next = p;
2510 }
2511 }
2512
2513 // Place a new activity at top of stack, so it is next to interact
2514 // with the user.
2515 if (addPos < 0) {
2516 addPos = mHistory.size();
2517 }
2518
2519 // If we are not placing the new activity frontmost, we do not want
2520 // to deliver the onUserLeaving callback to the actual frontmost
2521 // activity
2522 if (addPos < NH) {
2523 mUserLeaving = false;
2524 if (DEBUG_USER_LEAVING) Log.v(TAG, "startActivity() behind front, mUserLeaving=false");
2525 }
2526
2527 // Slot the activity into the history stack and proceed
2528 mHistory.add(addPos, r);
2529 r.inHistory = true;
2530 r.frontOfTask = newTask;
2531 r.task.numActivities++;
2532 if (NH > 0) {
2533 // We want to show the starting preview window if we are
2534 // switching to a new task, or the next activity's process is
2535 // not currently running.
2536 boolean showStartingIcon = newTask;
2537 ProcessRecord proc = r.app;
2538 if (proc == null) {
2539 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2540 }
2541 if (proc == null || proc.thread == null) {
2542 showStartingIcon = true;
2543 }
2544 if (DEBUG_TRANSITION) Log.v(TAG,
2545 "Prepare open transition: starting " + r);
2546 mWindowManager.prepareAppTransition(newTask
2547 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2548 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2549 mWindowManager.addAppToken(
2550 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2551 boolean doShow = true;
2552 if (newTask) {
2553 // Even though this activity is starting fresh, we still need
2554 // to reset it to make sure we apply affinities to move any
2555 // existing activities from other tasks in to it.
2556 // If the caller has requested that the target task be
2557 // reset, then do so.
2558 if ((r.intent.getFlags()
2559 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2560 resetTaskIfNeededLocked(r, r);
2561 doShow = topRunningActivityLocked(null) == r;
2562 }
2563 }
2564 if (SHOW_APP_STARTING_ICON && doShow) {
2565 // Figure out if we are transitioning from another activity that is
2566 // "has the same starting icon" as the next one. This allows the
2567 // window manager to keep the previous window it had previously
2568 // created, if it still had one.
2569 HistoryRecord prev = mResumedActivity;
2570 if (prev != null) {
2571 // We don't want to reuse the previous starting preview if:
2572 // (1) The current activity is in a different task.
2573 if (prev.task != r.task) prev = null;
2574 // (2) The current activity is already displayed.
2575 else if (prev.nowVisible) prev = null;
2576 }
2577 mWindowManager.setAppStartingWindow(
2578 r, r.packageName, r.theme, r.nonLocalizedLabel,
2579 r.labelRes, r.icon, prev, showStartingIcon);
2580 }
2581 } else {
2582 // If this is the first activity, don't do any fancy animations,
2583 // because there is nothing for it to animate on top of.
2584 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2585 r.info.screenOrientation, r.fullscreen);
2586 }
2587 if (VALIDATE_TOKENS) {
2588 mWindowManager.validateAppTokens(mHistory);
2589 }
2590
2591 resumeTopActivityLocked(null);
2592 }
2593
2594 /**
2595 * Perform clear operation as requested by
2596 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: assuming the top task on the
2597 * stack is the one that the new activity is being launched in, look for
2598 * an instance of that activity in the stack and, if found, finish all
2599 * activities on top of it and return the instance.
2600 *
2601 * @param newR Description of the new activity being started.
2602 * @return Returns the old activity that should be continue to be used,
2603 * or null if none was found.
2604 */
2605 private final HistoryRecord performClearTopTaskLocked(int taskId,
2606 HistoryRecord newR, boolean doClear) {
2607 int i = mHistory.size();
2608 while (i > 0) {
2609 i--;
2610 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2611 if (r.finishing) {
2612 continue;
2613 }
2614 if (r.task.taskId != taskId) {
2615 return null;
2616 }
2617 if (r.realActivity.equals(newR.realActivity)) {
2618 // Here it is! Now finish everything in front...
2619 HistoryRecord ret = r;
2620 if (doClear) {
2621 while (i < (mHistory.size()-1)) {
2622 i++;
2623 r = (HistoryRecord)mHistory.get(i);
2624 if (r.finishing) {
2625 continue;
2626 }
2627 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2628 null, "clear")) {
2629 i--;
2630 }
2631 }
2632 }
2633
2634 // Finally, if this is a normal launch mode (that is, not
2635 // expecting onNewIntent()), then we will finish the current
2636 // instance of the activity so a new fresh one can be started.
2637 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE) {
2638 if (!ret.finishing) {
2639 int index = indexOfTokenLocked(ret, false);
2640 if (index >= 0) {
2641 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2642 null, "clear");
2643 }
2644 return null;
2645 }
2646 }
2647
2648 return ret;
2649 }
2650 }
2651
2652 return null;
2653 }
2654
2655 /**
2656 * Find the activity in the history stack within the given task. Returns
2657 * the index within the history at which it's found, or < 0 if not found.
2658 */
2659 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
2660 int i = mHistory.size();
2661 while (i > 0) {
2662 i--;
2663 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
2664 if (candidate.task.taskId != task) {
2665 break;
2666 }
2667 if (candidate.realActivity.equals(r.realActivity)) {
2668 return i;
2669 }
2670 }
2671
2672 return -1;
2673 }
2674
2675 /**
2676 * Reorder the history stack so that the activity at the given index is
2677 * brought to the front.
2678 */
2679 private final HistoryRecord moveActivityToFrontLocked(int where) {
2680 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
2681 int top = mHistory.size();
2682 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
2683 mHistory.add(top, newTop);
2684 oldTop.frontOfTask = false;
2685 newTop.frontOfTask = true;
2686 return newTop;
2687 }
2688
2689 /**
2690 * Deliver a new Intent to an existing activity, so that its onNewIntent()
2691 * method will be called at the proper time.
2692 */
2693 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
2694 boolean sent = false;
2695 if (r.state == ActivityState.RESUMED
2696 && r.app != null && r.app.thread != null) {
2697 try {
2698 ArrayList<Intent> ar = new ArrayList<Intent>();
2699 ar.add(new Intent(intent));
2700 r.app.thread.scheduleNewIntent(ar, r);
2701 sent = true;
2702 } catch (Exception e) {
2703 Log.w(TAG, "Exception thrown sending new intent to " + r, e);
2704 }
2705 }
2706 if (!sent) {
2707 r.addNewIntentLocked(new Intent(intent));
2708 }
2709 }
2710
2711 private final void logStartActivity(int tag, HistoryRecord r,
2712 TaskRecord task) {
2713 EventLog.writeEvent(tag,
2714 System.identityHashCode(r), task.taskId,
2715 r.shortComponentName, r.intent.getAction(),
2716 r.intent.getType(), r.intent.getDataString(),
2717 r.intent.getFlags());
2718 }
2719
2720 private final int startActivityLocked(IApplicationThread caller,
2721 Intent intent, String resolvedType,
2722 Uri[] grantedUriPermissions,
2723 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
2724 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002725 int callingPid, int callingUid, boolean onlyIfNeeded,
2726 boolean componentSpecified) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 Log.i(TAG, "Starting activity: " + intent);
2728
2729 HistoryRecord sourceRecord = null;
2730 HistoryRecord resultRecord = null;
2731 if (resultTo != null) {
2732 int index = indexOfTokenLocked(resultTo, false);
The Android Open Source Project10592532009-03-18 17:39:46 -07002733 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 TAG, "Sending result to " + resultTo + " (index " + index + ")");
2735 if (index >= 0) {
2736 sourceRecord = (HistoryRecord)mHistory.get(index);
2737 if (requestCode >= 0 && !sourceRecord.finishing) {
2738 resultRecord = sourceRecord;
2739 }
2740 }
2741 }
2742
2743 int launchFlags = intent.getFlags();
2744
2745 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
2746 && sourceRecord != null) {
2747 // Transfer the result target from the source activity to the new
2748 // one being started, including any failures.
2749 if (requestCode >= 0) {
2750 return START_FORWARD_AND_REQUEST_CONFLICT;
2751 }
2752 resultRecord = sourceRecord.resultTo;
2753 resultWho = sourceRecord.resultWho;
2754 requestCode = sourceRecord.requestCode;
2755 sourceRecord.resultTo = null;
2756 if (resultRecord != null) {
2757 resultRecord.removeResultsLocked(
2758 sourceRecord, resultWho, requestCode);
2759 }
2760 }
2761
2762 int err = START_SUCCESS;
2763
2764 if (intent.getComponent() == null) {
2765 // We couldn't find a class that can handle the given Intent.
2766 // That's the end of that!
2767 err = START_INTENT_NOT_RESOLVED;
2768 }
2769
2770 if (err == START_SUCCESS && aInfo == null) {
2771 // We couldn't find the specific class specified in the Intent.
2772 // Also the end of the line.
2773 err = START_CLASS_NOT_FOUND;
2774 }
2775
2776 ProcessRecord callerApp = null;
2777 if (err == START_SUCCESS && caller != null) {
2778 callerApp = getRecordForAppLocked(caller);
2779 if (callerApp != null) {
2780 callingPid = callerApp.pid;
2781 callingUid = callerApp.info.uid;
2782 } else {
2783 Log.w(TAG, "Unable to find app for caller " + caller
2784 + " (pid=" + callingPid + ") when starting: "
2785 + intent.toString());
2786 err = START_PERMISSION_DENIED;
2787 }
2788 }
2789
2790 if (err != START_SUCCESS) {
2791 if (resultRecord != null) {
2792 sendActivityResultLocked(-1,
2793 resultRecord, resultWho, requestCode,
2794 Activity.RESULT_CANCELED, null);
2795 }
2796 return err;
2797 }
2798
2799 final int perm = checkComponentPermission(aInfo.permission, callingPid,
2800 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
2801 if (perm != PackageManager.PERMISSION_GRANTED) {
2802 if (resultRecord != null) {
2803 sendActivityResultLocked(-1,
2804 resultRecord, resultWho, requestCode,
2805 Activity.RESULT_CANCELED, null);
2806 }
2807 String msg = "Permission Denial: starting " + intent.toString()
2808 + " from " + callerApp + " (pid=" + callingPid
2809 + ", uid=" + callingUid + ")"
2810 + " requires " + aInfo.permission;
2811 Log.w(TAG, msg);
2812 throw new SecurityException(msg);
2813 }
2814
2815 if (mWatcher != null) {
2816 boolean abort = false;
2817 try {
2818 // The Intent we give to the watcher has the extra data
2819 // stripped off, since it can contain private information.
2820 Intent watchIntent = intent.cloneFilter();
2821 abort = !mWatcher.activityStarting(watchIntent,
2822 aInfo.applicationInfo.packageName);
2823 } catch (RemoteException e) {
2824 mWatcher = null;
2825 }
2826
2827 if (abort) {
2828 if (resultRecord != null) {
2829 sendActivityResultLocked(-1,
2830 resultRecord, resultWho, requestCode,
2831 Activity.RESULT_CANCELED, null);
2832 }
2833 // We pretend to the caller that it was really started, but
2834 // they will just get a cancel result.
2835 return START_SUCCESS;
2836 }
2837 }
2838
2839 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
2840 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002841 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002842
2843 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
2844 != 0 ? r : null;
2845
2846 // We'll invoke onUserLeaving before onPause only if the launching
2847 // activity did not explicitly state that this is an automated launch.
2848 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
2849 if (DEBUG_USER_LEAVING) Log.v(TAG,
2850 "startActivity() => mUserLeaving=" + mUserLeaving);
2851
2852 // If the onlyIfNeeded flag is set, then we can do this if the activity
2853 // being launched is the same as the one making the call... or, as
2854 // a special case, if we do not know the caller then we count the
2855 // current top activity as the caller.
2856 if (onlyIfNeeded) {
2857 HistoryRecord checkedCaller = sourceRecord;
2858 if (checkedCaller == null) {
2859 checkedCaller = topRunningActivityLocked(notTop);
2860 }
2861 if (!checkedCaller.realActivity.equals(r.realActivity)) {
2862 // Caller is not the same as launcher, so always needed.
2863 onlyIfNeeded = false;
2864 }
2865 }
2866
2867 if (grantedUriPermissions != null && callingUid > 0) {
2868 for (int i=0; i<grantedUriPermissions.length; i++) {
2869 grantUriPermissionLocked(callingUid, r.packageName,
2870 grantedUriPermissions[i], grantedMode, r);
2871 }
2872 }
2873
2874 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
2875 intent, r);
2876
2877 if (sourceRecord == null) {
2878 // This activity is not being started from another... in this
2879 // case we -always- start a new task.
2880 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
2881 Log.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
2882 + intent);
2883 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2884 }
2885 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2886 // The original activity who is starting us is running as a single
2887 // instance... this new activity it is starting must go on its
2888 // own task.
2889 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2890 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
2891 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
2892 // The activity being started is a single instance... it always
2893 // gets launched into its own task.
2894 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2895 }
2896
2897 if (resultRecord != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
2898 // For whatever reason this activity is being launched into a new
2899 // task... yet the caller has requested a result back. Well, that
2900 // is pretty messed up, so instead immediately send back a cancel
2901 // and let the new task continue launched as normal without a
2902 // dependency on its originator.
2903 Log.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
2904 sendActivityResultLocked(-1,
2905 resultRecord, resultWho, requestCode,
2906 Activity.RESULT_CANCELED, null);
2907 r.resultTo = null;
2908 resultRecord = null;
2909 }
2910
2911 boolean addingToTask = false;
2912 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
2913 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
2914 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
2915 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2916 // If bring to front is requested, and no result is requested, and
2917 // we can find a task that was started with this same
2918 // component, then instead of launching bring that one to the front.
2919 if (resultRecord == null) {
2920 // See if there is a task to bring to the front. If this is
2921 // a SINGLE_INSTANCE activity, there can be one and only one
2922 // instance of it in the history, and it is always in its own
2923 // unique task, so we do a special search.
2924 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
2925 ? findTaskLocked(intent, r.info)
2926 : findActivityLocked(intent, r.info);
2927 if (taskTop != null) {
2928 if (taskTop.task.intent == null) {
2929 // This task was started because of movement of
2930 // the activity based on affinity... now that we
2931 // are actually launching it, we can assign the
2932 // base intent.
2933 taskTop.task.setIntent(intent, r.info);
2934 }
2935 // If the target task is not in the front, then we need
2936 // to bring it to the front... except... well, with
2937 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
2938 // to have the same behavior as if a new instance was
2939 // being started, which means not bringing it to the front
2940 // if the caller is not itself in the front.
2941 HistoryRecord curTop = topRunningActivityLocked(notTop);
2942 if (curTop.task != taskTop.task) {
2943 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
2944 boolean callerAtFront = sourceRecord == null
2945 || curTop.task == sourceRecord.task;
2946 if (callerAtFront) {
2947 // We really do want to push this one into the
2948 // user's face, right now.
2949 moveTaskToFrontLocked(taskTop.task);
2950 }
2951 }
2952 // If the caller has requested that the target task be
2953 // reset, then do so.
2954 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2955 taskTop = resetTaskIfNeededLocked(taskTop, r);
2956 }
2957 if (onlyIfNeeded) {
2958 // We don't need to start a new activity, and
2959 // the client said not to do anything if that
2960 // is the case, so this is it! And for paranoia, make
2961 // sure we have correctly resumed the top activity.
2962 resumeTopActivityLocked(null);
2963 return START_RETURN_INTENT_TO_CALLER;
2964 }
2965 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
2966 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
2967 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2968 // In this situation we want to remove all activities
2969 // from the task up to the one being started. In most
2970 // cases this means we are resetting the task to its
2971 // initial state.
2972 HistoryRecord top = performClearTopTaskLocked(
2973 taskTop.task.taskId, r, true);
2974 if (top != null) {
2975 if (top.frontOfTask) {
2976 // Activity aliases may mean we use different
2977 // intents for the top activity, so make sure
2978 // the task now has the identity of the new
2979 // intent.
2980 top.task.setIntent(r.intent, r.info);
2981 }
2982 logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
2983 deliverNewIntentLocked(top, r.intent);
2984 } else {
2985 // A special case: we need to
2986 // start the activity because it is not currently
2987 // running, and the caller has asked to clear the
2988 // current task to have this activity at the top.
2989 addingToTask = true;
2990 // Now pretend like this activity is being started
2991 // by the top of its task, so it is put in the
2992 // right place.
2993 sourceRecord = taskTop;
2994 }
2995 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
2996 // In this case the top activity on the task is the
2997 // same as the one being launched, so we take that
2998 // as a request to bring the task to the foreground.
2999 // If the top activity in the task is the root
3000 // activity, deliver this new intent to it if it
3001 // desires.
3002 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3003 && taskTop.realActivity.equals(r.realActivity)) {
3004 logStartActivity(LOG_AM_NEW_INTENT, r, taskTop.task);
3005 if (taskTop.frontOfTask) {
3006 taskTop.task.setIntent(r.intent, r.info);
3007 }
3008 deliverNewIntentLocked(taskTop, r.intent);
3009 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3010 // In this case we are launching the root activity
3011 // of the task, but with a different intent. We
3012 // should start a new instance on top.
3013 addingToTask = true;
3014 sourceRecord = taskTop;
3015 }
3016 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3017 // In this case an activity is being launched in to an
3018 // existing task, without resetting that task. This
3019 // is typically the situation of launching an activity
3020 // from a notification or shortcut. We want to place
3021 // the new activity on top of the current task.
3022 addingToTask = true;
3023 sourceRecord = taskTop;
3024 } else if (!taskTop.task.rootWasReset) {
3025 // In this case we are launching in to an existing task
3026 // that has not yet been started from its front door.
3027 // The current task has been brought to the front.
3028 // Ideally, we'd probably like to place this new task
3029 // at the bottom of its stack, but that's a little hard
3030 // to do with the current organization of the code so
3031 // for now we'll just drop it.
3032 taskTop.task.setIntent(r.intent, r.info);
3033 }
3034 if (!addingToTask) {
3035 // We didn't do anything... but it was needed (a.k.a., client
3036 // don't use that intent!) And for paranoia, make
3037 // sure we have correctly resumed the top activity.
3038 resumeTopActivityLocked(null);
3039 return START_TASK_TO_FRONT;
3040 }
3041 }
3042 }
3043 }
3044
3045 //String uri = r.intent.toURI();
3046 //Intent intent2 = new Intent(uri);
3047 //Log.i(TAG, "Given intent: " + r.intent);
3048 //Log.i(TAG, "URI is: " + uri);
3049 //Log.i(TAG, "To intent: " + intent2);
3050
3051 if (r.packageName != null) {
3052 // If the activity being launched is the same as the one currently
3053 // at the top, then we need to check if it should only be launched
3054 // once.
3055 HistoryRecord top = topRunningActivityLocked(notTop);
3056 if (top != null && resultRecord == null) {
3057 if (top.realActivity.equals(r.realActivity)) {
3058 if (top.app != null && top.app.thread != null) {
3059 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3060 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3061 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3062 logStartActivity(LOG_AM_NEW_INTENT, top, top.task);
3063 // For paranoia, make sure we have correctly
3064 // resumed the top activity.
3065 resumeTopActivityLocked(null);
3066 if (onlyIfNeeded) {
3067 // We don't need to start a new activity, and
3068 // the client said not to do anything if that
3069 // is the case, so this is it!
3070 return START_RETURN_INTENT_TO_CALLER;
3071 }
3072 deliverNewIntentLocked(top, r.intent);
3073 return START_DELIVERED_TO_TOP;
3074 }
3075 }
3076 }
3077 }
3078
3079 } else {
3080 if (resultRecord != null) {
3081 sendActivityResultLocked(-1,
3082 resultRecord, resultWho, requestCode,
3083 Activity.RESULT_CANCELED, null);
3084 }
3085 return START_CLASS_NOT_FOUND;
3086 }
3087
3088 boolean newTask = false;
3089
3090 // Should this be considered a new task?
3091 if (resultRecord == null && !addingToTask
3092 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3093 // todo: should do better management of integers.
3094 mCurTask++;
3095 if (mCurTask <= 0) {
3096 mCurTask = 1;
3097 }
3098 r.task = new TaskRecord(mCurTask, r.info, intent,
3099 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3100 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3101 + " in new task " + r.task);
3102 newTask = true;
3103 addRecentTask(r.task);
3104
3105 } else if (sourceRecord != null) {
3106 if (!addingToTask &&
3107 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3108 // In this case, we are adding the activity to an existing
3109 // task, but the caller has asked to clear that task if the
3110 // activity is already running.
3111 HistoryRecord top = performClearTopTaskLocked(
3112 sourceRecord.task.taskId, r, true);
3113 if (top != null) {
3114 logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
3115 deliverNewIntentLocked(top, r.intent);
3116 // For paranoia, make sure we have correctly
3117 // resumed the top activity.
3118 resumeTopActivityLocked(null);
3119 return START_DELIVERED_TO_TOP;
3120 }
3121 } else if (!addingToTask &&
3122 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3123 // In this case, we are launching an activity in our own task
3124 // that may already be running somewhere in the history, and
3125 // we want to shuffle it to the front of the stack if so.
3126 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3127 if (where >= 0) {
3128 HistoryRecord top = moveActivityToFrontLocked(where);
3129 logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
3130 deliverNewIntentLocked(top, r.intent);
3131 resumeTopActivityLocked(null);
3132 return START_DELIVERED_TO_TOP;
3133 }
3134 }
3135 // An existing activity is starting this new activity, so we want
3136 // to keep the new one in the same task as the one that is starting
3137 // it.
3138 r.task = sourceRecord.task;
3139 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3140 + " in existing task " + r.task);
3141
3142 } else {
3143 // This not being started from an existing activity, and not part
3144 // of a new task... just put it in the top task, though these days
3145 // this case should never happen.
3146 final int N = mHistory.size();
3147 HistoryRecord prev =
3148 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3149 r.task = prev != null
3150 ? prev.task
3151 : new TaskRecord(mCurTask, r.info, intent,
3152 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3153 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3154 + " in new guessed " + r.task);
3155 }
3156 if (newTask) {
3157 EventLog.writeEvent(LOG_AM_CREATE_TASK, r.task.taskId);
3158 }
3159 logStartActivity(LOG_AM_CREATE_ACTIVITY, r, r.task);
3160 startActivityLocked(r, newTask);
3161 return START_SUCCESS;
3162 }
3163
3164 public final int startActivity(IApplicationThread caller,
3165 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3166 int grantedMode, IBinder resultTo,
3167 String resultWho, int requestCode, boolean onlyIfNeeded,
3168 boolean debug) {
3169 // Refuse possible leaked file descriptors
3170 if (intent != null && intent.hasFileDescriptors()) {
3171 throw new IllegalArgumentException("File descriptors passed in Intent");
3172 }
3173
The Android Open Source Project4df24232009-03-05 14:34:35 -08003174 final boolean componentSpecified = intent.getComponent() != null;
3175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003176 // Don't modify the client's object!
3177 intent = new Intent(intent);
3178
3179 // Collect information about the target of the Intent.
3180 // Must do this before locking, because resolving the intent
3181 // may require launching a process to run its content provider.
3182 ActivityInfo aInfo;
3183 try {
3184 ResolveInfo rInfo =
3185 ActivityThread.getPackageManager().resolveIntent(
3186 intent, resolvedType,
3187 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003188 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003189 aInfo = rInfo != null ? rInfo.activityInfo : null;
3190 } catch (RemoteException e) {
3191 aInfo = null;
3192 }
3193
3194 if (aInfo != null) {
3195 // Store the found target back into the intent, because now that
3196 // we have it we never want to do this again. For example, if the
3197 // user navigates back to this point in the history, we should
3198 // always restart the exact same activity.
3199 intent.setComponent(new ComponentName(
3200 aInfo.applicationInfo.packageName, aInfo.name));
3201
3202 // Don't debug things in the system process
3203 if (debug) {
3204 if (!aInfo.processName.equals("system")) {
3205 setDebugApp(aInfo.processName, true, false);
3206 }
3207 }
3208 }
3209
3210 synchronized(this) {
3211 final long origId = Binder.clearCallingIdentity();
3212 int res = startActivityLocked(caller, intent, resolvedType,
3213 grantedUriPermissions, grantedMode, aInfo,
3214 resultTo, resultWho, requestCode, -1, -1,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003215 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003216 Binder.restoreCallingIdentity(origId);
3217 return res;
3218 }
3219 }
3220
3221 public boolean startNextMatchingActivity(IBinder callingActivity,
3222 Intent intent) {
3223 // Refuse possible leaked file descriptors
3224 if (intent != null && intent.hasFileDescriptors() == true) {
3225 throw new IllegalArgumentException("File descriptors passed in Intent");
3226 }
3227
3228 synchronized (this) {
3229 int index = indexOfTokenLocked(callingActivity, false);
3230 if (index < 0) {
3231 return false;
3232 }
3233 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3234 if (r.app == null || r.app.thread == null) {
3235 // The caller is not running... d'oh!
3236 return false;
3237 }
3238 intent = new Intent(intent);
3239 // The caller is not allowed to change the data.
3240 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3241 // And we are resetting to find the next component...
3242 intent.setComponent(null);
3243
3244 ActivityInfo aInfo = null;
3245 try {
3246 List<ResolveInfo> resolves =
3247 ActivityThread.getPackageManager().queryIntentActivities(
3248 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003249 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250
3251 // Look for the original activity in the list...
3252 final int N = resolves != null ? resolves.size() : 0;
3253 for (int i=0; i<N; i++) {
3254 ResolveInfo rInfo = resolves.get(i);
3255 if (rInfo.activityInfo.packageName.equals(r.packageName)
3256 && rInfo.activityInfo.name.equals(r.info.name)) {
3257 // We found the current one... the next matching is
3258 // after it.
3259 i++;
3260 if (i<N) {
3261 aInfo = resolves.get(i).activityInfo;
3262 }
3263 break;
3264 }
3265 }
3266 } catch (RemoteException e) {
3267 }
3268
3269 if (aInfo == null) {
3270 // Nobody who is next!
3271 return false;
3272 }
3273
3274 intent.setComponent(new ComponentName(
3275 aInfo.applicationInfo.packageName, aInfo.name));
3276 intent.setFlags(intent.getFlags()&~(
3277 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3278 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3279 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3280 Intent.FLAG_ACTIVITY_NEW_TASK));
3281
3282 // Okay now we need to start the new activity, replacing the
3283 // currently running activity. This is a little tricky because
3284 // we want to start the new one as if the current one is finished,
3285 // but not finish the current one first so that there is no flicker.
3286 // And thus...
3287 final boolean wasFinishing = r.finishing;
3288 r.finishing = true;
3289
3290 // Propagate reply information over to the new activity.
3291 final HistoryRecord resultTo = r.resultTo;
3292 final String resultWho = r.resultWho;
3293 final int requestCode = r.requestCode;
3294 r.resultTo = null;
3295 if (resultTo != null) {
3296 resultTo.removeResultsLocked(r, resultWho, requestCode);
3297 }
3298
3299 final long origId = Binder.clearCallingIdentity();
3300 // XXX we are not dealing with propagating grantedUriPermissions...
3301 // those are not yet exposed to user code, so there is no need.
3302 int res = startActivityLocked(r.app.thread, intent,
3303 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003304 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 Binder.restoreCallingIdentity(origId);
3306
3307 r.finishing = wasFinishing;
3308 if (res != START_SUCCESS) {
3309 return false;
3310 }
3311 return true;
3312 }
3313 }
3314
3315 final int startActivityInPackage(int uid,
3316 Intent intent, String resolvedType, IBinder resultTo,
3317 String resultWho, int requestCode, boolean onlyIfNeeded) {
The Android Open Source Project4df24232009-03-05 14:34:35 -08003318 final boolean componentSpecified = intent.getComponent() != null;
3319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 // Don't modify the client's object!
3321 intent = new Intent(intent);
3322
3323 // Collect information about the target of the Intent.
3324 // Must do this before locking, because resolving the intent
3325 // may require launching a process to run its content provider.
3326 ActivityInfo aInfo;
3327 try {
3328 ResolveInfo rInfo =
3329 ActivityThread.getPackageManager().resolveIntent(
3330 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003331 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332 aInfo = rInfo != null ? rInfo.activityInfo : null;
3333 } catch (RemoteException e) {
3334 aInfo = null;
3335 }
3336
3337 if (aInfo != null) {
3338 // Store the found target back into the intent, because now that
3339 // we have it we never want to do this again. For example, if the
3340 // user navigates back to this point in the history, we should
3341 // always restart the exact same activity.
3342 intent.setComponent(new ComponentName(
3343 aInfo.applicationInfo.packageName, aInfo.name));
3344 }
3345
3346 synchronized(this) {
3347 return startActivityLocked(null, intent, resolvedType,
3348 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003349 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003350 }
3351 }
3352
3353 private final void addRecentTask(TaskRecord task) {
3354 // Remove any existing entries that are the same kind of task.
3355 int N = mRecentTasks.size();
3356 for (int i=0; i<N; i++) {
3357 TaskRecord tr = mRecentTasks.get(i);
3358 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3359 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3360 mRecentTasks.remove(i);
3361 i--;
3362 N--;
3363 if (task.intent == null) {
3364 // If the new recent task we are adding is not fully
3365 // specified, then replace it with the existing recent task.
3366 task = tr;
3367 }
3368 }
3369 }
3370 if (N >= MAX_RECENT_TASKS) {
3371 mRecentTasks.remove(N-1);
3372 }
3373 mRecentTasks.add(0, task);
3374 }
3375
3376 public void setRequestedOrientation(IBinder token,
3377 int requestedOrientation) {
3378 synchronized (this) {
3379 int index = indexOfTokenLocked(token, false);
3380 if (index < 0) {
3381 return;
3382 }
3383 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3384 final long origId = Binder.clearCallingIdentity();
3385 mWindowManager.setAppOrientation(r, requestedOrientation);
3386 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003387 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 r.mayFreezeScreenLocked(r.app) ? r : null);
3389 if (config != null) {
3390 r.frozenBeforeDestroy = true;
3391 if (!updateConfigurationLocked(config, r)) {
3392 resumeTopActivityLocked(null);
3393 }
3394 }
3395 Binder.restoreCallingIdentity(origId);
3396 }
3397 }
3398
3399 public int getRequestedOrientation(IBinder token) {
3400 synchronized (this) {
3401 int index = indexOfTokenLocked(token, false);
3402 if (index < 0) {
3403 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3404 }
3405 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3406 return mWindowManager.getAppOrientation(r);
3407 }
3408 }
3409
3410 private final void stopActivityLocked(HistoryRecord r) {
3411 if (DEBUG_SWITCH) Log.d(TAG, "Stopping: " + r);
3412 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3413 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3414 if (!r.finishing) {
3415 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3416 "no-history");
3417 }
3418 } else if (r.app != null && r.app.thread != null) {
3419 if (mFocusedActivity == r) {
3420 setFocusedActivityLocked(topRunningActivityLocked(null));
3421 }
3422 r.resumeKeyDispatchingLocked();
3423 try {
3424 r.stopped = false;
3425 r.state = ActivityState.STOPPING;
3426 if (DEBUG_VISBILITY) Log.v(
3427 TAG, "Stopping visible=" + r.visible + " for " + r);
3428 if (!r.visible) {
3429 mWindowManager.setAppVisibility(r, false);
3430 }
3431 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3432 } catch (Exception e) {
3433 // Maybe just ignore exceptions here... if the process
3434 // has crashed, our death notification will clean things
3435 // up.
3436 Log.w(TAG, "Exception thrown during pause", e);
3437 // Just in case, assume it to be stopped.
3438 r.stopped = true;
3439 r.state = ActivityState.STOPPED;
3440 if (r.configDestroy) {
3441 destroyActivityLocked(r, true);
3442 }
3443 }
3444 }
3445 }
3446
3447 /**
3448 * @return Returns true if the activity is being finished, false if for
3449 * some reason it is being left as-is.
3450 */
3451 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3452 Intent resultData, String reason) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003453 if (DEBUG_RESULTS) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 TAG, "Finishing activity: token=" + token
3455 + ", result=" + resultCode + ", data=" + resultData);
3456
3457 int index = indexOfTokenLocked(token, false);
3458 if (index < 0) {
3459 return false;
3460 }
3461 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3462
3463 // Is this the last activity left?
3464 boolean lastActivity = true;
3465 for (int i=mHistory.size()-1; i>=0; i--) {
3466 HistoryRecord p = (HistoryRecord)mHistory.get(i);
3467 if (!p.finishing && p != r) {
3468 lastActivity = false;
3469 break;
3470 }
3471 }
3472
3473 // If this is the last activity, but it is the home activity, then
3474 // just don't finish it.
3475 if (lastActivity) {
3476 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
3477 return false;
3478 }
3479 }
3480
3481 finishActivityLocked(r, index, resultCode, resultData, reason);
3482 return true;
3483 }
3484
3485 /**
3486 * @return Returns true if this activity has been removed from the history
3487 * list, or false if it is still in the list and will be removed later.
3488 */
3489 private final boolean finishActivityLocked(HistoryRecord r, int index,
3490 int resultCode, Intent resultData, String reason) {
3491 if (r.finishing) {
3492 Log.w(TAG, "Duplicate finish request for " + r);
3493 return false;
3494 }
3495
3496 r.finishing = true;
3497 EventLog.writeEvent(LOG_AM_FINISH_ACTIVITY,
3498 System.identityHashCode(r),
3499 r.task.taskId, r.shortComponentName, reason);
3500 r.task.numActivities--;
3501 if (r.frontOfTask && index < (mHistory.size()-1)) {
3502 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
3503 if (next.task == r.task) {
3504 next.frontOfTask = true;
3505 }
3506 }
3507
3508 r.pauseKeyDispatchingLocked();
3509 if (mFocusedActivity == r) {
3510 setFocusedActivityLocked(topRunningActivityLocked(null));
3511 }
3512
3513 // send the result
3514 HistoryRecord resultTo = r.resultTo;
3515 if (resultTo != null) {
Chris Tate8a7dc172009-03-24 20:11:42 -07003516 if (DEBUG_RESULTS) Log.v(TAG, "Adding result to " + resultTo
3517 + " who=" + r.resultWho + " req=" + r.requestCode
3518 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519 if (r.info.applicationInfo.uid > 0) {
3520 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3521 r.packageName, resultData, r);
3522 }
3523 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3524 resultData);
3525 r.resultTo = null;
3526 }
Chris Tate8a7dc172009-03-24 20:11:42 -07003527 else if (DEBUG_RESULTS) Log.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528
3529 // Make sure this HistoryRecord is not holding on to other resources,
3530 // because clients have remote IPC references to this object so we
3531 // can't assume that will go away and want to avoid circular IPC refs.
3532 r.results = null;
3533 r.pendingResults = null;
3534 r.newIntents = null;
3535 r.icicle = null;
3536
3537 if (mPendingThumbnails.size() > 0) {
3538 // There are clients waiting to receive thumbnails so, in case
3539 // this is an activity that someone is waiting for, add it
3540 // to the pending list so we can correctly update the clients.
3541 mCancelledThumbnails.add(r);
3542 }
3543
3544 if (mResumedActivity == r) {
3545 boolean endTask = index <= 0
3546 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
3547 if (DEBUG_TRANSITION) Log.v(TAG,
3548 "Prepare close transition: finishing " + r);
3549 mWindowManager.prepareAppTransition(endTask
3550 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
3551 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
3552
3553 // Tell window manager to prepare for this one to be removed.
3554 mWindowManager.setAppVisibility(r, false);
3555
3556 if (mPausingActivity == null) {
3557 if (DEBUG_PAUSE) Log.v(TAG, "Finish needs to pause: " + r);
3558 if (DEBUG_USER_LEAVING) Log.v(TAG, "finish() => pause with userLeaving=false");
3559 startPausingLocked(false, false);
3560 }
3561
3562 } else if (r.state != ActivityState.PAUSING) {
3563 // If the activity is PAUSING, we will complete the finish once
3564 // it is done pausing; else we can just directly finish it here.
3565 if (DEBUG_PAUSE) Log.v(TAG, "Finish not pausing: " + r);
3566 return finishCurrentActivityLocked(r, index,
3567 FINISH_AFTER_PAUSE) == null;
3568 } else {
3569 if (DEBUG_PAUSE) Log.v(TAG, "Finish waiting for pause of: " + r);
3570 }
3571
3572 return false;
3573 }
3574
3575 private static final int FINISH_IMMEDIATELY = 0;
3576 private static final int FINISH_AFTER_PAUSE = 1;
3577 private static final int FINISH_AFTER_VISIBLE = 2;
3578
3579 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
3580 int mode) {
3581 final int index = indexOfTokenLocked(r, false);
3582 if (index < 0) {
3583 return null;
3584 }
3585
3586 return finishCurrentActivityLocked(r, index, mode);
3587 }
3588
3589 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
3590 int index, int mode) {
3591 // First things first: if this activity is currently visible,
3592 // and the resumed activity is not yet visible, then hold off on
3593 // finishing until the resumed one becomes visible.
3594 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
3595 if (!mStoppingActivities.contains(r)) {
3596 mStoppingActivities.add(r);
3597 if (mStoppingActivities.size() > 3) {
3598 // If we already have a few activities waiting to stop,
3599 // then give up on things going idle and start clearing
3600 // them out.
3601 Message msg = Message.obtain();
3602 msg.what = ActivityManagerService.IDLE_NOW_MSG;
3603 mHandler.sendMessage(msg);
3604 }
3605 }
3606 r.state = ActivityState.STOPPING;
3607 updateOomAdjLocked();
3608 return r;
3609 }
3610
3611 // make sure the record is cleaned out of other places.
3612 mStoppingActivities.remove(r);
3613 mWaitingVisibleActivities.remove(r);
3614 if (mResumedActivity == r) {
3615 mResumedActivity = null;
3616 }
3617 final ActivityState prevState = r.state;
3618 r.state = ActivityState.FINISHING;
3619
3620 if (mode == FINISH_IMMEDIATELY
3621 || prevState == ActivityState.STOPPED
3622 || prevState == ActivityState.INITIALIZING) {
3623 // If this activity is already stopped, we can just finish
3624 // it right now.
3625 return destroyActivityLocked(r, true) ? null : r;
3626 } else {
3627 // Need to go through the full pause cycle to get this
3628 // activity into the stopped state and then finish it.
3629 if (localLOGV) Log.v(TAG, "Enqueueing pending finish: " + r);
3630 mFinishingActivities.add(r);
3631 resumeTopActivityLocked(null);
3632 }
3633 return r;
3634 }
3635
3636 /**
3637 * This is the internal entry point for handling Activity.finish().
3638 *
3639 * @param token The Binder token referencing the Activity we want to finish.
3640 * @param resultCode Result code, if any, from this Activity.
3641 * @param resultData Result data (Intent), if any, from this Activity.
3642 *
3643 * @result Returns true if the activity successfully finished, or false if it is still running.
3644 */
3645 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
3646 // Refuse possible leaked file descriptors
3647 if (resultData != null && resultData.hasFileDescriptors() == true) {
3648 throw new IllegalArgumentException("File descriptors passed in Intent");
3649 }
3650
3651 synchronized(this) {
3652 if (mWatcher != null) {
3653 // Find the first activity that is not finishing.
3654 HistoryRecord next = topRunningActivityLocked(token, 0);
3655 if (next != null) {
3656 // ask watcher if this is allowed
3657 boolean resumeOK = true;
3658 try {
3659 resumeOK = mWatcher.activityResuming(next.packageName);
3660 } catch (RemoteException e) {
3661 mWatcher = null;
3662 }
3663
3664 if (!resumeOK) {
3665 return false;
3666 }
3667 }
3668 }
3669 final long origId = Binder.clearCallingIdentity();
3670 boolean res = requestFinishActivityLocked(token, resultCode,
3671 resultData, "app-request");
3672 Binder.restoreCallingIdentity(origId);
3673 return res;
3674 }
3675 }
3676
3677 void sendActivityResultLocked(int callingUid, HistoryRecord r,
3678 String resultWho, int requestCode, int resultCode, Intent data) {
3679
3680 if (callingUid > 0) {
3681 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3682 data, r);
3683 }
3684
The Android Open Source Project10592532009-03-18 17:39:46 -07003685 if (DEBUG_RESULTS) Log.v(TAG, "Send activity result to " + r
3686 + " : who=" + resultWho + " req=" + requestCode
3687 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
3689 try {
3690 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3691 list.add(new ResultInfo(resultWho, requestCode,
3692 resultCode, data));
3693 r.app.thread.scheduleSendResult(r, list);
3694 return;
3695 } catch (Exception e) {
3696 Log.w(TAG, "Exception thrown sending result to " + r, e);
3697 }
3698 }
3699
3700 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
3701 }
3702
3703 public final void finishSubActivity(IBinder token, String resultWho,
3704 int requestCode) {
3705 synchronized(this) {
3706 int index = indexOfTokenLocked(token, false);
3707 if (index < 0) {
3708 return;
3709 }
3710 HistoryRecord self = (HistoryRecord)mHistory.get(index);
3711
3712 final long origId = Binder.clearCallingIdentity();
3713
3714 int i;
3715 for (i=mHistory.size()-1; i>=0; i--) {
3716 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3717 if (r.resultTo == self && r.requestCode == requestCode) {
3718 if ((r.resultWho == null && resultWho == null) ||
3719 (r.resultWho != null && r.resultWho.equals(resultWho))) {
3720 finishActivityLocked(r, i,
3721 Activity.RESULT_CANCELED, null, "request-sub");
3722 }
3723 }
3724 }
3725
3726 Binder.restoreCallingIdentity(origId);
3727 }
3728 }
3729
3730 /**
3731 * Perform clean-up of service connections in an activity record.
3732 */
3733 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
3734 // Throw away any services that have been bound by this activity.
3735 if (r.connections != null) {
3736 Iterator<ConnectionRecord> it = r.connections.iterator();
3737 while (it.hasNext()) {
3738 ConnectionRecord c = it.next();
3739 removeConnectionLocked(c, null, r);
3740 }
3741 r.connections = null;
3742 }
3743 }
3744
3745 /**
3746 * Perform the common clean-up of an activity record. This is called both
3747 * as part of destroyActivityLocked() (when destroying the client-side
3748 * representation) and cleaning things up as a result of its hosting
3749 * processing going away, in which case there is no remaining client-side
3750 * state to destroy so only the cleanup here is needed.
3751 */
3752 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
3753 if (mResumedActivity == r) {
3754 mResumedActivity = null;
3755 }
3756 if (mFocusedActivity == r) {
3757 mFocusedActivity = null;
3758 }
3759
3760 r.configDestroy = false;
3761 r.frozenBeforeDestroy = false;
3762
3763 // Make sure this record is no longer in the pending finishes list.
3764 // This could happen, for example, if we are trimming activities
3765 // down to the max limit while they are still waiting to finish.
3766 mFinishingActivities.remove(r);
3767 mWaitingVisibleActivities.remove(r);
3768
3769 // Remove any pending results.
3770 if (r.finishing && r.pendingResults != null) {
3771 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
3772 PendingIntentRecord rec = apr.get();
3773 if (rec != null) {
3774 cancelIntentSenderLocked(rec, false);
3775 }
3776 }
3777 r.pendingResults = null;
3778 }
3779
3780 if (cleanServices) {
3781 cleanUpActivityServicesLocked(r);
3782 }
3783
3784 if (mPendingThumbnails.size() > 0) {
3785 // There are clients waiting to receive thumbnails so, in case
3786 // this is an activity that someone is waiting for, add it
3787 // to the pending list so we can correctly update the clients.
3788 mCancelledThumbnails.add(r);
3789 }
3790
3791 // Get rid of any pending idle timeouts.
3792 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
3793 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
3794 }
3795
3796 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
3797 if (r.state != ActivityState.DESTROYED) {
3798 mHistory.remove(r);
3799 r.inHistory = false;
3800 r.state = ActivityState.DESTROYED;
3801 mWindowManager.removeAppToken(r);
3802 if (VALIDATE_TOKENS) {
3803 mWindowManager.validateAppTokens(mHistory);
3804 }
3805 cleanUpActivityServicesLocked(r);
3806 removeActivityUriPermissionsLocked(r);
3807 }
3808 }
3809
3810 /**
3811 * Destroy the current CLIENT SIDE instance of an activity. This may be
3812 * called both when actually finishing an activity, or when performing
3813 * a configuration switch where we destroy the current client-side object
3814 * but then create a new client-side object for this same HistoryRecord.
3815 */
3816 private final boolean destroyActivityLocked(HistoryRecord r,
3817 boolean removeFromApp) {
3818 if (DEBUG_SWITCH) Log.v(
3819 TAG, "Removing activity: token=" + r
3820 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
3821 EventLog.writeEvent(LOG_AM_DESTROY_ACTIVITY,
3822 System.identityHashCode(r),
3823 r.task.taskId, r.shortComponentName);
3824
3825 boolean removedFromHistory = false;
3826
3827 cleanUpActivityLocked(r, false);
3828
3829 if (r.app != null) {
3830 if (removeFromApp) {
3831 int idx = r.app.activities.indexOf(r);
3832 if (idx >= 0) {
3833 r.app.activities.remove(idx);
3834 }
3835 if (r.persistent) {
3836 decPersistentCountLocked(r.app);
3837 }
3838 }
3839
3840 boolean skipDestroy = false;
3841
3842 try {
3843 if (DEBUG_SWITCH) Log.i(TAG, "Destroying: " + r);
3844 r.app.thread.scheduleDestroyActivity(r, r.finishing,
3845 r.configChangeFlags);
3846 } catch (Exception e) {
3847 // We can just ignore exceptions here... if the process
3848 // has crashed, our death notification will clean things
3849 // up.
3850 //Log.w(TAG, "Exception thrown during finish", e);
3851 if (r.finishing) {
3852 removeActivityFromHistoryLocked(r);
3853 removedFromHistory = true;
3854 skipDestroy = true;
3855 }
3856 }
3857
3858 r.app = null;
3859 r.nowVisible = false;
3860
3861 if (r.finishing && !skipDestroy) {
3862 r.state = ActivityState.DESTROYING;
3863 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
3864 msg.obj = r;
3865 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
3866 } else {
3867 r.state = ActivityState.DESTROYED;
3868 }
3869 } else {
3870 // remove this record from the history.
3871 if (r.finishing) {
3872 removeActivityFromHistoryLocked(r);
3873 removedFromHistory = true;
3874 } else {
3875 r.state = ActivityState.DESTROYED;
3876 }
3877 }
3878
3879 r.configChangeFlags = 0;
3880
3881 if (!mLRUActivities.remove(r)) {
3882 Log.w(TAG, "Activity " + r + " being finished, but not in LRU list");
3883 }
3884
3885 return removedFromHistory;
3886 }
3887
3888 private static void removeHistoryRecordsForAppLocked(ArrayList list,
3889 ProcessRecord app)
3890 {
3891 int i = list.size();
3892 if (localLOGV) Log.v(
3893 TAG, "Removing app " + app + " from list " + list
3894 + " with " + i + " entries");
3895 while (i > 0) {
3896 i--;
3897 HistoryRecord r = (HistoryRecord)list.get(i);
3898 if (localLOGV) Log.v(
3899 TAG, "Record #" + i + " " + r + ": app=" + r.app);
3900 if (r.app == app) {
3901 if (localLOGV) Log.v(TAG, "Removing this entry!");
3902 list.remove(i);
3903 }
3904 }
3905 }
3906
3907 /**
3908 * Main function for removing an existing process from the activity manager
3909 * as a result of that process going away. Clears out all connections
3910 * to the process.
3911 */
3912 private final void handleAppDiedLocked(ProcessRecord app,
3913 boolean restarting) {
3914 cleanUpApplicationRecordLocked(app, restarting, -1);
3915 if (!restarting) {
3916 mLRUProcesses.remove(app);
3917 }
3918
3919 // Just in case...
3920 if (mPausingActivity != null && mPausingActivity.app == app) {
3921 if (DEBUG_PAUSE) Log.v(TAG, "App died while pausing: " + mPausingActivity);
3922 mPausingActivity = null;
3923 }
3924 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
3925 mLastPausedActivity = null;
3926 }
3927
3928 // Remove this application's activities from active lists.
3929 removeHistoryRecordsForAppLocked(mLRUActivities, app);
3930 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
3931 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
3932 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
3933
3934 boolean atTop = true;
3935 boolean hasVisibleActivities = false;
3936
3937 // Clean out the history list.
3938 int i = mHistory.size();
3939 if (localLOGV) Log.v(
3940 TAG, "Removing app " + app + " from history with " + i + " entries");
3941 while (i > 0) {
3942 i--;
3943 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3944 if (localLOGV) Log.v(
3945 TAG, "Record #" + i + " " + r + ": app=" + r.app);
3946 if (r.app == app) {
3947 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
3948 if (localLOGV) Log.v(
3949 TAG, "Removing this entry! frozen=" + r.haveState
3950 + " finishing=" + r.finishing);
3951 mHistory.remove(i);
3952
3953 r.inHistory = false;
3954 mWindowManager.removeAppToken(r);
3955 if (VALIDATE_TOKENS) {
3956 mWindowManager.validateAppTokens(mHistory);
3957 }
3958 removeActivityUriPermissionsLocked(r);
3959
3960 } else {
3961 // We have the current state for this activity, so
3962 // it can be restarted later when needed.
3963 if (localLOGV) Log.v(
3964 TAG, "Keeping entry, setting app to null");
3965 if (r.visible) {
3966 hasVisibleActivities = true;
3967 }
3968 r.app = null;
3969 r.nowVisible = false;
3970 if (!r.haveState) {
3971 r.icicle = null;
3972 }
3973 }
3974
3975 cleanUpActivityLocked(r, true);
3976 r.state = ActivityState.STOPPED;
3977 }
3978 atTop = false;
3979 }
3980
3981 app.activities.clear();
3982
3983 if (app.instrumentationClass != null) {
3984 Log.w(TAG, "Crash of app " + app.processName
3985 + " running instrumentation " + app.instrumentationClass);
3986 Bundle info = new Bundle();
3987 info.putString("shortMsg", "Process crashed.");
3988 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
3989 }
3990
3991 if (!restarting) {
3992 if (!resumeTopActivityLocked(null)) {
3993 // If there was nothing to resume, and we are not already
3994 // restarting this process, but there is a visible activity that
3995 // is hosted by the process... then make sure all visible
3996 // activities are running, taking care of restarting this
3997 // process.
3998 if (hasVisibleActivities) {
3999 ensureActivitiesVisibleLocked(null, 0);
4000 }
4001 }
4002 }
4003 }
4004
4005 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4006 IBinder threadBinder = thread.asBinder();
4007
4008 // Find the application record.
4009 int count = mLRUProcesses.size();
4010 int i;
4011 for (i=0; i<count; i++) {
4012 ProcessRecord rec = mLRUProcesses.get(i);
4013 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4014 return i;
4015 }
4016 }
4017 return -1;
4018 }
4019
4020 private final ProcessRecord getRecordForAppLocked(
4021 IApplicationThread thread) {
4022 if (thread == null) {
4023 return null;
4024 }
4025
4026 int appIndex = getLRURecordIndexForAppLocked(thread);
4027 return appIndex >= 0 ? mLRUProcesses.get(appIndex) : null;
4028 }
4029
4030 private final void appDiedLocked(ProcessRecord app, int pid,
4031 IApplicationThread thread) {
4032
4033 mProcDeaths[0]++;
4034
4035 if (app.thread != null && app.thread.asBinder() == thread.asBinder()) {
4036 Log.i(TAG, "Process " + app.processName + " (pid " + pid
4037 + ") has died.");
4038 EventLog.writeEvent(LOG_AM_PROCESS_DIED, app.pid, app.processName);
4039 if (localLOGV) Log.v(
4040 TAG, "Dying app: " + app + ", pid: " + pid
4041 + ", thread: " + thread.asBinder());
4042 boolean doLowMem = app.instrumentationClass == null;
4043 handleAppDiedLocked(app, false);
4044
4045 if (doLowMem) {
4046 // If there are no longer any background processes running,
4047 // and the app that died was not running instrumentation,
4048 // then tell everyone we are now low on memory.
4049 boolean haveBg = false;
4050 int count = mLRUProcesses.size();
4051 int i;
4052 for (i=0; i<count; i++) {
4053 ProcessRecord rec = mLRUProcesses.get(i);
4054 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4055 haveBg = true;
4056 break;
4057 }
4058 }
4059
4060 if (!haveBg) {
4061 Log.i(TAG, "Low Memory: No more background processes.");
4062 EventLog.writeEvent(LOG_AM_LOW_MEMORY, mLRUProcesses.size());
4063 for (i=0; i<count; i++) {
4064 ProcessRecord rec = mLRUProcesses.get(i);
4065 if (rec.thread != null) {
4066 rec.lastRequestedGc = SystemClock.uptimeMillis();
4067 try {
4068 rec.thread.scheduleLowMemory();
4069 } catch (RemoteException e) {
4070 // Don't care if the process is gone.
4071 }
4072 }
4073 }
4074 }
4075 }
4076 } else if (Config.LOGD) {
4077 Log.d(TAG, "Received spurious death notification for thread "
4078 + thread.asBinder());
4079 }
4080 }
4081
4082 final String readFile(String filename) {
4083 try {
4084 FileInputStream fs = new FileInputStream(filename);
4085 byte[] inp = new byte[8192];
4086 int size = fs.read(inp);
4087 fs.close();
4088 return new String(inp, 0, 0, size);
4089 } catch (java.io.IOException e) {
4090 }
4091 return "";
4092 }
4093
4094 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4095 final String annotation) {
4096 if (app.notResponding || app.crashing) {
4097 return;
4098 }
4099
4100 // Log the ANR to the event log.
4101 EventLog.writeEvent(LOG_ANR, app.pid, app.processName, annotation);
4102
4103 // If we are on a secure build and the application is not interesting to the user (it is
4104 // not visible or in the background), just kill it instead of displaying a dialog.
4105 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
4106 if (isSecure && !app.isInterestingToUserLocked() && Process.myPid() != app.pid) {
4107 Process.killProcess(app.pid);
4108 return;
4109 }
4110
4111 // DeviceMonitor.start();
4112
4113 String processInfo = null;
4114 if (MONITOR_CPU_USAGE) {
4115 updateCpuStatsNow();
4116 synchronized (mProcessStatsThread) {
4117 processInfo = mProcessStats.printCurrentState();
4118 }
4119 }
4120
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004121 StringBuilder info = mStringBuilder;
4122 info.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004123 info.append("ANR (application not responding) in process: ");
4124 info.append(app.processName);
4125 if (annotation != null) {
4126 info.append("\nAnnotation: ");
4127 info.append(annotation);
4128 }
4129 if (MONITOR_CPU_USAGE) {
4130 info.append("\nCPU usage:\n");
4131 info.append(processInfo);
4132 }
4133 Log.i(TAG, info.toString());
4134
4135 // The application is not responding. Dump as many thread traces as we can.
4136 boolean fileDump = prepareTraceFile(true);
4137 if (!fileDump) {
4138 // Dumping traces to the log, just dump the process that isn't responding so
4139 // we don't overflow the log
4140 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4141 } else {
4142 // Dumping traces to a file so dump all active processes we know about
4143 synchronized (this) {
4144 for (int i = mLRUProcesses.size() - 1 ; i >= 0 ; i--) {
4145 ProcessRecord r = mLRUProcesses.get(i);
4146 if (r.thread != null) {
4147 Process.sendSignal(r.pid, Process.SIGNAL_QUIT);
4148 }
4149 }
4150 }
4151 }
4152
4153 if (mWatcher != null) {
4154 try {
4155 int res = mWatcher.appNotResponding(app.processName,
4156 app.pid, info.toString());
4157 if (res != 0) {
4158 if (res < 0) {
4159 // wait until the SIGQUIT has had a chance to process before killing the
4160 // process.
4161 try {
4162 wait(2000);
4163 } catch (InterruptedException e) {
4164 }
4165
4166 Process.killProcess(app.pid);
4167 return;
4168 }
4169 }
4170 } catch (RemoteException e) {
4171 mWatcher = null;
4172 }
4173 }
4174
4175 makeAppNotRespondingLocked(app,
4176 activity != null ? activity.shortComponentName : null,
4177 annotation != null ? "ANR " + annotation : "ANR",
4178 info.toString(), null);
4179 Message msg = Message.obtain();
4180 HashMap map = new HashMap();
4181 msg.what = SHOW_NOT_RESPONDING_MSG;
4182 msg.obj = map;
4183 map.put("app", app);
4184 if (activity != null) {
4185 map.put("activity", activity);
4186 }
4187
4188 mHandler.sendMessage(msg);
4189 return;
4190 }
4191
4192 /**
4193 * If a stack trace file has been configured, prepare the filesystem
4194 * by creating the directory if it doesn't exist and optionally
4195 * removing the old trace file.
4196 *
4197 * @param removeExisting If set, the existing trace file will be removed.
4198 * @return Returns true if the trace file preparations succeeded
4199 */
4200 public static boolean prepareTraceFile(boolean removeExisting) {
4201 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4202 boolean fileReady = false;
4203 if (!TextUtils.isEmpty(tracesPath)) {
4204 File f = new File(tracesPath);
4205 if (!f.exists()) {
4206 // Ensure the enclosing directory exists
4207 File dir = f.getParentFile();
4208 if (!dir.exists()) {
4209 fileReady = dir.mkdirs();
4210 FileUtils.setPermissions(dir.getAbsolutePath(),
4211 FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO, -1, -1);
4212 } else if (dir.isDirectory()) {
4213 fileReady = true;
4214 }
4215 } else if (removeExisting) {
4216 // Remove the previous traces file, so we don't fill the disk.
4217 // The VM will recreate it
4218 Log.i(TAG, "Removing old ANR trace file from " + tracesPath);
4219 fileReady = f.delete();
4220 }
4221 }
4222
4223 return fileReady;
4224 }
4225
4226
4227 private final void decPersistentCountLocked(ProcessRecord app)
4228 {
4229 app.persistentActivities--;
4230 if (app.persistentActivities > 0) {
4231 // Still more of 'em...
4232 return;
4233 }
4234 if (app.persistent) {
4235 // Ah, but the application itself is persistent. Whatever!
4236 return;
4237 }
4238
4239 // App is no longer persistent... make sure it and the ones
4240 // following it in the LRU list have the correc oom_adj.
4241 updateOomAdjLocked();
4242 }
4243
4244 public void setPersistent(IBinder token, boolean isPersistent) {
4245 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4246 != PackageManager.PERMISSION_GRANTED) {
4247 String msg = "Permission Denial: setPersistent() from pid="
4248 + Binder.getCallingPid()
4249 + ", uid=" + Binder.getCallingUid()
4250 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
4251 Log.w(TAG, msg);
4252 throw new SecurityException(msg);
4253 }
4254
4255 synchronized(this) {
4256 int index = indexOfTokenLocked(token, true);
4257 if (index < 0) {
4258 return;
4259 }
4260 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4261 ProcessRecord app = r.app;
4262
4263 if (localLOGV) Log.v(
4264 TAG, "Setting persistence " + isPersistent + ": " + r);
4265
4266 if (isPersistent) {
4267 if (r.persistent) {
4268 // Okay okay, I heard you already!
4269 if (localLOGV) Log.v(TAG, "Already persistent!");
4270 return;
4271 }
4272 r.persistent = true;
4273 app.persistentActivities++;
4274 if (localLOGV) Log.v(TAG, "Num persistent now: " + app.persistentActivities);
4275 if (app.persistentActivities > 1) {
4276 // We aren't the first...
4277 if (localLOGV) Log.v(TAG, "Not the first!");
4278 return;
4279 }
4280 if (app.persistent) {
4281 // This would be redundant.
4282 if (localLOGV) Log.v(TAG, "App is persistent!");
4283 return;
4284 }
4285
4286 // App is now persistent... make sure it and the ones
4287 // following it now have the correct oom_adj.
4288 final long origId = Binder.clearCallingIdentity();
4289 updateOomAdjLocked();
4290 Binder.restoreCallingIdentity(origId);
4291
4292 } else {
4293 if (!r.persistent) {
4294 // Okay okay, I heard you already!
4295 return;
4296 }
4297 r.persistent = false;
4298 final long origId = Binder.clearCallingIdentity();
4299 decPersistentCountLocked(app);
4300 Binder.restoreCallingIdentity(origId);
4301
4302 }
4303 }
4304 }
4305
4306 public boolean clearApplicationUserData(final String packageName,
4307 final IPackageDataObserver observer) {
4308 int uid = Binder.getCallingUid();
4309 int pid = Binder.getCallingPid();
4310 long callingId = Binder.clearCallingIdentity();
4311 try {
4312 IPackageManager pm = ActivityThread.getPackageManager();
4313 int pkgUid = -1;
4314 synchronized(this) {
4315 try {
4316 pkgUid = pm.getPackageUid(packageName);
4317 } catch (RemoteException e) {
4318 }
4319 if (pkgUid == -1) {
4320 Log.w(TAG, "Invalid packageName:" + packageName);
4321 return false;
4322 }
4323 if (uid == pkgUid || checkComponentPermission(
4324 android.Manifest.permission.CLEAR_APP_USER_DATA,
4325 pid, uid, -1)
4326 == PackageManager.PERMISSION_GRANTED) {
4327 restartPackageLocked(packageName, pkgUid);
4328 } else {
4329 throw new SecurityException(pid+" does not have permission:"+
4330 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4331 "for process:"+packageName);
4332 }
4333 }
4334
4335 try {
4336 //clear application user data
4337 pm.clearApplicationUserData(packageName, observer);
4338 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4339 Uri.fromParts("package", packageName, null));
4340 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4341 broadcastIntentLocked(null, null, intent,
4342 null, null, 0, null, null, null,
4343 false, false, MY_PID, Process.SYSTEM_UID);
4344 } catch (RemoteException e) {
4345 }
4346 } finally {
4347 Binder.restoreCallingIdentity(callingId);
4348 }
4349 return true;
4350 }
4351
4352 public void restartPackage(final String packageName) {
4353 if (checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4354 != PackageManager.PERMISSION_GRANTED) {
4355 String msg = "Permission Denial: restartPackage() from pid="
4356 + Binder.getCallingPid()
4357 + ", uid=" + Binder.getCallingUid()
4358 + " requires " + android.Manifest.permission.RESTART_PACKAGES;
4359 Log.w(TAG, msg);
4360 throw new SecurityException(msg);
4361 }
4362
4363 long callingId = Binder.clearCallingIdentity();
4364 try {
4365 IPackageManager pm = ActivityThread.getPackageManager();
4366 int pkgUid = -1;
4367 synchronized(this) {
4368 try {
4369 pkgUid = pm.getPackageUid(packageName);
4370 } catch (RemoteException e) {
4371 }
4372 if (pkgUid == -1) {
4373 Log.w(TAG, "Invalid packageName: " + packageName);
4374 return;
4375 }
4376 restartPackageLocked(packageName, pkgUid);
4377 }
4378 } finally {
4379 Binder.restoreCallingIdentity(callingId);
4380 }
4381 }
4382
4383 private void restartPackageLocked(final String packageName, int uid) {
4384 uninstallPackageLocked(packageName, uid, false);
4385 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
4386 Uri.fromParts("package", packageName, null));
4387 intent.putExtra(Intent.EXTRA_UID, uid);
4388 broadcastIntentLocked(null, null, intent,
4389 null, null, 0, null, null, null,
4390 false, false, MY_PID, Process.SYSTEM_UID);
4391 }
4392
4393 private final void uninstallPackageLocked(String name, int uid,
4394 boolean callerWillRestart) {
4395 if (Config.LOGD) Log.d(TAG, "Uninstalling process " + name);
4396
4397 int i, N;
4398
4399 final String procNamePrefix = name + ":";
4400 if (uid < 0) {
4401 try {
4402 uid = ActivityThread.getPackageManager().getPackageUid(name);
4403 } catch (RemoteException e) {
4404 }
4405 }
4406
4407 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
4408 while (badApps.hasNext()) {
4409 SparseArray<Long> ba = badApps.next();
4410 if (ba.get(uid) != null) {
4411 badApps.remove();
4412 }
4413 }
4414
4415 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
4416
4417 // Remove all processes this package may have touched: all with the
4418 // same UID (except for the system or root user), and all whose name
4419 // matches the package name.
4420 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
4421 final int NA = apps.size();
4422 for (int ia=0; ia<NA; ia++) {
4423 ProcessRecord app = apps.valueAt(ia);
4424 if (app.removed) {
4425 procs.add(app);
4426 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
4427 || app.processName.equals(name)
4428 || app.processName.startsWith(procNamePrefix)) {
4429 app.removed = true;
4430 procs.add(app);
4431 }
4432 }
4433 }
4434
4435 N = procs.size();
4436 for (i=0; i<N; i++) {
4437 removeProcessLocked(procs.get(i), callerWillRestart);
4438 }
4439
4440 for (i=mHistory.size()-1; i>=0; i--) {
4441 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4442 if (r.packageName.equals(name)) {
4443 if (Config.LOGD) Log.d(
4444 TAG, " Force finishing activity "
4445 + r.intent.getComponent().flattenToShortString());
4446 if (r.app != null) {
4447 r.app.removed = true;
4448 }
4449 r.app = null;
4450 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
4451 }
4452 }
4453
4454 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
4455 for (ServiceRecord service : mServices.values()) {
4456 if (service.packageName.equals(name)) {
4457 if (service.app != null) {
4458 service.app.removed = true;
4459 }
4460 service.app = null;
4461 services.add(service);
4462 }
4463 }
4464
4465 N = services.size();
4466 for (i=0; i<N; i++) {
4467 bringDownServiceLocked(services.get(i), true);
4468 }
4469
4470 resumeTopActivityLocked(null);
4471 }
4472
4473 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
4474 final String name = app.processName;
4475 final int uid = app.info.uid;
4476 if (Config.LOGD) Log.d(
4477 TAG, "Force removing process " + app + " (" + name
4478 + "/" + uid + ")");
4479
4480 mProcessNames.remove(name, uid);
4481 boolean needRestart = false;
4482 if (app.pid > 0 && app.pid != MY_PID) {
4483 int pid = app.pid;
4484 synchronized (mPidsSelfLocked) {
4485 mPidsSelfLocked.remove(pid);
4486 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
4487 }
4488 handleAppDiedLocked(app, true);
4489 mLRUProcesses.remove(app);
4490 Process.killProcess(pid);
4491
4492 if (app.persistent) {
4493 if (!callerWillRestart) {
4494 addAppLocked(app.info);
4495 } else {
4496 needRestart = true;
4497 }
4498 }
4499 } else {
4500 mRemovedProcesses.add(app);
4501 }
4502
4503 return needRestart;
4504 }
4505
4506 private final void processStartTimedOutLocked(ProcessRecord app) {
4507 final int pid = app.pid;
4508 boolean gone = false;
4509 synchronized (mPidsSelfLocked) {
4510 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
4511 if (knownApp != null && knownApp.thread == null) {
4512 mPidsSelfLocked.remove(pid);
4513 gone = true;
4514 }
4515 }
4516
4517 if (gone) {
4518 Log.w(TAG, "Process " + app + " failed to attach");
4519 mProcessNames.remove(app.processName, app.info.uid);
4520 Process.killProcess(pid);
4521 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
4522 Log.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
4523 mPendingBroadcast = null;
4524 scheduleBroadcastsLocked();
4525 }
4526 } else {
4527 Log.w(TAG, "Spurious process start timeout - pid not known for " + app);
4528 }
4529 }
4530
4531 private final boolean attachApplicationLocked(IApplicationThread thread,
4532 int pid) {
4533
4534 // Find the application record that is being attached... either via
4535 // the pid if we are running in multiple processes, or just pull the
4536 // next app record if we are emulating process with anonymous threads.
4537 ProcessRecord app;
4538 if (pid != MY_PID && pid >= 0) {
4539 synchronized (mPidsSelfLocked) {
4540 app = mPidsSelfLocked.get(pid);
4541 }
4542 } else if (mStartingProcesses.size() > 0) {
4543 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004544 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 } else {
4546 app = null;
4547 }
4548
4549 if (app == null) {
4550 Log.w(TAG, "No pending application record for pid " + pid
4551 + " (IApplicationThread " + thread + "); dropping process");
4552 EventLog.writeEvent(LOG_AM_DROP_PROCESS, pid);
4553 if (pid > 0 && pid != MY_PID) {
4554 Process.killProcess(pid);
4555 } else {
4556 try {
4557 thread.scheduleExit();
4558 } catch (Exception e) {
4559 // Ignore exceptions.
4560 }
4561 }
4562 return false;
4563 }
4564
4565 // If this application record is still attached to a previous
4566 // process, clean it up now.
4567 if (app.thread != null) {
4568 handleAppDiedLocked(app, true);
4569 }
4570
4571 // Tell the process all about itself.
4572
4573 if (localLOGV) Log.v(
4574 TAG, "Binding process pid " + pid + " to record " + app);
4575
4576 String processName = app.processName;
4577 try {
4578 thread.asBinder().linkToDeath(new AppDeathRecipient(
4579 app, pid, thread), 0);
4580 } catch (RemoteException e) {
4581 app.resetPackageList();
4582 startProcessLocked(app, "link fail", processName);
4583 return false;
4584 }
4585
4586 EventLog.writeEvent(LOG_AM_PROCESS_BOUND, app.pid, app.processName);
4587
4588 app.thread = thread;
4589 app.curAdj = app.setAdj = -100;
4590 app.forcingToForeground = null;
4591 app.foregroundServices = false;
4592 app.debugging = false;
4593
4594 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
4595
4596 List providers = generateApplicationProvidersLocked(app);
4597
4598 if (localLOGV) Log.v(
4599 TAG, "New app record " + app
4600 + " thread=" + thread.asBinder() + " pid=" + pid);
4601 try {
4602 int testMode = IApplicationThread.DEBUG_OFF;
4603 if (mDebugApp != null && mDebugApp.equals(processName)) {
4604 testMode = mWaitForDebugger
4605 ? IApplicationThread.DEBUG_WAIT
4606 : IApplicationThread.DEBUG_ON;
4607 app.debugging = true;
4608 if (mDebugTransient) {
4609 mDebugApp = mOrigDebugApp;
4610 mWaitForDebugger = mOrigWaitForDebugger;
4611 }
4612 }
Dianne Hackborn1655be42009-05-08 14:29:01 -07004613 thread.bindApplication(processName, app.instrumentationInfo != null
4614 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004615 app.instrumentationClass, app.instrumentationProfileFile,
4616 app.instrumentationArguments, app.instrumentationWatcher, testMode,
4617 mConfiguration, getCommonServicesLocked());
4618 updateLRUListLocked(app, false);
4619 app.lastRequestedGc = SystemClock.uptimeMillis();
4620 } catch (Exception e) {
4621 // todo: Yikes! What should we do? For now we will try to
4622 // start another process, but that could easily get us in
4623 // an infinite loop of restarting processes...
4624 Log.w(TAG, "Exception thrown during bind!", e);
4625
4626 app.resetPackageList();
4627 startProcessLocked(app, "bind fail", processName);
4628 return false;
4629 }
4630
4631 // Remove this record from the list of starting applications.
4632 mPersistentStartingProcesses.remove(app);
4633 mProcessesOnHold.remove(app);
4634
4635 boolean badApp = false;
4636 boolean didSomething = false;
4637
4638 // See if the top visible activity is waiting to run in this process...
4639 HistoryRecord hr = topRunningActivityLocked(null);
4640 if (hr != null) {
4641 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
4642 && processName.equals(hr.processName)) {
4643 try {
4644 if (realStartActivityLocked(hr, app, true, true)) {
4645 didSomething = true;
4646 }
4647 } catch (Exception e) {
4648 Log.w(TAG, "Exception in new application when starting activity "
4649 + hr.intent.getComponent().flattenToShortString(), e);
4650 badApp = true;
4651 }
4652 } else {
4653 ensureActivitiesVisibleLocked(hr, null, processName, 0);
4654 }
4655 }
4656
4657 // Find any services that should be running in this process...
4658 if (!badApp && mPendingServices.size() > 0) {
4659 ServiceRecord sr = null;
4660 try {
4661 for (int i=0; i<mPendingServices.size(); i++) {
4662 sr = mPendingServices.get(i);
4663 if (app.info.uid != sr.appInfo.uid
4664 || !processName.equals(sr.processName)) {
4665 continue;
4666 }
4667
4668 mPendingServices.remove(i);
4669 i--;
4670 realStartServiceLocked(sr, app);
4671 didSomething = true;
4672 }
4673 } catch (Exception e) {
4674 Log.w(TAG, "Exception in new application when starting service "
4675 + sr.shortName, e);
4676 badApp = true;
4677 }
4678 }
4679
4680 // Check if the next broadcast receiver is in this process...
4681 BroadcastRecord br = mPendingBroadcast;
4682 if (!badApp && br != null && br.curApp == app) {
4683 try {
4684 mPendingBroadcast = null;
4685 processCurBroadcastLocked(br, app);
4686 didSomething = true;
4687 } catch (Exception e) {
4688 Log.w(TAG, "Exception in new application when starting receiver "
4689 + br.curComponent.flattenToShortString(), e);
4690 badApp = true;
4691 logBroadcastReceiverDiscard(br);
4692 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
4693 br.resultExtras, br.resultAbort, true);
4694 scheduleBroadcastsLocked();
4695 }
4696 }
4697
4698 if (badApp) {
4699 // todo: Also need to kill application to deal with all
4700 // kinds of exceptions.
4701 handleAppDiedLocked(app, false);
4702 return false;
4703 }
4704
4705 if (!didSomething) {
4706 updateOomAdjLocked();
4707 }
4708
4709 return true;
4710 }
4711
4712 public final void attachApplication(IApplicationThread thread) {
4713 synchronized (this) {
4714 int callingPid = Binder.getCallingPid();
4715 final long origId = Binder.clearCallingIdentity();
4716 attachApplicationLocked(thread, callingPid);
4717 Binder.restoreCallingIdentity(origId);
4718 }
4719 }
4720
4721 public final void activityIdle(IBinder token) {
4722 final long origId = Binder.clearCallingIdentity();
4723 activityIdleInternal(token, false);
4724 Binder.restoreCallingIdentity(origId);
4725 }
4726
4727 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
4728 boolean remove) {
4729 int N = mStoppingActivities.size();
4730 if (N <= 0) return null;
4731
4732 ArrayList<HistoryRecord> stops = null;
4733
4734 final boolean nowVisible = mResumedActivity != null
4735 && mResumedActivity.nowVisible
4736 && !mResumedActivity.waitingVisible;
4737 for (int i=0; i<N; i++) {
4738 HistoryRecord s = mStoppingActivities.get(i);
4739 if (localLOGV) Log.v(TAG, "Stopping " + s + ": nowVisible="
4740 + nowVisible + " waitingVisible=" + s.waitingVisible
4741 + " finishing=" + s.finishing);
4742 if (s.waitingVisible && nowVisible) {
4743 mWaitingVisibleActivities.remove(s);
4744 s.waitingVisible = false;
4745 if (s.finishing) {
4746 // If this activity is finishing, it is sitting on top of
4747 // everyone else but we now know it is no longer needed...
4748 // so get rid of it. Otherwise, we need to go through the
4749 // normal flow and hide it once we determine that it is
4750 // hidden by the activities in front of it.
4751 if (localLOGV) Log.v(TAG, "Before stopping, can hide: " + s);
4752 mWindowManager.setAppVisibility(s, false);
4753 }
4754 }
4755 if (!s.waitingVisible && remove) {
4756 if (localLOGV) Log.v(TAG, "Ready to stop: " + s);
4757 if (stops == null) {
4758 stops = new ArrayList<HistoryRecord>();
4759 }
4760 stops.add(s);
4761 mStoppingActivities.remove(i);
4762 N--;
4763 i--;
4764 }
4765 }
4766
4767 return stops;
4768 }
4769
4770 void enableScreenAfterBoot() {
4771 mWindowManager.enableScreenAfterBoot();
4772 }
4773
4774 final void activityIdleInternal(IBinder token, boolean fromTimeout) {
4775 if (localLOGV) Log.v(TAG, "Activity idle: " + token);
4776
4777 ArrayList<HistoryRecord> stops = null;
4778 ArrayList<HistoryRecord> finishes = null;
4779 ArrayList<HistoryRecord> thumbnails = null;
4780 int NS = 0;
4781 int NF = 0;
4782 int NT = 0;
4783 IApplicationThread sendThumbnail = null;
4784 boolean booting = false;
4785 boolean enableScreen = false;
4786
4787 synchronized (this) {
4788 if (token != null) {
4789 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
4790 }
4791
4792 // Get the activity record.
4793 int index = indexOfTokenLocked(token, false);
4794 if (index >= 0) {
4795 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4796
4797 // No longer need to keep the device awake.
4798 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
4799 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
4800 mLaunchingActivity.release();
4801 }
4802
4803 // We are now idle. If someone is waiting for a thumbnail from
4804 // us, we can now deliver.
4805 r.idle = true;
4806 scheduleAppGcsLocked();
4807 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
4808 sendThumbnail = r.app.thread;
4809 r.thumbnailNeeded = false;
4810 }
4811
4812 // If this activity is fullscreen, set up to hide those under it.
4813
4814 if (DEBUG_VISBILITY) Log.v(TAG, "Idle activity for " + r);
4815 ensureActivitiesVisibleLocked(null, 0);
4816
4817 //Log.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
4818 if (!mBooted && !fromTimeout) {
4819 mBooted = true;
4820 enableScreen = true;
4821 }
4822 }
4823
4824 // Atomically retrieve all of the other things to do.
4825 stops = processStoppingActivitiesLocked(true);
4826 NS = stops != null ? stops.size() : 0;
4827 if ((NF=mFinishingActivities.size()) > 0) {
4828 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
4829 mFinishingActivities.clear();
4830 }
4831 if ((NT=mCancelledThumbnails.size()) > 0) {
4832 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
4833 mCancelledThumbnails.clear();
4834 }
4835
4836 booting = mBooting;
4837 mBooting = false;
4838 }
4839
4840 int i;
4841
4842 // Send thumbnail if requested.
4843 if (sendThumbnail != null) {
4844 try {
4845 sendThumbnail.requestThumbnail(token);
4846 } catch (Exception e) {
4847 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
4848 sendPendingThumbnail(null, token, null, null, true);
4849 }
4850 }
4851
4852 // Stop any activities that are scheduled to do so but have been
4853 // waiting for the next one to start.
4854 for (i=0; i<NS; i++) {
4855 HistoryRecord r = (HistoryRecord)stops.get(i);
4856 synchronized (this) {
4857 if (r.finishing) {
4858 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
4859 } else {
4860 stopActivityLocked(r);
4861 }
4862 }
4863 }
4864
4865 // Finish any activities that are scheduled to do so but have been
4866 // waiting for the next one to start.
4867 for (i=0; i<NF; i++) {
4868 HistoryRecord r = (HistoryRecord)finishes.get(i);
4869 synchronized (this) {
4870 destroyActivityLocked(r, true);
4871 }
4872 }
4873
4874 // Report back to any thumbnail receivers.
4875 for (i=0; i<NT; i++) {
4876 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
4877 sendPendingThumbnail(r, null, null, null, true);
4878 }
4879
4880 if (booting) {
4881 // Ensure that any processes we had put on hold are now started
4882 // up.
4883 final int NP = mProcessesOnHold.size();
4884 if (NP > 0) {
4885 ArrayList<ProcessRecord> procs =
4886 new ArrayList<ProcessRecord>(mProcessesOnHold);
4887 for (int ip=0; ip<NP; ip++) {
4888 this.startProcessLocked(procs.get(ip), "on-hold", null);
4889 }
4890 }
4891 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
4892 // Tell anyone interested that we are done booting!
4893 synchronized (this) {
4894 broadcastIntentLocked(null, null,
4895 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
4896 null, null, 0, null, null,
4897 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
4898 false, false, MY_PID, Process.SYSTEM_UID);
4899 }
4900 }
4901 }
4902
4903 trimApplications();
4904 //dump();
4905 //mWindowManager.dump();
4906
4907 if (enableScreen) {
4908 EventLog.writeEvent(LOG_BOOT_PROGRESS_ENABLE_SCREEN,
4909 SystemClock.uptimeMillis());
4910 enableScreenAfterBoot();
4911 }
4912 }
4913
4914 public final void activityPaused(IBinder token, Bundle icicle) {
4915 // Refuse possible leaked file descriptors
4916 if (icicle != null && icicle.hasFileDescriptors()) {
4917 throw new IllegalArgumentException("File descriptors passed in Bundle");
4918 }
4919
4920 final long origId = Binder.clearCallingIdentity();
4921 activityPaused(token, icicle, false);
4922 Binder.restoreCallingIdentity(origId);
4923 }
4924
4925 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
4926 if (DEBUG_PAUSE) Log.v(
4927 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
4928 + ", timeout=" + timeout);
4929
4930 HistoryRecord r = null;
4931
4932 synchronized (this) {
4933 int index = indexOfTokenLocked(token, false);
4934 if (index >= 0) {
4935 r = (HistoryRecord)mHistory.get(index);
4936 if (!timeout) {
4937 r.icicle = icicle;
4938 r.haveState = true;
4939 }
4940 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4941 if (mPausingActivity == r) {
4942 r.state = ActivityState.PAUSED;
4943 completePauseLocked();
4944 } else {
4945 EventLog.writeEvent(LOG_AM_FAILED_TO_PAUSE_ACTIVITY,
4946 System.identityHashCode(r), r.shortComponentName,
4947 mPausingActivity != null
4948 ? mPausingActivity.shortComponentName : "(none)");
4949 }
4950 }
4951 }
4952 }
4953
4954 public final void activityStopped(IBinder token, Bitmap thumbnail,
4955 CharSequence description) {
4956 if (localLOGV) Log.v(
4957 TAG, "Activity stopped: token=" + token);
4958
4959 HistoryRecord r = null;
4960
4961 final long origId = Binder.clearCallingIdentity();
4962
4963 synchronized (this) {
4964 int index = indexOfTokenLocked(token, false);
4965 if (index >= 0) {
4966 r = (HistoryRecord)mHistory.get(index);
4967 r.thumbnail = thumbnail;
4968 r.description = description;
4969 r.stopped = true;
4970 r.state = ActivityState.STOPPED;
4971 if (!r.finishing) {
4972 if (r.configDestroy) {
4973 destroyActivityLocked(r, true);
4974 resumeTopActivityLocked(null);
4975 }
4976 }
4977 }
4978 }
4979
4980 if (r != null) {
4981 sendPendingThumbnail(r, null, null, null, false);
4982 }
4983
4984 trimApplications();
4985
4986 Binder.restoreCallingIdentity(origId);
4987 }
4988
4989 public final void activityDestroyed(IBinder token) {
4990 if (DEBUG_SWITCH) Log.v(TAG, "ACTIVITY DESTROYED: " + token);
4991 synchronized (this) {
4992 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
4993
4994 int index = indexOfTokenLocked(token, false);
4995 if (index >= 0) {
4996 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4997 if (r.state == ActivityState.DESTROYING) {
4998 final long origId = Binder.clearCallingIdentity();
4999 removeActivityFromHistoryLocked(r);
5000 Binder.restoreCallingIdentity(origId);
5001 }
5002 }
5003 }
5004 }
5005
5006 public String getCallingPackage(IBinder token) {
5007 synchronized (this) {
5008 HistoryRecord r = getCallingRecordLocked(token);
5009 return r != null && r.app != null ? r.app.processName : null;
5010 }
5011 }
5012
5013 public ComponentName getCallingActivity(IBinder token) {
5014 synchronized (this) {
5015 HistoryRecord r = getCallingRecordLocked(token);
5016 return r != null ? r.intent.getComponent() : null;
5017 }
5018 }
5019
5020 private HistoryRecord getCallingRecordLocked(IBinder token) {
5021 int index = indexOfTokenLocked(token, true);
5022 if (index >= 0) {
5023 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5024 if (r != null) {
5025 return r.resultTo;
5026 }
5027 }
5028 return null;
5029 }
5030
5031 public ComponentName getActivityClassForToken(IBinder token) {
5032 synchronized(this) {
5033 int index = indexOfTokenLocked(token, false);
5034 if (index >= 0) {
5035 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5036 return r.intent.getComponent();
5037 }
5038 return null;
5039 }
5040 }
5041
5042 public String getPackageForToken(IBinder token) {
5043 synchronized(this) {
5044 int index = indexOfTokenLocked(token, false);
5045 if (index >= 0) {
5046 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5047 return r.packageName;
5048 }
5049 return null;
5050 }
5051 }
5052
5053 public IIntentSender getIntentSender(int type,
5054 String packageName, IBinder token, String resultWho,
5055 int requestCode, Intent intent, String resolvedType, int flags) {
5056 // Refuse possible leaked file descriptors
5057 if (intent != null && intent.hasFileDescriptors() == true) {
5058 throw new IllegalArgumentException("File descriptors passed in Intent");
5059 }
5060
5061 synchronized(this) {
5062 int callingUid = Binder.getCallingUid();
5063 try {
5064 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5065 Process.supportsProcesses()) {
5066 int uid = ActivityThread.getPackageManager()
5067 .getPackageUid(packageName);
5068 if (uid != Binder.getCallingUid()) {
5069 String msg = "Permission Denial: getIntentSender() from pid="
5070 + Binder.getCallingPid()
5071 + ", uid=" + Binder.getCallingUid()
5072 + ", (need uid=" + uid + ")"
5073 + " is not allowed to send as package " + packageName;
5074 Log.w(TAG, msg);
5075 throw new SecurityException(msg);
5076 }
5077 }
5078 } catch (RemoteException e) {
5079 throw new SecurityException(e);
5080 }
5081 HistoryRecord activity = null;
5082 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
5083 int index = indexOfTokenLocked(token, false);
5084 if (index < 0) {
5085 return null;
5086 }
5087 activity = (HistoryRecord)mHistory.get(index);
5088 if (activity.finishing) {
5089 return null;
5090 }
5091 }
5092
5093 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5094 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5095 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5096 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5097 |PendingIntent.FLAG_UPDATE_CURRENT);
5098
5099 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5100 type, packageName, activity, resultWho,
5101 requestCode, intent, resolvedType, flags);
5102 WeakReference<PendingIntentRecord> ref;
5103 ref = mIntentSenderRecords.get(key);
5104 PendingIntentRecord rec = ref != null ? ref.get() : null;
5105 if (rec != null) {
5106 if (!cancelCurrent) {
5107 if (updateCurrent) {
5108 rec.key.requestIntent.replaceExtras(intent);
5109 }
5110 return rec;
5111 }
5112 rec.canceled = true;
5113 mIntentSenderRecords.remove(key);
5114 }
5115 if (noCreate) {
5116 return rec;
5117 }
5118 rec = new PendingIntentRecord(this, key, callingUid);
5119 mIntentSenderRecords.put(key, rec.ref);
5120 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
5121 if (activity.pendingResults == null) {
5122 activity.pendingResults
5123 = new HashSet<WeakReference<PendingIntentRecord>>();
5124 }
5125 activity.pendingResults.add(rec.ref);
5126 }
5127 return rec;
5128 }
5129 }
5130
5131 public void cancelIntentSender(IIntentSender sender) {
5132 if (!(sender instanceof PendingIntentRecord)) {
5133 return;
5134 }
5135 synchronized(this) {
5136 PendingIntentRecord rec = (PendingIntentRecord)sender;
5137 try {
5138 int uid = ActivityThread.getPackageManager()
5139 .getPackageUid(rec.key.packageName);
5140 if (uid != Binder.getCallingUid()) {
5141 String msg = "Permission Denial: cancelIntentSender() from pid="
5142 + Binder.getCallingPid()
5143 + ", uid=" + Binder.getCallingUid()
5144 + " is not allowed to cancel packges "
5145 + rec.key.packageName;
5146 Log.w(TAG, msg);
5147 throw new SecurityException(msg);
5148 }
5149 } catch (RemoteException e) {
5150 throw new SecurityException(e);
5151 }
5152 cancelIntentSenderLocked(rec, true);
5153 }
5154 }
5155
5156 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
5157 rec.canceled = true;
5158 mIntentSenderRecords.remove(rec.key);
5159 if (cleanActivity && rec.key.activity != null) {
5160 rec.key.activity.pendingResults.remove(rec.ref);
5161 }
5162 }
5163
5164 public String getPackageForIntentSender(IIntentSender pendingResult) {
5165 if (!(pendingResult instanceof PendingIntentRecord)) {
5166 return null;
5167 }
5168 synchronized(this) {
5169 try {
5170 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
5171 return res.key.packageName;
5172 } catch (ClassCastException e) {
5173 }
5174 }
5175 return null;
5176 }
5177
5178 public void setProcessLimit(int max) {
5179 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5180 "setProcessLimit()");
5181 mProcessLimit = max;
5182 }
5183
5184 public int getProcessLimit() {
5185 return mProcessLimit;
5186 }
5187
5188 void foregroundTokenDied(ForegroundToken token) {
5189 synchronized (ActivityManagerService.this) {
5190 synchronized (mPidsSelfLocked) {
5191 ForegroundToken cur
5192 = mForegroundProcesses.get(token.pid);
5193 if (cur != token) {
5194 return;
5195 }
5196 mForegroundProcesses.remove(token.pid);
5197 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
5198 if (pr == null) {
5199 return;
5200 }
5201 pr.forcingToForeground = null;
5202 pr.foregroundServices = false;
5203 }
5204 updateOomAdjLocked();
5205 }
5206 }
5207
5208 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
5209 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5210 "setProcessForeground()");
5211 synchronized(this) {
5212 boolean changed = false;
5213
5214 synchronized (mPidsSelfLocked) {
5215 ProcessRecord pr = mPidsSelfLocked.get(pid);
5216 if (pr == null) {
5217 Log.w(TAG, "setProcessForeground called on unknown pid: " + pid);
5218 return;
5219 }
5220 ForegroundToken oldToken = mForegroundProcesses.get(pid);
5221 if (oldToken != null) {
5222 oldToken.token.unlinkToDeath(oldToken, 0);
5223 mForegroundProcesses.remove(pid);
5224 pr.forcingToForeground = null;
5225 changed = true;
5226 }
5227 if (isForeground && token != null) {
5228 ForegroundToken newToken = new ForegroundToken() {
5229 public void binderDied() {
5230 foregroundTokenDied(this);
5231 }
5232 };
5233 newToken.pid = pid;
5234 newToken.token = token;
5235 try {
5236 token.linkToDeath(newToken, 0);
5237 mForegroundProcesses.put(pid, newToken);
5238 pr.forcingToForeground = token;
5239 changed = true;
5240 } catch (RemoteException e) {
5241 // If the process died while doing this, we will later
5242 // do the cleanup with the process death link.
5243 }
5244 }
5245 }
5246
5247 if (changed) {
5248 updateOomAdjLocked();
5249 }
5250 }
5251 }
5252
5253 // =========================================================
5254 // PERMISSIONS
5255 // =========================================================
5256
5257 static class PermissionController extends IPermissionController.Stub {
5258 ActivityManagerService mActivityManagerService;
5259 PermissionController(ActivityManagerService activityManagerService) {
5260 mActivityManagerService = activityManagerService;
5261 }
5262
5263 public boolean checkPermission(String permission, int pid, int uid) {
5264 return mActivityManagerService.checkPermission(permission, pid,
5265 uid) == PackageManager.PERMISSION_GRANTED;
5266 }
5267 }
5268
5269 /**
5270 * This can be called with or without the global lock held.
5271 */
5272 int checkComponentPermission(String permission, int pid, int uid,
5273 int reqUid) {
5274 // We might be performing an operation on behalf of an indirect binder
5275 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
5276 // client identity accordingly before proceeding.
5277 Identity tlsIdentity = sCallerIdentity.get();
5278 if (tlsIdentity != null) {
5279 Log.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
5280 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
5281 uid = tlsIdentity.uid;
5282 pid = tlsIdentity.pid;
5283 }
5284
5285 // Root, system server and our own process get to do everything.
5286 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
5287 !Process.supportsProcesses()) {
5288 return PackageManager.PERMISSION_GRANTED;
5289 }
5290 // If the target requires a specific UID, always fail for others.
5291 if (reqUid >= 0 && uid != reqUid) {
5292 return PackageManager.PERMISSION_DENIED;
5293 }
5294 if (permission == null) {
5295 return PackageManager.PERMISSION_GRANTED;
5296 }
5297 try {
5298 return ActivityThread.getPackageManager()
5299 .checkUidPermission(permission, uid);
5300 } catch (RemoteException e) {
5301 // Should never happen, but if it does... deny!
5302 Log.e(TAG, "PackageManager is dead?!?", e);
5303 }
5304 return PackageManager.PERMISSION_DENIED;
5305 }
5306
5307 /**
5308 * As the only public entry point for permissions checking, this method
5309 * can enforce the semantic that requesting a check on a null global
5310 * permission is automatically denied. (Internally a null permission
5311 * string is used when calling {@link #checkComponentPermission} in cases
5312 * when only uid-based security is needed.)
5313 *
5314 * This can be called with or without the global lock held.
5315 */
5316 public int checkPermission(String permission, int pid, int uid) {
5317 if (permission == null) {
5318 return PackageManager.PERMISSION_DENIED;
5319 }
5320 return checkComponentPermission(permission, pid, uid, -1);
5321 }
5322
5323 /**
5324 * Binder IPC calls go through the public entry point.
5325 * This can be called with or without the global lock held.
5326 */
5327 int checkCallingPermission(String permission) {
5328 return checkPermission(permission,
5329 Binder.getCallingPid(),
5330 Binder.getCallingUid());
5331 }
5332
5333 /**
5334 * This can be called with or without the global lock held.
5335 */
5336 void enforceCallingPermission(String permission, String func) {
5337 if (checkCallingPermission(permission)
5338 == PackageManager.PERMISSION_GRANTED) {
5339 return;
5340 }
5341
5342 String msg = "Permission Denial: " + func + " from pid="
5343 + Binder.getCallingPid()
5344 + ", uid=" + Binder.getCallingUid()
5345 + " requires " + permission;
5346 Log.w(TAG, msg);
5347 throw new SecurityException(msg);
5348 }
5349
5350 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
5351 ProviderInfo pi, int uid, int modeFlags) {
5352 try {
5353 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
5354 if ((pi.readPermission != null) &&
5355 (pm.checkUidPermission(pi.readPermission, uid)
5356 != PackageManager.PERMISSION_GRANTED)) {
5357 return false;
5358 }
5359 }
5360 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
5361 if ((pi.writePermission != null) &&
5362 (pm.checkUidPermission(pi.writePermission, uid)
5363 != PackageManager.PERMISSION_GRANTED)) {
5364 return false;
5365 }
5366 }
5367 return true;
5368 } catch (RemoteException e) {
5369 return false;
5370 }
5371 }
5372
5373 private final boolean checkUriPermissionLocked(Uri uri, int uid,
5374 int modeFlags) {
5375 // Root gets to do everything.
5376 if (uid == 0 || !Process.supportsProcesses()) {
5377 return true;
5378 }
5379 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
5380 if (perms == null) return false;
5381 UriPermission perm = perms.get(uri);
5382 if (perm == null) return false;
5383 return (modeFlags&perm.modeFlags) == modeFlags;
5384 }
5385
5386 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
5387 // Another redirected-binder-call permissions check as in
5388 // {@link checkComponentPermission}.
5389 Identity tlsIdentity = sCallerIdentity.get();
5390 if (tlsIdentity != null) {
5391 uid = tlsIdentity.uid;
5392 pid = tlsIdentity.pid;
5393 }
5394
5395 // Our own process gets to do everything.
5396 if (pid == MY_PID) {
5397 return PackageManager.PERMISSION_GRANTED;
5398 }
5399 synchronized(this) {
5400 return checkUriPermissionLocked(uri, uid, modeFlags)
5401 ? PackageManager.PERMISSION_GRANTED
5402 : PackageManager.PERMISSION_DENIED;
5403 }
5404 }
5405
5406 private void grantUriPermissionLocked(int callingUid,
5407 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
5408 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5409 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5410 if (modeFlags == 0) {
5411 return;
5412 }
5413
5414 final IPackageManager pm = ActivityThread.getPackageManager();
5415
5416 // If this is not a content: uri, we can't do anything with it.
5417 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
5418 return;
5419 }
5420
5421 String name = uri.getAuthority();
5422 ProviderInfo pi = null;
5423 ContentProviderRecord cpr
5424 = (ContentProviderRecord)mProvidersByName.get(name);
5425 if (cpr != null) {
5426 pi = cpr.info;
5427 } else {
5428 try {
5429 pi = pm.resolveContentProvider(name,
5430 PackageManager.GET_URI_PERMISSION_PATTERNS);
5431 } catch (RemoteException ex) {
5432 }
5433 }
5434 if (pi == null) {
5435 Log.w(TAG, "No content provider found for: " + name);
5436 return;
5437 }
5438
5439 int targetUid;
5440 try {
5441 targetUid = pm.getPackageUid(targetPkg);
5442 if (targetUid < 0) {
5443 return;
5444 }
5445 } catch (RemoteException ex) {
5446 return;
5447 }
5448
5449 // First... does the target actually need this permission?
5450 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
5451 // No need to grant the target this permission.
5452 return;
5453 }
5454
5455 // Second... maybe someone else has already granted the
5456 // permission?
5457 if (checkUriPermissionLocked(uri, targetUid, modeFlags)) {
5458 // No need to grant the target this permission.
5459 return;
5460 }
5461
5462 // Third... is the provider allowing granting of URI permissions?
5463 if (!pi.grantUriPermissions) {
5464 throw new SecurityException("Provider " + pi.packageName
5465 + "/" + pi.name
5466 + " does not allow granting of Uri permissions (uri "
5467 + uri + ")");
5468 }
5469 if (pi.uriPermissionPatterns != null) {
5470 final int N = pi.uriPermissionPatterns.length;
5471 boolean allowed = false;
5472 for (int i=0; i<N; i++) {
5473 if (pi.uriPermissionPatterns[i] != null
5474 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
5475 allowed = true;
5476 break;
5477 }
5478 }
5479 if (!allowed) {
5480 throw new SecurityException("Provider " + pi.packageName
5481 + "/" + pi.name
5482 + " does not allow granting of permission to path of Uri "
5483 + uri);
5484 }
5485 }
5486
5487 // Fourth... does the caller itself have permission to access
5488 // this uri?
5489 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
5490 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
5491 throw new SecurityException("Uid " + callingUid
5492 + " does not have permission to uri " + uri);
5493 }
5494 }
5495
5496 // Okay! So here we are: the caller has the assumed permission
5497 // to the uri, and the target doesn't. Let's now give this to
5498 // the target.
5499
5500 HashMap<Uri, UriPermission> targetUris
5501 = mGrantedUriPermissions.get(targetUid);
5502 if (targetUris == null) {
5503 targetUris = new HashMap<Uri, UriPermission>();
5504 mGrantedUriPermissions.put(targetUid, targetUris);
5505 }
5506
5507 UriPermission perm = targetUris.get(uri);
5508 if (perm == null) {
5509 perm = new UriPermission(targetUid, uri);
5510 targetUris.put(uri, perm);
5511
5512 }
5513 perm.modeFlags |= modeFlags;
5514 if (activity == null) {
5515 perm.globalModeFlags |= modeFlags;
5516 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
5517 perm.readActivities.add(activity);
5518 if (activity.readUriPermissions == null) {
5519 activity.readUriPermissions = new HashSet<UriPermission>();
5520 }
5521 activity.readUriPermissions.add(perm);
5522 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
5523 perm.writeActivities.add(activity);
5524 if (activity.writeUriPermissions == null) {
5525 activity.writeUriPermissions = new HashSet<UriPermission>();
5526 }
5527 activity.writeUriPermissions.add(perm);
5528 }
5529 }
5530
5531 private void grantUriPermissionFromIntentLocked(int callingUid,
5532 String targetPkg, Intent intent, HistoryRecord activity) {
5533 if (intent == null) {
5534 return;
5535 }
5536 Uri data = intent.getData();
5537 if (data == null) {
5538 return;
5539 }
5540 grantUriPermissionLocked(callingUid, targetPkg, data,
5541 intent.getFlags(), activity);
5542 }
5543
5544 public void grantUriPermission(IApplicationThread caller, String targetPkg,
5545 Uri uri, int modeFlags) {
5546 synchronized(this) {
5547 final ProcessRecord r = getRecordForAppLocked(caller);
5548 if (r == null) {
5549 throw new SecurityException("Unable to find app for caller "
5550 + caller
5551 + " when granting permission to uri " + uri);
5552 }
5553 if (targetPkg == null) {
5554 Log.w(TAG, "grantUriPermission: null target");
5555 return;
5556 }
5557 if (uri == null) {
5558 Log.w(TAG, "grantUriPermission: null uri");
5559 return;
5560 }
5561
5562 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
5563 null);
5564 }
5565 }
5566
5567 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
5568 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
5569 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
5570 HashMap<Uri, UriPermission> perms
5571 = mGrantedUriPermissions.get(perm.uid);
5572 if (perms != null) {
5573 perms.remove(perm.uri);
5574 if (perms.size() == 0) {
5575 mGrantedUriPermissions.remove(perm.uid);
5576 }
5577 }
5578 }
5579 }
5580
5581 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
5582 if (activity.readUriPermissions != null) {
5583 for (UriPermission perm : activity.readUriPermissions) {
5584 perm.readActivities.remove(activity);
5585 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
5586 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
5587 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
5588 removeUriPermissionIfNeededLocked(perm);
5589 }
5590 }
5591 }
5592 if (activity.writeUriPermissions != null) {
5593 for (UriPermission perm : activity.writeUriPermissions) {
5594 perm.writeActivities.remove(activity);
5595 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
5596 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
5597 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
5598 removeUriPermissionIfNeededLocked(perm);
5599 }
5600 }
5601 }
5602 }
5603
5604 private void revokeUriPermissionLocked(int callingUid, Uri uri,
5605 int modeFlags) {
5606 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5607 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5608 if (modeFlags == 0) {
5609 return;
5610 }
5611
5612 final IPackageManager pm = ActivityThread.getPackageManager();
5613
5614 final String authority = uri.getAuthority();
5615 ProviderInfo pi = null;
5616 ContentProviderRecord cpr
5617 = (ContentProviderRecord)mProvidersByName.get(authority);
5618 if (cpr != null) {
5619 pi = cpr.info;
5620 } else {
5621 try {
5622 pi = pm.resolveContentProvider(authority,
5623 PackageManager.GET_URI_PERMISSION_PATTERNS);
5624 } catch (RemoteException ex) {
5625 }
5626 }
5627 if (pi == null) {
5628 Log.w(TAG, "No content provider found for: " + authority);
5629 return;
5630 }
5631
5632 // Does the caller have this permission on the URI?
5633 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
5634 // Right now, if you are not the original owner of the permission,
5635 // you are not allowed to revoke it.
5636 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
5637 throw new SecurityException("Uid " + callingUid
5638 + " does not have permission to uri " + uri);
5639 //}
5640 }
5641
5642 // Go through all of the permissions and remove any that match.
5643 final List<String> SEGMENTS = uri.getPathSegments();
5644 if (SEGMENTS != null) {
5645 final int NS = SEGMENTS.size();
5646 int N = mGrantedUriPermissions.size();
5647 for (int i=0; i<N; i++) {
5648 HashMap<Uri, UriPermission> perms
5649 = mGrantedUriPermissions.valueAt(i);
5650 Iterator<UriPermission> it = perms.values().iterator();
5651 toploop:
5652 while (it.hasNext()) {
5653 UriPermission perm = it.next();
5654 Uri targetUri = perm.uri;
5655 if (!authority.equals(targetUri.getAuthority())) {
5656 continue;
5657 }
5658 List<String> targetSegments = targetUri.getPathSegments();
5659 if (targetSegments == null) {
5660 continue;
5661 }
5662 if (targetSegments.size() < NS) {
5663 continue;
5664 }
5665 for (int j=0; j<NS; j++) {
5666 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
5667 continue toploop;
5668 }
5669 }
5670 perm.clearModes(modeFlags);
5671 if (perm.modeFlags == 0) {
5672 it.remove();
5673 }
5674 }
5675 if (perms.size() == 0) {
5676 mGrantedUriPermissions.remove(
5677 mGrantedUriPermissions.keyAt(i));
5678 N--;
5679 i--;
5680 }
5681 }
5682 }
5683 }
5684
5685 public void revokeUriPermission(IApplicationThread caller, Uri uri,
5686 int modeFlags) {
5687 synchronized(this) {
5688 final ProcessRecord r = getRecordForAppLocked(caller);
5689 if (r == null) {
5690 throw new SecurityException("Unable to find app for caller "
5691 + caller
5692 + " when revoking permission to uri " + uri);
5693 }
5694 if (uri == null) {
5695 Log.w(TAG, "revokeUriPermission: null uri");
5696 return;
5697 }
5698
5699 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5700 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5701 if (modeFlags == 0) {
5702 return;
5703 }
5704
5705 final IPackageManager pm = ActivityThread.getPackageManager();
5706
5707 final String authority = uri.getAuthority();
5708 ProviderInfo pi = null;
5709 ContentProviderRecord cpr
5710 = (ContentProviderRecord)mProvidersByName.get(authority);
5711 if (cpr != null) {
5712 pi = cpr.info;
5713 } else {
5714 try {
5715 pi = pm.resolveContentProvider(authority,
5716 PackageManager.GET_URI_PERMISSION_PATTERNS);
5717 } catch (RemoteException ex) {
5718 }
5719 }
5720 if (pi == null) {
5721 Log.w(TAG, "No content provider found for: " + authority);
5722 return;
5723 }
5724
5725 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
5726 }
5727 }
5728
5729 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
5730 synchronized (this) {
5731 ProcessRecord app =
5732 who != null ? getRecordForAppLocked(who) : null;
5733 if (app == null) return;
5734
5735 Message msg = Message.obtain();
5736 msg.what = WAIT_FOR_DEBUGGER_MSG;
5737 msg.obj = app;
5738 msg.arg1 = waiting ? 1 : 0;
5739 mHandler.sendMessage(msg);
5740 }
5741 }
5742
5743 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
5744 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08005745 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005746 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08005747 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005748 }
5749
5750 // =========================================================
5751 // TASK MANAGEMENT
5752 // =========================================================
5753
5754 public List getTasks(int maxNum, int flags,
5755 IThumbnailReceiver receiver) {
5756 ArrayList list = new ArrayList();
5757
5758 PendingThumbnailsRecord pending = null;
5759 IApplicationThread topThumbnail = null;
5760 HistoryRecord topRecord = null;
5761
5762 synchronized(this) {
5763 if (localLOGV) Log.v(
5764 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
5765 + ", receiver=" + receiver);
5766
5767 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
5768 != PackageManager.PERMISSION_GRANTED) {
5769 if (receiver != null) {
5770 // If the caller wants to wait for pending thumbnails,
5771 // it ain't gonna get them.
5772 try {
5773 receiver.finished();
5774 } catch (RemoteException ex) {
5775 }
5776 }
5777 String msg = "Permission Denial: getTasks() from pid="
5778 + Binder.getCallingPid()
5779 + ", uid=" + Binder.getCallingUid()
5780 + " requires " + android.Manifest.permission.GET_TASKS;
5781 Log.w(TAG, msg);
5782 throw new SecurityException(msg);
5783 }
5784
5785 int pos = mHistory.size()-1;
5786 HistoryRecord next =
5787 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
5788 HistoryRecord top = null;
5789 CharSequence topDescription = null;
5790 TaskRecord curTask = null;
5791 int numActivities = 0;
5792 int numRunning = 0;
5793 while (pos >= 0 && maxNum > 0) {
5794 final HistoryRecord r = next;
5795 pos--;
5796 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
5797
5798 // Initialize state for next task if needed.
5799 if (top == null ||
5800 (top.state == ActivityState.INITIALIZING
5801 && top.task == r.task)) {
5802 top = r;
5803 topDescription = r.description;
5804 curTask = r.task;
5805 numActivities = numRunning = 0;
5806 }
5807
5808 // Add 'r' into the current task.
5809 numActivities++;
5810 if (r.app != null && r.app.thread != null) {
5811 numRunning++;
5812 }
5813 if (topDescription == null) {
5814 topDescription = r.description;
5815 }
5816
5817 if (localLOGV) Log.v(
5818 TAG, r.intent.getComponent().flattenToShortString()
5819 + ": task=" + r.task);
5820
5821 // If the next one is a different task, generate a new
5822 // TaskInfo entry for what we have.
5823 if (next == null || next.task != curTask) {
5824 ActivityManager.RunningTaskInfo ci
5825 = new ActivityManager.RunningTaskInfo();
5826 ci.id = curTask.taskId;
5827 ci.baseActivity = r.intent.getComponent();
5828 ci.topActivity = top.intent.getComponent();
5829 ci.thumbnail = top.thumbnail;
5830 ci.description = topDescription;
5831 ci.numActivities = numActivities;
5832 ci.numRunning = numRunning;
5833 //System.out.println(
5834 // "#" + maxNum + ": " + " descr=" + ci.description);
5835 if (ci.thumbnail == null && receiver != null) {
5836 if (localLOGV) Log.v(
5837 TAG, "State=" + top.state + "Idle=" + top.idle
5838 + " app=" + top.app
5839 + " thr=" + (top.app != null ? top.app.thread : null));
5840 if (top.state == ActivityState.RESUMED
5841 || top.state == ActivityState.PAUSING) {
5842 if (top.idle && top.app != null
5843 && top.app.thread != null) {
5844 topRecord = top;
5845 topThumbnail = top.app.thread;
5846 } else {
5847 top.thumbnailNeeded = true;
5848 }
5849 }
5850 if (pending == null) {
5851 pending = new PendingThumbnailsRecord(receiver);
5852 }
5853 pending.pendingRecords.add(top);
5854 }
5855 list.add(ci);
5856 maxNum--;
5857 top = null;
5858 }
5859 }
5860
5861 if (pending != null) {
5862 mPendingThumbnails.add(pending);
5863 }
5864 }
5865
5866 if (localLOGV) Log.v(TAG, "We have pending thumbnails: " + pending);
5867
5868 if (topThumbnail != null) {
5869 if (localLOGV) Log.v(TAG, "Requesting top thumbnail");
5870 try {
5871 topThumbnail.requestThumbnail(topRecord);
5872 } catch (Exception e) {
5873 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
5874 sendPendingThumbnail(null, topRecord, null, null, true);
5875 }
5876 }
5877
5878 if (pending == null && receiver != null) {
5879 // In this case all thumbnails were available and the client
5880 // is being asked to be told when the remaining ones come in...
5881 // which is unusually, since the top-most currently running
5882 // activity should never have a canned thumbnail! Oh well.
5883 try {
5884 receiver.finished();
5885 } catch (RemoteException ex) {
5886 }
5887 }
5888
5889 return list;
5890 }
5891
5892 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5893 int flags) {
5894 synchronized (this) {
5895 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5896 "getRecentTasks()");
5897
5898 final int N = mRecentTasks.size();
5899 ArrayList<ActivityManager.RecentTaskInfo> res
5900 = new ArrayList<ActivityManager.RecentTaskInfo>(
5901 maxNum < N ? maxNum : N);
5902 for (int i=0; i<N && maxNum > 0; i++) {
5903 TaskRecord tr = mRecentTasks.get(i);
5904 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
5905 || (tr.intent == null)
5906 || ((tr.intent.getFlags()
5907 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5908 ActivityManager.RecentTaskInfo rti
5909 = new ActivityManager.RecentTaskInfo();
5910 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
5911 rti.baseIntent = new Intent(
5912 tr.intent != null ? tr.intent : tr.affinityIntent);
5913 rti.origActivity = tr.origActivity;
5914 res.add(rti);
5915 maxNum--;
5916 }
5917 }
5918 return res;
5919 }
5920 }
5921
5922 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5923 int j;
5924 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
5925 TaskRecord jt = startTask;
5926
5927 // First look backwards
5928 for (j=startIndex-1; j>=0; j--) {
5929 HistoryRecord r = (HistoryRecord)mHistory.get(j);
5930 if (r.task != jt) {
5931 jt = r.task;
5932 if (affinity.equals(jt.affinity)) {
5933 return j;
5934 }
5935 }
5936 }
5937
5938 // Now look forwards
5939 final int N = mHistory.size();
5940 jt = startTask;
5941 for (j=startIndex+1; j<N; j++) {
5942 HistoryRecord r = (HistoryRecord)mHistory.get(j);
5943 if (r.task != jt) {
5944 if (affinity.equals(jt.affinity)) {
5945 return j;
5946 }
5947 jt = r.task;
5948 }
5949 }
5950
5951 // Might it be at the top?
5952 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
5953 return N-1;
5954 }
5955
5956 return -1;
5957 }
5958
5959 /**
5960 * Perform a reset of the given task, if needed as part of launching it.
5961 * Returns the new HistoryRecord at the top of the task.
5962 */
5963 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
5964 HistoryRecord newActivity) {
5965 boolean forceReset = (newActivity.info.flags
5966 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
5967 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
5968 if ((newActivity.info.flags
5969 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
5970 forceReset = true;
5971 }
5972 }
5973
5974 final TaskRecord task = taskTop.task;
5975
5976 // We are going to move through the history list so that we can look
5977 // at each activity 'target' with 'below' either the interesting
5978 // activity immediately below it in the stack or null.
5979 HistoryRecord target = null;
5980 int targetI = 0;
5981 int taskTopI = -1;
5982 int replyChainEnd = -1;
5983 int lastReparentPos = -1;
5984 for (int i=mHistory.size()-1; i>=-1; i--) {
5985 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
5986
5987 if (below != null && below.finishing) {
5988 continue;
5989 }
5990 if (target == null) {
5991 target = below;
5992 targetI = i;
5993 // If we were in the middle of a reply chain before this
5994 // task, it doesn't appear like the root of the chain wants
5995 // anything interesting, so drop it.
5996 replyChainEnd = -1;
5997 continue;
5998 }
5999
6000 final int flags = target.info.flags;
6001
6002 final boolean finishOnTaskLaunch =
6003 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6004 final boolean allowTaskReparenting =
6005 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6006
6007 if (target.task == task) {
6008 // We are inside of the task being reset... we'll either
6009 // finish this activity, push it out for another task,
6010 // or leave it as-is. We only do this
6011 // for activities that are not the root of the task (since
6012 // if we finish the root, we may no longer have the task!).
6013 if (taskTopI < 0) {
6014 taskTopI = targetI;
6015 }
6016 if (below != null && below.task == task) {
6017 final boolean clearWhenTaskReset =
6018 (target.intent.getFlags()
6019 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006020 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006021 // If this activity is sending a reply to a previous
6022 // activity, we can't do anything with it now until
6023 // we reach the start of the reply chain.
6024 // XXX note that we are assuming the result is always
6025 // to the previous activity, which is almost always
6026 // the case but we really shouldn't count on.
6027 if (replyChainEnd < 0) {
6028 replyChainEnd = targetI;
6029 }
Ed Heyl73798232009-03-24 21:32:21 -07006030 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006031 && target.taskAffinity != null
6032 && !target.taskAffinity.equals(task.affinity)) {
6033 // If this activity has an affinity for another
6034 // task, then we need to move it out of here. We will
6035 // move it as far out of the way as possible, to the
6036 // bottom of the activity stack. This also keeps it
6037 // correctly ordered with any activities we previously
6038 // moved.
6039 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6040 if (target.taskAffinity != null
6041 && target.taskAffinity.equals(p.task.affinity)) {
6042 // If the activity currently at the bottom has the
6043 // same task affinity as the one we are moving,
6044 // then merge it into the same task.
6045 target.task = p.task;
6046 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6047 + " out to bottom task " + p.task);
6048 } else {
6049 mCurTask++;
6050 if (mCurTask <= 0) {
6051 mCurTask = 1;
6052 }
6053 target.task = new TaskRecord(mCurTask, target.info, null,
6054 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6055 target.task.affinityIntent = target.intent;
6056 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6057 + " out to new task " + target.task);
6058 }
6059 mWindowManager.setAppGroupId(target, task.taskId);
6060 if (replyChainEnd < 0) {
6061 replyChainEnd = targetI;
6062 }
6063 int dstPos = 0;
6064 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6065 p = (HistoryRecord)mHistory.get(srcPos);
6066 if (p.finishing) {
6067 continue;
6068 }
6069 if (DEBUG_TASKS) Log.v(TAG, "Pushing next activity " + p
6070 + " out to target's task " + target.task);
6071 task.numActivities--;
6072 p.task = target.task;
6073 target.task.numActivities++;
6074 mHistory.remove(srcPos);
6075 mHistory.add(dstPos, p);
6076 mWindowManager.moveAppToken(dstPos, p);
6077 mWindowManager.setAppGroupId(p, p.task.taskId);
6078 dstPos++;
6079 if (VALIDATE_TOKENS) {
6080 mWindowManager.validateAppTokens(mHistory);
6081 }
6082 i++;
6083 }
6084 if (taskTop == p) {
6085 taskTop = below;
6086 }
6087 if (taskTopI == replyChainEnd) {
6088 taskTopI = -1;
6089 }
6090 replyChainEnd = -1;
6091 addRecentTask(target.task);
6092 } else if (forceReset || finishOnTaskLaunch
6093 || clearWhenTaskReset) {
6094 // If the activity should just be removed -- either
6095 // because it asks for it, or the task should be
6096 // cleared -- then finish it and anything that is
6097 // part of its reply chain.
6098 if (clearWhenTaskReset) {
6099 // In this case, we want to finish this activity
6100 // and everything above it, so be sneaky and pretend
6101 // like these are all in the reply chain.
6102 replyChainEnd = targetI+1;
6103 while (replyChainEnd < mHistory.size() &&
6104 ((HistoryRecord)mHistory.get(
6105 replyChainEnd)).task == task) {
6106 replyChainEnd++;
6107 }
6108 replyChainEnd--;
6109 } else if (replyChainEnd < 0) {
6110 replyChainEnd = targetI;
6111 }
6112 HistoryRecord p = null;
6113 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6114 p = (HistoryRecord)mHistory.get(srcPos);
6115 if (p.finishing) {
6116 continue;
6117 }
6118 if (finishActivityLocked(p, srcPos,
6119 Activity.RESULT_CANCELED, null, "reset")) {
6120 replyChainEnd--;
6121 srcPos--;
6122 }
6123 }
6124 if (taskTop == p) {
6125 taskTop = below;
6126 }
6127 if (taskTopI == replyChainEnd) {
6128 taskTopI = -1;
6129 }
6130 replyChainEnd = -1;
6131 } else {
6132 // If we were in the middle of a chain, well the
6133 // activity that started it all doesn't want anything
6134 // special, so leave it all as-is.
6135 replyChainEnd = -1;
6136 }
6137 } else {
6138 // Reached the bottom of the task -- any reply chain
6139 // should be left as-is.
6140 replyChainEnd = -1;
6141 }
6142
6143 } else if (target.resultTo != null) {
6144 // If this activity is sending a reply to a previous
6145 // activity, we can't do anything with it now until
6146 // we reach the start of the reply chain.
6147 // XXX note that we are assuming the result is always
6148 // to the previous activity, which is almost always
6149 // the case but we really shouldn't count on.
6150 if (replyChainEnd < 0) {
6151 replyChainEnd = targetI;
6152 }
6153
6154 } else if (taskTopI >= 0 && allowTaskReparenting
6155 && task.affinity != null
6156 && task.affinity.equals(target.taskAffinity)) {
6157 // We are inside of another task... if this activity has
6158 // an affinity for our task, then either remove it if we are
6159 // clearing or move it over to our task. Note that
6160 // we currently punt on the case where we are resetting a
6161 // task that is not at the top but who has activities above
6162 // with an affinity to it... this is really not a normal
6163 // case, and we will need to later pull that task to the front
6164 // and usually at that point we will do the reset and pick
6165 // up those remaining activities. (This only happens if
6166 // someone starts an activity in a new task from an activity
6167 // in a task that is not currently on top.)
6168 if (forceReset || finishOnTaskLaunch) {
6169 if (replyChainEnd < 0) {
6170 replyChainEnd = targetI;
6171 }
6172 HistoryRecord p = null;
6173 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6174 p = (HistoryRecord)mHistory.get(srcPos);
6175 if (p.finishing) {
6176 continue;
6177 }
6178 if (finishActivityLocked(p, srcPos,
6179 Activity.RESULT_CANCELED, null, "reset")) {
6180 taskTopI--;
6181 lastReparentPos--;
6182 replyChainEnd--;
6183 srcPos--;
6184 }
6185 }
6186 replyChainEnd = -1;
6187 } else {
6188 if (replyChainEnd < 0) {
6189 replyChainEnd = targetI;
6190 }
6191 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
6192 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
6193 if (p.finishing) {
6194 continue;
6195 }
6196 if (lastReparentPos < 0) {
6197 lastReparentPos = taskTopI;
6198 taskTop = p;
6199 } else {
6200 lastReparentPos--;
6201 }
6202 mHistory.remove(srcPos);
6203 p.task.numActivities--;
6204 p.task = task;
6205 mHistory.add(lastReparentPos, p);
6206 if (DEBUG_TASKS) Log.v(TAG, "Pulling activity " + p
6207 + " in to resetting task " + task);
6208 task.numActivities++;
6209 mWindowManager.moveAppToken(lastReparentPos, p);
6210 mWindowManager.setAppGroupId(p, p.task.taskId);
6211 if (VALIDATE_TOKENS) {
6212 mWindowManager.validateAppTokens(mHistory);
6213 }
6214 }
6215 replyChainEnd = -1;
6216
6217 // Now we've moved it in to place... but what if this is
6218 // a singleTop activity and we have put it on top of another
6219 // instance of the same activity? Then we drop the instance
6220 // below so it remains singleTop.
6221 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
6222 for (int j=lastReparentPos-1; j>=0; j--) {
6223 HistoryRecord p = (HistoryRecord)mHistory.get(j);
6224 if (p.finishing) {
6225 continue;
6226 }
6227 if (p.intent.getComponent().equals(target.intent.getComponent())) {
6228 if (finishActivityLocked(p, j,
6229 Activity.RESULT_CANCELED, null, "replace")) {
6230 taskTopI--;
6231 lastReparentPos--;
6232 }
6233 }
6234 }
6235 }
6236 }
6237 }
6238
6239 target = below;
6240 targetI = i;
6241 }
6242
6243 return taskTop;
6244 }
6245
6246 /**
6247 * TODO: Add mWatcher hook
6248 */
6249 public void moveTaskToFront(int task) {
6250 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6251 "moveTaskToFront()");
6252
6253 synchronized(this) {
6254 final long origId = Binder.clearCallingIdentity();
6255 try {
6256 int N = mRecentTasks.size();
6257 for (int i=0; i<N; i++) {
6258 TaskRecord tr = mRecentTasks.get(i);
6259 if (tr.taskId == task) {
6260 moveTaskToFrontLocked(tr);
6261 return;
6262 }
6263 }
6264 for (int i=mHistory.size()-1; i>=0; i--) {
6265 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
6266 if (hr.task.taskId == task) {
6267 moveTaskToFrontLocked(hr.task);
6268 return;
6269 }
6270 }
6271 } finally {
6272 Binder.restoreCallingIdentity(origId);
6273 }
6274 }
6275 }
6276
6277 private final void moveTaskToFrontLocked(TaskRecord tr) {
6278 if (DEBUG_SWITCH) Log.v(TAG, "moveTaskToFront: " + tr);
6279
6280 final int task = tr.taskId;
6281 int top = mHistory.size()-1;
6282
6283 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
6284 // nothing to do!
6285 return;
6286 }
6287
6288 if (DEBUG_TRANSITION) Log.v(TAG,
6289 "Prepare to front transition: task=" + tr);
6290 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
6291
6292 ArrayList moved = new ArrayList();
6293
6294 // Applying the affinities may have removed entries from the history,
6295 // so get the size again.
6296 top = mHistory.size()-1;
6297 int pos = top;
6298
6299 // Shift all activities with this task up to the top
6300 // of the stack, keeping them in the same internal order.
6301 while (pos >= 0) {
6302 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
6303 if (localLOGV) Log.v(
6304 TAG, "At " + pos + " ckp " + r.task + ": " + r);
6305 boolean first = true;
6306 if (r.task.taskId == task) {
6307 if (localLOGV) Log.v(TAG, "Removing and adding at " + top);
6308 mHistory.remove(pos);
6309 mHistory.add(top, r);
6310 moved.add(0, r);
6311 top--;
6312 if (first) {
6313 addRecentTask(r.task);
6314 first = false;
6315 }
6316 }
6317 pos--;
6318 }
6319
6320 mWindowManager.moveAppTokensToTop(moved);
6321 if (VALIDATE_TOKENS) {
6322 mWindowManager.validateAppTokens(mHistory);
6323 }
6324
6325 finishTaskMove(task);
6326 EventLog.writeEvent(LOG_TASK_TO_FRONT, task);
6327 }
6328
6329 private final void finishTaskMove(int task) {
6330 resumeTopActivityLocked(null);
6331 }
6332
6333 public void moveTaskToBack(int task) {
6334 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6335 "moveTaskToBack()");
6336
6337 synchronized(this) {
6338 final long origId = Binder.clearCallingIdentity();
6339 moveTaskToBackLocked(task);
6340 Binder.restoreCallingIdentity(origId);
6341 }
6342 }
6343
6344 /**
6345 * Moves an activity, and all of the other activities within the same task, to the bottom
6346 * of the history stack. The activity's order within the task is unchanged.
6347 *
6348 * @param token A reference to the activity we wish to move
6349 * @param nonRoot If false then this only works if the activity is the root
6350 * of a task; if true it will work for any activity in a task.
6351 * @return Returns true if the move completed, false if not.
6352 */
6353 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
6354 synchronized(this) {
6355 final long origId = Binder.clearCallingIdentity();
6356 int taskId = getTaskForActivityLocked(token, !nonRoot);
6357 if (taskId >= 0) {
6358 return moveTaskToBackLocked(taskId);
6359 }
6360 Binder.restoreCallingIdentity(origId);
6361 }
6362 return false;
6363 }
6364
6365 /**
6366 * Worker method for rearranging history stack. Implements the function of moving all
6367 * activities for a specific task (gathering them if disjoint) into a single group at the
6368 * bottom of the stack.
6369 *
6370 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
6371 * to premeptively cancel the move.
6372 *
6373 * @param task The taskId to collect and move to the bottom.
6374 * @return Returns true if the move completed, false if not.
6375 */
6376 private final boolean moveTaskToBackLocked(int task) {
6377 Log.i(TAG, "moveTaskToBack: " + task);
6378
6379 // If we have a watcher, preflight the move before committing to it. First check
6380 // for *other* available tasks, but if none are available, then try again allowing the
6381 // current task to be selected.
6382 if (mWatcher != null) {
6383 HistoryRecord next = topRunningActivityLocked(null, task);
6384 if (next == null) {
6385 next = topRunningActivityLocked(null, 0);
6386 }
6387 if (next != null) {
6388 // ask watcher if this is allowed
6389 boolean moveOK = true;
6390 try {
6391 moveOK = mWatcher.activityResuming(next.packageName);
6392 } catch (RemoteException e) {
6393 mWatcher = null;
6394 }
6395 if (!moveOK) {
6396 return false;
6397 }
6398 }
6399 }
6400
6401 ArrayList moved = new ArrayList();
6402
6403 if (DEBUG_TRANSITION) Log.v(TAG,
6404 "Prepare to back transition: task=" + task);
6405 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
6406
6407 final int N = mHistory.size();
6408 int bottom = 0;
6409 int pos = 0;
6410
6411 // Shift all activities with this task down to the bottom
6412 // of the stack, keeping them in the same internal order.
6413 while (pos < N) {
6414 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
6415 if (localLOGV) Log.v(
6416 TAG, "At " + pos + " ckp " + r.task + ": " + r);
6417 if (r.task.taskId == task) {
6418 if (localLOGV) Log.v(TAG, "Removing and adding at " + (N-1));
6419 mHistory.remove(pos);
6420 mHistory.add(bottom, r);
6421 moved.add(r);
6422 bottom++;
6423 }
6424 pos++;
6425 }
6426
6427 mWindowManager.moveAppTokensToBottom(moved);
6428 if (VALIDATE_TOKENS) {
6429 mWindowManager.validateAppTokens(mHistory);
6430 }
6431
6432 finishTaskMove(task);
6433 return true;
6434 }
6435
6436 public void moveTaskBackwards(int task) {
6437 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6438 "moveTaskBackwards()");
6439
6440 synchronized(this) {
6441 final long origId = Binder.clearCallingIdentity();
6442 moveTaskBackwardsLocked(task);
6443 Binder.restoreCallingIdentity(origId);
6444 }
6445 }
6446
6447 private final void moveTaskBackwardsLocked(int task) {
6448 Log.e(TAG, "moveTaskBackwards not yet implemented!");
6449 }
6450
6451 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
6452 synchronized(this) {
6453 return getTaskForActivityLocked(token, onlyRoot);
6454 }
6455 }
6456
6457 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
6458 final int N = mHistory.size();
6459 TaskRecord lastTask = null;
6460 for (int i=0; i<N; i++) {
6461 HistoryRecord r = (HistoryRecord)mHistory.get(i);
6462 if (r == token) {
6463 if (!onlyRoot || lastTask != r.task) {
6464 return r.task.taskId;
6465 }
6466 return -1;
6467 }
6468 lastTask = r.task;
6469 }
6470
6471 return -1;
6472 }
6473
6474 /**
6475 * Returns the top activity in any existing task matching the given
6476 * Intent. Returns null if no such task is found.
6477 */
6478 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
6479 ComponentName cls = intent.getComponent();
6480 if (info.targetActivity != null) {
6481 cls = new ComponentName(info.packageName, info.targetActivity);
6482 }
6483
6484 TaskRecord cp = null;
6485
6486 final int N = mHistory.size();
6487 for (int i=(N-1); i>=0; i--) {
6488 HistoryRecord r = (HistoryRecord)mHistory.get(i);
6489 if (!r.finishing && r.task != cp
6490 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
6491 cp = r.task;
6492 //Log.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
6493 // + "/aff=" + r.task.affinity + " to new cls="
6494 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
6495 if (r.task.affinity != null) {
6496 if (r.task.affinity.equals(info.taskAffinity)) {
6497 //Log.i(TAG, "Found matching affinity!");
6498 return r;
6499 }
6500 } else if (r.task.intent != null
6501 && r.task.intent.getComponent().equals(cls)) {
6502 //Log.i(TAG, "Found matching class!");
6503 //dump();
6504 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
6505 return r;
6506 } else if (r.task.affinityIntent != null
6507 && r.task.affinityIntent.getComponent().equals(cls)) {
6508 //Log.i(TAG, "Found matching class!");
6509 //dump();
6510 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
6511 return r;
6512 }
6513 }
6514 }
6515
6516 return null;
6517 }
6518
6519 /**
6520 * Returns the first activity (starting from the top of the stack) that
6521 * is the same as the given activity. Returns null if no such activity
6522 * is found.
6523 */
6524 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
6525 ComponentName cls = intent.getComponent();
6526 if (info.targetActivity != null) {
6527 cls = new ComponentName(info.packageName, info.targetActivity);
6528 }
6529
6530 final int N = mHistory.size();
6531 for (int i=(N-1); i>=0; i--) {
6532 HistoryRecord r = (HistoryRecord)mHistory.get(i);
6533 if (!r.finishing) {
6534 if (r.intent.getComponent().equals(cls)) {
6535 //Log.i(TAG, "Found matching class!");
6536 //dump();
6537 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
6538 return r;
6539 }
6540 }
6541 }
6542
6543 return null;
6544 }
6545
6546 public void finishOtherInstances(IBinder token, ComponentName className) {
6547 synchronized(this) {
6548 final long origId = Binder.clearCallingIdentity();
6549
6550 int N = mHistory.size();
6551 TaskRecord lastTask = null;
6552 for (int i=0; i<N; i++) {
6553 HistoryRecord r = (HistoryRecord)mHistory.get(i);
6554 if (r.realActivity.equals(className)
6555 && r != token && lastTask != r.task) {
6556 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
6557 null, "others")) {
6558 i--;
6559 N--;
6560 }
6561 }
6562 lastTask = r.task;
6563 }
6564
6565 Binder.restoreCallingIdentity(origId);
6566 }
6567 }
6568
6569 // =========================================================
6570 // THUMBNAILS
6571 // =========================================================
6572
6573 public void reportThumbnail(IBinder token,
6574 Bitmap thumbnail, CharSequence description) {
6575 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
6576 final long origId = Binder.clearCallingIdentity();
6577 sendPendingThumbnail(null, token, thumbnail, description, true);
6578 Binder.restoreCallingIdentity(origId);
6579 }
6580
6581 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
6582 Bitmap thumbnail, CharSequence description, boolean always) {
6583 TaskRecord task = null;
6584 ArrayList receivers = null;
6585
6586 //System.out.println("Send pending thumbnail: " + r);
6587
6588 synchronized(this) {
6589 if (r == null) {
6590 int index = indexOfTokenLocked(token, false);
6591 if (index < 0) {
6592 return;
6593 }
6594 r = (HistoryRecord)mHistory.get(index);
6595 }
6596 if (thumbnail == null) {
6597 thumbnail = r.thumbnail;
6598 description = r.description;
6599 }
6600 if (thumbnail == null && !always) {
6601 // If there is no thumbnail, and this entry is not actually
6602 // going away, then abort for now and pick up the next
6603 // thumbnail we get.
6604 return;
6605 }
6606 task = r.task;
6607
6608 int N = mPendingThumbnails.size();
6609 int i=0;
6610 while (i<N) {
6611 PendingThumbnailsRecord pr =
6612 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
6613 //System.out.println("Looking in " + pr.pendingRecords);
6614 if (pr.pendingRecords.remove(r)) {
6615 if (receivers == null) {
6616 receivers = new ArrayList();
6617 }
6618 receivers.add(pr);
6619 if (pr.pendingRecords.size() == 0) {
6620 pr.finished = true;
6621 mPendingThumbnails.remove(i);
6622 N--;
6623 continue;
6624 }
6625 }
6626 i++;
6627 }
6628 }
6629
6630 if (receivers != null) {
6631 final int N = receivers.size();
6632 for (int i=0; i<N; i++) {
6633 try {
6634 PendingThumbnailsRecord pr =
6635 (PendingThumbnailsRecord)receivers.get(i);
6636 pr.receiver.newThumbnail(
6637 task != null ? task.taskId : -1, thumbnail, description);
6638 if (pr.finished) {
6639 pr.receiver.finished();
6640 }
6641 } catch (Exception e) {
6642 Log.w(TAG, "Exception thrown when sending thumbnail", e);
6643 }
6644 }
6645 }
6646 }
6647
6648 // =========================================================
6649 // CONTENT PROVIDERS
6650 // =========================================================
6651
6652 private final List generateApplicationProvidersLocked(ProcessRecord app) {
6653 List providers = null;
6654 try {
6655 providers = ActivityThread.getPackageManager().
6656 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07006657 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 } catch (RemoteException ex) {
6659 }
6660 if (providers != null) {
6661 final int N = providers.size();
6662 for (int i=0; i<N; i++) {
6663 ProviderInfo cpi =
6664 (ProviderInfo)providers.get(i);
6665 ContentProviderRecord cpr =
6666 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
6667 if (cpr == null) {
6668 cpr = new ContentProviderRecord(cpi, app.info);
6669 mProvidersByClass.put(cpi.name, cpr);
6670 }
6671 app.pubProviders.put(cpi.name, cpr);
6672 app.addPackage(cpi.applicationInfo.packageName);
6673 }
6674 }
6675 return providers;
6676 }
6677
6678 private final String checkContentProviderPermissionLocked(
6679 ProviderInfo cpi, ProcessRecord r, int mode) {
6680 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
6681 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
6682 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
6683 cpi.exported ? -1 : cpi.applicationInfo.uid)
6684 == PackageManager.PERMISSION_GRANTED
6685 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
6686 return null;
6687 }
6688 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
6689 cpi.exported ? -1 : cpi.applicationInfo.uid)
6690 == PackageManager.PERMISSION_GRANTED) {
6691 return null;
6692 }
6693 String msg = "Permission Denial: opening provider " + cpi.name
6694 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
6695 + ", uid=" + callingUid + ") requires "
6696 + cpi.readPermission + " or " + cpi.writePermission;
6697 Log.w(TAG, msg);
6698 return msg;
6699 }
6700
6701 private final ContentProviderHolder getContentProviderImpl(
6702 IApplicationThread caller, String name) {
6703 ContentProviderRecord cpr;
6704 ProviderInfo cpi = null;
6705
6706 synchronized(this) {
6707 ProcessRecord r = null;
6708 if (caller != null) {
6709 r = getRecordForAppLocked(caller);
6710 if (r == null) {
6711 throw new SecurityException(
6712 "Unable to find app for caller " + caller
6713 + " (pid=" + Binder.getCallingPid()
6714 + ") when getting content provider " + name);
6715 }
6716 }
6717
6718 // First check if this content provider has been published...
6719 cpr = (ContentProviderRecord)mProvidersByName.get(name);
6720 if (cpr != null) {
6721 cpi = cpr.info;
6722 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
6723 return new ContentProviderHolder(cpi,
6724 cpi.readPermission != null
6725 ? cpi.readPermission : cpi.writePermission);
6726 }
6727
6728 if (r != null && cpr.canRunHere(r)) {
6729 // This provider has been published or is in the process
6730 // of being published... but it is also allowed to run
6731 // in the caller's process, so don't make a connection
6732 // and just let the caller instantiate its own instance.
6733 if (cpr.provider != null) {
6734 // don't give caller the provider object, it needs
6735 // to make its own.
6736 cpr = new ContentProviderRecord(cpr);
6737 }
6738 return cpr;
6739 }
6740
6741 final long origId = Binder.clearCallingIdentity();
6742
6743 // In this case the provider is a single instance, so we can
6744 // return it right away.
6745 if (r != null) {
6746 r.conProviders.add(cpr);
6747 cpr.clients.add(r);
6748 } else {
6749 cpr.externals++;
6750 }
6751
6752 if (cpr.app != null) {
6753 updateOomAdjLocked(cpr.app);
6754 }
6755
6756 Binder.restoreCallingIdentity(origId);
6757
6758 } else {
6759 try {
6760 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006761 resolveContentProvider(name,
6762 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006763 } catch (RemoteException ex) {
6764 }
6765 if (cpi == null) {
6766 return null;
6767 }
6768
6769 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
6770 return new ContentProviderHolder(cpi,
6771 cpi.readPermission != null
6772 ? cpi.readPermission : cpi.writePermission);
6773 }
6774
6775 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
6776 final boolean firstClass = cpr == null;
6777 if (firstClass) {
6778 try {
6779 ApplicationInfo ai =
6780 ActivityThread.getPackageManager().
6781 getApplicationInfo(
6782 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07006783 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006784 if (ai == null) {
6785 Log.w(TAG, "No package info for content provider "
6786 + cpi.name);
6787 return null;
6788 }
6789 cpr = new ContentProviderRecord(cpi, ai);
6790 } catch (RemoteException ex) {
6791 // pm is in same process, this will never happen.
6792 }
6793 }
6794
6795 if (r != null && cpr.canRunHere(r)) {
6796 // If this is a multiprocess provider, then just return its
6797 // info and allow the caller to instantiate it. Only do
6798 // this if the provider is the same user as the caller's
6799 // process, or can run as root (so can be in any process).
6800 return cpr;
6801 }
6802
6803 if (false) {
6804 RuntimeException e = new RuntimeException("foo");
6805 //Log.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
6806 // + " pruid " + ai.uid + "): " + cpi.className, e);
6807 }
6808
6809 // This is single process, and our app is now connecting to it.
6810 // See if we are already in the process of launching this
6811 // provider.
6812 final int N = mLaunchingProviders.size();
6813 int i;
6814 for (i=0; i<N; i++) {
6815 if (mLaunchingProviders.get(i) == cpr) {
6816 break;
6817 }
6818 if (false) {
6819 final ContentProviderRecord rec =
6820 (ContentProviderRecord)mLaunchingProviders.get(i);
6821 if (rec.info.name.equals(cpr.info.name)) {
6822 cpr = rec;
6823 break;
6824 }
6825 }
6826 }
6827
6828 // If the provider is not already being launched, then get it
6829 // started.
6830 if (i >= N) {
6831 final long origId = Binder.clearCallingIdentity();
6832 ProcessRecord proc = startProcessLocked(cpi.processName,
6833 cpr.appInfo, false, 0, "content provider",
6834 new ComponentName(cpi.applicationInfo.packageName,
6835 cpi.name));
6836 if (proc == null) {
6837 Log.w(TAG, "Unable to launch app "
6838 + cpi.applicationInfo.packageName + "/"
6839 + cpi.applicationInfo.uid + " for provider "
6840 + name + ": process is bad");
6841 return null;
6842 }
6843 cpr.launchingApp = proc;
6844 mLaunchingProviders.add(cpr);
6845 Binder.restoreCallingIdentity(origId);
6846 }
6847
6848 // Make sure the provider is published (the same provider class
6849 // may be published under multiple names).
6850 if (firstClass) {
6851 mProvidersByClass.put(cpi.name, cpr);
6852 }
6853 mProvidersByName.put(name, cpr);
6854
6855 if (r != null) {
6856 r.conProviders.add(cpr);
6857 cpr.clients.add(r);
6858 } else {
6859 cpr.externals++;
6860 }
6861 }
6862 }
6863
6864 // Wait for the provider to be published...
6865 synchronized (cpr) {
6866 while (cpr.provider == null) {
6867 if (cpr.launchingApp == null) {
6868 Log.w(TAG, "Unable to launch app "
6869 + cpi.applicationInfo.packageName + "/"
6870 + cpi.applicationInfo.uid + " for provider "
6871 + name + ": launching app became null");
6872 EventLog.writeEvent(LOG_AM_PROVIDER_LOST_PROCESS,
6873 cpi.applicationInfo.packageName,
6874 cpi.applicationInfo.uid, name);
6875 return null;
6876 }
6877 try {
6878 cpr.wait();
6879 } catch (InterruptedException ex) {
6880 }
6881 }
6882 }
6883 return cpr;
6884 }
6885
6886 public final ContentProviderHolder getContentProvider(
6887 IApplicationThread caller, String name) {
6888 if (caller == null) {
6889 String msg = "null IApplicationThread when getting content provider "
6890 + name;
6891 Log.w(TAG, msg);
6892 throw new SecurityException(msg);
6893 }
6894
6895 return getContentProviderImpl(caller, name);
6896 }
6897
6898 private ContentProviderHolder getContentProviderExternal(String name) {
6899 return getContentProviderImpl(null, name);
6900 }
6901
6902 /**
6903 * Drop a content provider from a ProcessRecord's bookkeeping
6904 * @param cpr
6905 */
6906 public void removeContentProvider(IApplicationThread caller, String name) {
6907 synchronized (this) {
6908 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
6909 if(cpr == null) {
6910 //remove from mProvidersByClass
6911 if(localLOGV) Log.v(TAG, name+" content provider not found in providers list");
6912 return;
6913 }
6914 final ProcessRecord r = getRecordForAppLocked(caller);
6915 if (r == null) {
6916 throw new SecurityException(
6917 "Unable to find app for caller " + caller +
6918 " when removing content provider " + name);
6919 }
6920 //update content provider record entry info
6921 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
6922 if(localLOGV) Log.v(TAG, "Removing content provider requested by "+
6923 r.info.processName+" from process "+localCpr.appInfo.processName);
6924 if(localCpr.appInfo.processName == r.info.processName) {
6925 //should not happen. taken care of as a local provider
6926 if(localLOGV) Log.v(TAG, "local provider doing nothing Ignoring other names");
6927 return;
6928 } else {
6929 localCpr.clients.remove(r);
6930 r.conProviders.remove(localCpr);
6931 }
6932 updateOomAdjLocked();
6933 }
6934 }
6935
6936 private void removeContentProviderExternal(String name) {
6937 synchronized (this) {
6938 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
6939 if(cpr == null) {
6940 //remove from mProvidersByClass
6941 if(localLOGV) Log.v(TAG, name+" content provider not found in providers list");
6942 return;
6943 }
6944
6945 //update content provider record entry info
6946 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
6947 localCpr.externals--;
6948 if (localCpr.externals < 0) {
6949 Log.e(TAG, "Externals < 0 for content provider " + localCpr);
6950 }
6951 updateOomAdjLocked();
6952 }
6953 }
6954
6955 public final void publishContentProviders(IApplicationThread caller,
6956 List<ContentProviderHolder> providers) {
6957 if (providers == null) {
6958 return;
6959 }
6960
6961 synchronized(this) {
6962 final ProcessRecord r = getRecordForAppLocked(caller);
6963 if (r == null) {
6964 throw new SecurityException(
6965 "Unable to find app for caller " + caller
6966 + " (pid=" + Binder.getCallingPid()
6967 + ") when publishing content providers");
6968 }
6969
6970 final long origId = Binder.clearCallingIdentity();
6971
6972 final int N = providers.size();
6973 for (int i=0; i<N; i++) {
6974 ContentProviderHolder src = providers.get(i);
6975 if (src == null || src.info == null || src.provider == null) {
6976 continue;
6977 }
6978 ContentProviderRecord dst =
6979 (ContentProviderRecord)r.pubProviders.get(src.info.name);
6980 if (dst != null) {
6981 mProvidersByClass.put(dst.info.name, dst);
6982 String names[] = dst.info.authority.split(";");
6983 for (int j = 0; j < names.length; j++) {
6984 mProvidersByName.put(names[j], dst);
6985 }
6986
6987 int NL = mLaunchingProviders.size();
6988 int j;
6989 for (j=0; j<NL; j++) {
6990 if (mLaunchingProviders.get(j) == dst) {
6991 mLaunchingProviders.remove(j);
6992 j--;
6993 NL--;
6994 }
6995 }
6996 synchronized (dst) {
6997 dst.provider = src.provider;
6998 dst.app = r;
6999 dst.notifyAll();
7000 }
7001 updateOomAdjLocked(r);
7002 }
7003 }
7004
7005 Binder.restoreCallingIdentity(origId);
7006 }
7007 }
7008
7009 public static final void installSystemProviders() {
7010 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7011 List providers = mSelf.generateApplicationProvidersLocked(app);
7012 mSystemThread.installSystemProviders(providers);
7013 }
7014
7015 // =========================================================
7016 // GLOBAL MANAGEMENT
7017 // =========================================================
7018
7019 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
7020 ApplicationInfo info, String customProcess) {
7021 String proc = customProcess != null ? customProcess : info.processName;
7022 BatteryStatsImpl.Uid.Proc ps = null;
7023 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7024 synchronized (stats) {
7025 ps = stats.getProcessStatsLocked(info.uid, proc);
7026 }
7027 return new ProcessRecord(ps, thread, info, proc);
7028 }
7029
7030 final ProcessRecord addAppLocked(ApplicationInfo info) {
7031 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
7032
7033 if (app == null) {
7034 app = newProcessRecordLocked(null, info, null);
7035 mProcessNames.put(info.processName, info.uid, app);
7036 updateLRUListLocked(app, true);
7037 }
7038
7039 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
7040 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
7041 app.persistent = true;
7042 app.maxAdj = CORE_SERVER_ADJ;
7043 }
7044 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
7045 mPersistentStartingProcesses.add(app);
7046 startProcessLocked(app, "added application", app.processName);
7047 }
7048
7049 return app;
7050 }
7051
7052 public void unhandledBack() {
7053 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
7054 "unhandledBack()");
7055
7056 synchronized(this) {
7057 int count = mHistory.size();
7058 if (Config.LOGD) Log.d(
7059 TAG, "Performing unhandledBack(): stack size = " + count);
7060 if (count > 1) {
7061 final long origId = Binder.clearCallingIdentity();
7062 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
7063 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
7064 Binder.restoreCallingIdentity(origId);
7065 }
7066 }
7067 }
7068
7069 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
7070 String name = uri.getAuthority();
7071 ContentProviderHolder cph = getContentProviderExternal(name);
7072 ParcelFileDescriptor pfd = null;
7073 if (cph != null) {
7074 // We record the binder invoker's uid in thread-local storage before
7075 // going to the content provider to open the file. Later, in the code
7076 // that handles all permissions checks, we look for this uid and use
7077 // that rather than the Activity Manager's own uid. The effect is that
7078 // we do the check against the caller's permissions even though it looks
7079 // to the content provider like the Activity Manager itself is making
7080 // the request.
7081 sCallerIdentity.set(new Identity(
7082 Binder.getCallingPid(), Binder.getCallingUid()));
7083 try {
7084 pfd = cph.provider.openFile(uri, "r");
7085 } catch (FileNotFoundException e) {
7086 // do nothing; pfd will be returned null
7087 } finally {
7088 // Ensure that whatever happens, we clean up the identity state
7089 sCallerIdentity.remove();
7090 }
7091
7092 // We've got the fd now, so we're done with the provider.
7093 removeContentProviderExternal(name);
7094 } else {
7095 Log.d(TAG, "Failed to get provider for authority '" + name + "'");
7096 }
7097 return pfd;
7098 }
7099
7100 public void goingToSleep() {
7101 synchronized(this) {
7102 mSleeping = true;
7103 mWindowManager.setEventDispatching(false);
7104
7105 if (mResumedActivity != null) {
7106 pauseIfSleepingLocked();
7107 } else {
7108 Log.w(TAG, "goingToSleep with no resumed activity!");
7109 }
7110 }
7111 }
7112
Dianne Hackborn55280a92009-05-07 15:53:46 -07007113 public boolean shutdown(int timeout) {
7114 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
7115 != PackageManager.PERMISSION_GRANTED) {
7116 throw new SecurityException("Requires permission "
7117 + android.Manifest.permission.SHUTDOWN);
7118 }
7119
7120 boolean timedout = false;
7121
7122 synchronized(this) {
7123 mShuttingDown = true;
7124 mWindowManager.setEventDispatching(false);
7125
7126 if (mResumedActivity != null) {
7127 pauseIfSleepingLocked();
7128 final long endTime = System.currentTimeMillis() + timeout;
7129 while (mResumedActivity != null || mPausingActivity != null) {
7130 long delay = endTime - System.currentTimeMillis();
7131 if (delay <= 0) {
7132 Log.w(TAG, "Activity manager shutdown timed out");
7133 timedout = true;
7134 break;
7135 }
7136 try {
7137 this.wait();
7138 } catch (InterruptedException e) {
7139 }
7140 }
7141 }
7142 }
7143
7144 mUsageStatsService.shutdown();
7145 mBatteryStatsService.shutdown();
7146
7147 return timedout;
7148 }
7149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007150 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07007151 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007152 if (!mGoingToSleep.isHeld()) {
7153 mGoingToSleep.acquire();
7154 if (mLaunchingActivity.isHeld()) {
7155 mLaunchingActivity.release();
7156 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
7157 }
7158 }
7159
7160 // If we are not currently pausing an activity, get the current
7161 // one to pause. If we are pausing one, we will just let that stuff
7162 // run and release the wake lock when all done.
7163 if (mPausingActivity == null) {
7164 if (DEBUG_PAUSE) Log.v(TAG, "Sleep needs to pause...");
7165 if (DEBUG_USER_LEAVING) Log.v(TAG, "Sleep => pause with userLeaving=false");
7166 startPausingLocked(false, true);
7167 }
7168 }
7169 }
7170
7171 public void wakingUp() {
7172 synchronized(this) {
7173 if (mGoingToSleep.isHeld()) {
7174 mGoingToSleep.release();
7175 }
7176 mWindowManager.setEventDispatching(true);
7177 mSleeping = false;
7178 resumeTopActivityLocked(null);
7179 }
7180 }
7181
7182 public void setDebugApp(String packageName, boolean waitForDebugger,
7183 boolean persistent) {
7184 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
7185 "setDebugApp()");
7186
7187 // Note that this is not really thread safe if there are multiple
7188 // callers into it at the same time, but that's not a situation we
7189 // care about.
7190 if (persistent) {
7191 final ContentResolver resolver = mContext.getContentResolver();
7192 Settings.System.putString(
7193 resolver, Settings.System.DEBUG_APP,
7194 packageName);
7195 Settings.System.putInt(
7196 resolver, Settings.System.WAIT_FOR_DEBUGGER,
7197 waitForDebugger ? 1 : 0);
7198 }
7199
7200 synchronized (this) {
7201 if (!persistent) {
7202 mOrigDebugApp = mDebugApp;
7203 mOrigWaitForDebugger = mWaitForDebugger;
7204 }
7205 mDebugApp = packageName;
7206 mWaitForDebugger = waitForDebugger;
7207 mDebugTransient = !persistent;
7208 if (packageName != null) {
7209 final long origId = Binder.clearCallingIdentity();
7210 uninstallPackageLocked(packageName, -1, false);
7211 Binder.restoreCallingIdentity(origId);
7212 }
7213 }
7214 }
7215
7216 public void setAlwaysFinish(boolean enabled) {
7217 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
7218 "setAlwaysFinish()");
7219
7220 Settings.System.putInt(
7221 mContext.getContentResolver(),
7222 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
7223
7224 synchronized (this) {
7225 mAlwaysFinishActivities = enabled;
7226 }
7227 }
7228
7229 public void setActivityWatcher(IActivityWatcher watcher) {
7230 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
7231 "setActivityWatcher()");
7232 synchronized (this) {
7233 mWatcher = watcher;
7234 }
7235 }
7236
7237 public final void enterSafeMode() {
7238 synchronized(this) {
7239 // It only makes sense to do this before the system is ready
7240 // and started launching other packages.
7241 if (!mSystemReady) {
7242 try {
7243 ActivityThread.getPackageManager().enterSafeMode();
7244 } catch (RemoteException e) {
7245 }
7246
7247 View v = LayoutInflater.from(mContext).inflate(
7248 com.android.internal.R.layout.safe_mode, null);
7249 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
7250 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
7251 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
7252 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
7253 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
7254 lp.format = v.getBackground().getOpacity();
7255 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
7256 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
7257 ((WindowManager)mContext.getSystemService(
7258 Context.WINDOW_SERVICE)).addView(v, lp);
7259 }
7260 }
7261 }
7262
7263 public void noteWakeupAlarm(IIntentSender sender) {
7264 if (!(sender instanceof PendingIntentRecord)) {
7265 return;
7266 }
7267 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7268 synchronized (stats) {
7269 if (mBatteryStatsService.isOnBattery()) {
7270 mBatteryStatsService.enforceCallingPermission();
7271 PendingIntentRecord rec = (PendingIntentRecord)sender;
7272 int MY_UID = Binder.getCallingUid();
7273 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
7274 BatteryStatsImpl.Uid.Pkg pkg =
7275 stats.getPackageStatsLocked(uid, rec.key.packageName);
7276 pkg.incWakeupsLocked();
7277 }
7278 }
7279 }
7280
7281 public boolean killPidsForMemory(int[] pids) {
7282 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
7283 throw new SecurityException("killPidsForMemory only available to the system");
7284 }
7285
7286 // XXX Note: don't acquire main activity lock here, because the window
7287 // manager calls in with its locks held.
7288
7289 boolean killed = false;
7290 synchronized (mPidsSelfLocked) {
7291 int[] types = new int[pids.length];
7292 int worstType = 0;
7293 for (int i=0; i<pids.length; i++) {
7294 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
7295 if (proc != null) {
7296 int type = proc.setAdj;
7297 types[i] = type;
7298 if (type > worstType) {
7299 worstType = type;
7300 }
7301 }
7302 }
7303
7304 // If the worse oom_adj is somewhere in the hidden proc LRU range,
7305 // then constrain it so we will kill all hidden procs.
7306 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
7307 worstType = HIDDEN_APP_MIN_ADJ;
7308 }
7309 Log.w(TAG, "Killing processes for memory at adjustment " + worstType);
7310 for (int i=0; i<pids.length; i++) {
7311 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
7312 if (proc == null) {
7313 continue;
7314 }
7315 int adj = proc.setAdj;
7316 if (adj >= worstType) {
7317 Log.w(TAG, "Killing for memory: " + proc + " (adj "
7318 + adj + ")");
7319 EventLog.writeEvent(LOG_AM_KILL_FOR_MEMORY, proc.pid,
7320 proc.processName, adj);
7321 killed = true;
7322 Process.killProcess(pids[i]);
7323 }
7324 }
7325 }
7326 return killed;
7327 }
7328
7329 public void reportPss(IApplicationThread caller, int pss) {
7330 Watchdog.PssRequestor req;
7331 String name;
7332 ProcessRecord callerApp;
7333 synchronized (this) {
7334 if (caller == null) {
7335 return;
7336 }
7337 callerApp = getRecordForAppLocked(caller);
7338 if (callerApp == null) {
7339 return;
7340 }
7341 callerApp.lastPss = pss;
7342 req = callerApp;
7343 name = callerApp.processName;
7344 }
7345 Watchdog.getInstance().reportPss(req, name, pss);
7346 if (!callerApp.persistent) {
7347 removeRequestedPss(callerApp);
7348 }
7349 }
7350
7351 public void requestPss(Runnable completeCallback) {
7352 ArrayList<ProcessRecord> procs;
7353 synchronized (this) {
7354 mRequestPssCallback = completeCallback;
7355 mRequestPssList.clear();
7356 for (int i=mLRUProcesses.size()-1; i>=0; i--) {
7357 ProcessRecord proc = mLRUProcesses.get(i);
7358 if (!proc.persistent) {
7359 mRequestPssList.add(proc);
7360 }
7361 }
7362 procs = new ArrayList<ProcessRecord>(mRequestPssList);
7363 }
7364
7365 int oldPri = Process.getThreadPriority(Process.myTid());
7366 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
7367 for (int i=procs.size()-1; i>=0; i--) {
7368 ProcessRecord proc = procs.get(i);
7369 proc.lastPss = 0;
7370 proc.requestPss();
7371 }
7372 Process.setThreadPriority(oldPri);
7373 }
7374
7375 void removeRequestedPss(ProcessRecord proc) {
7376 Runnable callback = null;
7377 synchronized (this) {
7378 if (mRequestPssList.remove(proc)) {
7379 if (mRequestPssList.size() == 0) {
7380 callback = mRequestPssCallback;
7381 mRequestPssCallback = null;
7382 }
7383 }
7384 }
7385
7386 if (callback != null) {
7387 callback.run();
7388 }
7389 }
7390
7391 public void collectPss(Watchdog.PssStats stats) {
7392 stats.mEmptyPss = 0;
7393 stats.mEmptyCount = 0;
7394 stats.mBackgroundPss = 0;
7395 stats.mBackgroundCount = 0;
7396 stats.mServicePss = 0;
7397 stats.mServiceCount = 0;
7398 stats.mVisiblePss = 0;
7399 stats.mVisibleCount = 0;
7400 stats.mForegroundPss = 0;
7401 stats.mForegroundCount = 0;
7402 stats.mNoPssCount = 0;
7403 synchronized (this) {
7404 int i;
7405 int NPD = mProcDeaths.length < stats.mProcDeaths.length
7406 ? mProcDeaths.length : stats.mProcDeaths.length;
7407 int aggr = 0;
7408 for (i=0; i<NPD; i++) {
7409 aggr += mProcDeaths[i];
7410 stats.mProcDeaths[i] = aggr;
7411 }
7412 while (i<stats.mProcDeaths.length) {
7413 stats.mProcDeaths[i] = 0;
7414 i++;
7415 }
7416
7417 for (i=mLRUProcesses.size()-1; i>=0; i--) {
7418 ProcessRecord proc = mLRUProcesses.get(i);
7419 if (proc.persistent) {
7420 continue;
7421 }
7422 //Log.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
7423 if (proc.lastPss == 0) {
7424 stats.mNoPssCount++;
7425 continue;
7426 }
7427 if (proc.setAdj == EMPTY_APP_ADJ) {
7428 stats.mEmptyPss += proc.lastPss;
7429 stats.mEmptyCount++;
7430 } else if (proc.setAdj == CONTENT_PROVIDER_ADJ) {
7431 stats.mEmptyPss += proc.lastPss;
7432 stats.mEmptyCount++;
7433 } else if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
7434 stats.mBackgroundPss += proc.lastPss;
7435 stats.mBackgroundCount++;
7436 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
7437 stats.mVisiblePss += proc.lastPss;
7438 stats.mVisibleCount++;
7439 } else {
7440 stats.mForegroundPss += proc.lastPss;
7441 stats.mForegroundCount++;
7442 }
7443 }
7444 }
7445 }
7446
7447 public final void startRunning(String pkg, String cls, String action,
7448 String data) {
7449 synchronized(this) {
7450 if (mStartRunning) {
7451 return;
7452 }
7453 mStartRunning = true;
7454 mTopComponent = pkg != null && cls != null
7455 ? new ComponentName(pkg, cls) : null;
7456 mTopAction = action != null ? action : Intent.ACTION_MAIN;
7457 mTopData = data;
7458 if (!mSystemReady) {
7459 return;
7460 }
7461 }
7462
7463 systemReady();
7464 }
7465
7466 private void retrieveSettings() {
7467 final ContentResolver resolver = mContext.getContentResolver();
7468 String debugApp = Settings.System.getString(
7469 resolver, Settings.System.DEBUG_APP);
7470 boolean waitForDebugger = Settings.System.getInt(
7471 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
7472 boolean alwaysFinishActivities = Settings.System.getInt(
7473 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
7474
7475 Configuration configuration = new Configuration();
7476 Settings.System.getConfiguration(resolver, configuration);
7477
7478 synchronized (this) {
7479 mDebugApp = mOrigDebugApp = debugApp;
7480 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
7481 mAlwaysFinishActivities = alwaysFinishActivities;
7482 // This happens before any activities are started, so we can
7483 // change mConfiguration in-place.
7484 mConfiguration.updateFrom(configuration);
7485 }
7486 }
7487
7488 public boolean testIsSystemReady() {
7489 // no need to synchronize(this) just to read & return the value
7490 return mSystemReady;
7491 }
7492
7493 public void systemReady() {
7494 // In the simulator, startRunning will never have been called, which
7495 // normally sets a few crucial variables. Do it here instead.
7496 if (!Process.supportsProcesses()) {
7497 mStartRunning = true;
7498 mTopAction = Intent.ACTION_MAIN;
7499 }
7500
7501 synchronized(this) {
7502 if (mSystemReady) {
7503 return;
7504 }
7505 mSystemReady = true;
7506 if (!mStartRunning) {
7507 return;
7508 }
7509 }
7510
7511 if (Config.LOGD) Log.d(TAG, "Start running!");
7512 EventLog.writeEvent(LOG_BOOT_PROGRESS_AMS_READY,
7513 SystemClock.uptimeMillis());
7514
7515 synchronized(this) {
7516 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
7517 ResolveInfo ri = mContext.getPackageManager()
7518 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07007519 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007520 CharSequence errorMsg = null;
7521 if (ri != null) {
7522 ActivityInfo ai = ri.activityInfo;
7523 ApplicationInfo app = ai.applicationInfo;
7524 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7525 mTopAction = Intent.ACTION_FACTORY_TEST;
7526 mTopData = null;
7527 mTopComponent = new ComponentName(app.packageName,
7528 ai.name);
7529 } else {
7530 errorMsg = mContext.getResources().getText(
7531 com.android.internal.R.string.factorytest_not_system);
7532 }
7533 } else {
7534 errorMsg = mContext.getResources().getText(
7535 com.android.internal.R.string.factorytest_no_action);
7536 }
7537 if (errorMsg != null) {
7538 mTopAction = null;
7539 mTopData = null;
7540 mTopComponent = null;
7541 Message msg = Message.obtain();
7542 msg.what = SHOW_FACTORY_ERROR_MSG;
7543 msg.getData().putCharSequence("msg", errorMsg);
7544 mHandler.sendMessage(msg);
7545 }
7546 }
7547 }
7548
7549 retrieveSettings();
7550
7551 synchronized (this) {
7552 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
7553 try {
7554 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007555 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007556 if (apps != null) {
7557 int N = apps.size();
7558 int i;
7559 for (i=0; i<N; i++) {
7560 ApplicationInfo info
7561 = (ApplicationInfo)apps.get(i);
7562 if (info != null &&
7563 !info.packageName.equals("android")) {
7564 addAppLocked(info);
7565 }
7566 }
7567 }
7568 } catch (RemoteException ex) {
7569 // pm is in same process, this will never happen.
7570 }
7571 }
7572
7573 try {
7574 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
7575 Message msg = Message.obtain();
7576 msg.what = SHOW_UID_ERROR_MSG;
7577 mHandler.sendMessage(msg);
7578 }
7579 } catch (RemoteException e) {
7580 }
7581
7582 // Start up initial activity.
7583 mBooting = true;
7584 resumeTopActivityLocked(null);
7585 }
7586 }
7587
7588 boolean makeAppCrashingLocked(ProcessRecord app,
7589 String tag, String shortMsg, String longMsg, byte[] crashData) {
7590 app.crashing = true;
7591 app.crashingReport = generateProcessError(app,
7592 ActivityManager.ProcessErrorStateInfo.CRASHED, tag, shortMsg, longMsg, crashData);
7593 startAppProblemLocked(app);
7594 app.stopFreezingAllLocked();
7595 return handleAppCrashLocked(app);
7596 }
7597
7598 void makeAppNotRespondingLocked(ProcessRecord app,
7599 String tag, String shortMsg, String longMsg, byte[] crashData) {
7600 app.notResponding = true;
7601 app.notRespondingReport = generateProcessError(app,
7602 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING, tag, shortMsg, longMsg,
7603 crashData);
7604 startAppProblemLocked(app);
7605 app.stopFreezingAllLocked();
7606 }
7607
7608 /**
7609 * Generate a process error record, suitable for attachment to a ProcessRecord.
7610 *
7611 * @param app The ProcessRecord in which the error occurred.
7612 * @param condition Crashing, Application Not Responding, etc. Values are defined in
7613 * ActivityManager.AppErrorStateInfo
7614 * @param tag The tag that was passed into handleApplicationError(). Typically the classname.
7615 * @param shortMsg Short message describing the crash.
7616 * @param longMsg Long message describing the crash.
7617 * @param crashData Raw data passed into handleApplicationError(). Typically a stack trace.
7618 *
7619 * @return Returns a fully-formed AppErrorStateInfo record.
7620 */
7621 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
7622 int condition, String tag, String shortMsg, String longMsg, byte[] crashData) {
7623 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
7624
7625 report.condition = condition;
7626 report.processName = app.processName;
7627 report.pid = app.pid;
7628 report.uid = app.info.uid;
7629 report.tag = tag;
7630 report.shortMsg = shortMsg;
7631 report.longMsg = longMsg;
7632 report.crashData = crashData;
7633
7634 return report;
7635 }
7636
7637 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog,
7638 boolean crashed) {
7639 synchronized (this) {
7640 app.crashing = false;
7641 app.crashingReport = null;
7642 app.notResponding = false;
7643 app.notRespondingReport = null;
7644 if (app.anrDialog == fromDialog) {
7645 app.anrDialog = null;
7646 }
7647 if (app.waitDialog == fromDialog) {
7648 app.waitDialog = null;
7649 }
7650 if (app.pid > 0 && app.pid != MY_PID) {
7651 if (crashed) {
7652 handleAppCrashLocked(app);
7653 }
7654 Log.i(ActivityManagerService.TAG, "Killing process "
7655 + app.processName
7656 + " (pid=" + app.pid + ") at user's request");
7657 Process.killProcess(app.pid);
7658 }
7659
7660 }
7661 }
7662
7663 boolean handleAppCrashLocked(ProcessRecord app) {
7664 long now = SystemClock.uptimeMillis();
7665
7666 Long crashTime = mProcessCrashTimes.get(app.info.processName,
7667 app.info.uid);
7668 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
7669 // This process loses!
7670 Log.w(TAG, "Process " + app.info.processName
7671 + " has crashed too many times: killing!");
7672 EventLog.writeEvent(LOG_AM_PROCESS_CRASHED_TOO_MUCH,
7673 app.info.processName, app.info.uid);
7674 killServicesLocked(app, false);
7675 for (int i=mHistory.size()-1; i>=0; i--) {
7676 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7677 if (r.app == app) {
7678 if (Config.LOGD) Log.d(
7679 TAG, " Force finishing activity "
7680 + r.intent.getComponent().flattenToShortString());
7681 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
7682 }
7683 }
7684 if (!app.persistent) {
7685 // We don't want to start this process again until the user
7686 // explicitly does so... but for persistent process, we really
7687 // need to keep it running. If a persistent process is actually
7688 // repeatedly crashing, then badness for everyone.
7689 EventLog.writeEvent(LOG_AM_PROCESS_BAD, app.info.uid,
7690 app.info.processName);
7691 mBadProcesses.put(app.info.processName, app.info.uid, now);
7692 app.bad = true;
7693 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
7694 app.removed = true;
7695 removeProcessLocked(app, false);
7696 return false;
7697 }
7698 }
7699
7700 // Bump up the crash count of any services currently running in the proc.
7701 if (app.services.size() != 0) {
7702 // Any services running in the application need to be placed
7703 // back in the pending list.
7704 Iterator it = app.services.iterator();
7705 while (it.hasNext()) {
7706 ServiceRecord sr = (ServiceRecord)it.next();
7707 sr.crashCount++;
7708 }
7709 }
7710
7711 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
7712 return true;
7713 }
7714
7715 void startAppProblemLocked(ProcessRecord app) {
7716 skipCurrentReceiverLocked(app);
7717 }
7718
7719 void skipCurrentReceiverLocked(ProcessRecord app) {
7720 boolean reschedule = false;
7721 BroadcastRecord r = app.curReceiver;
7722 if (r != null) {
7723 // The current broadcast is waiting for this app's receiver
7724 // to be finished. Looks like that's not going to happen, so
7725 // let the broadcast continue.
7726 logBroadcastReceiverDiscard(r);
7727 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
7728 r.resultExtras, r.resultAbort, true);
7729 reschedule = true;
7730 }
7731 r = mPendingBroadcast;
7732 if (r != null && r.curApp == app) {
7733 if (DEBUG_BROADCAST) Log.v(TAG,
7734 "skip & discard pending app " + r);
7735 logBroadcastReceiverDiscard(r);
7736 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
7737 r.resultExtras, r.resultAbort, true);
7738 reschedule = true;
7739 }
7740 if (reschedule) {
7741 scheduleBroadcastsLocked();
7742 }
7743 }
7744
7745 public int handleApplicationError(IBinder app, int flags,
7746 String tag, String shortMsg, String longMsg, byte[] crashData) {
7747 AppErrorResult result = new AppErrorResult();
7748
7749 ProcessRecord r = null;
7750 synchronized (this) {
7751 if (app != null) {
7752 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7753 final int NA = apps.size();
7754 for (int ia=0; ia<NA; ia++) {
7755 ProcessRecord p = apps.valueAt(ia);
7756 if (p.thread != null && p.thread.asBinder() == app) {
7757 r = p;
7758 break;
7759 }
7760 }
7761 }
7762 }
7763
7764 if (r != null) {
7765 // The application has crashed. Send the SIGQUIT to the process so
7766 // that it can dump its state.
7767 Process.sendSignal(r.pid, Process.SIGNAL_QUIT);
7768 //Log.i(TAG, "Current system threads:");
7769 //Process.sendSignal(MY_PID, Process.SIGNAL_QUIT);
7770 }
7771
7772 if (mWatcher != null) {
7773 try {
7774 String name = r != null ? r.processName : null;
7775 int pid = r != null ? r.pid : Binder.getCallingPid();
7776 if (!mWatcher.appCrashed(name, pid,
7777 shortMsg, longMsg, crashData)) {
7778 Log.w(TAG, "Force-killing crashed app " + name
7779 + " at watcher's request");
7780 Process.killProcess(pid);
7781 return 0;
7782 }
7783 } catch (RemoteException e) {
7784 mWatcher = null;
7785 }
7786 }
7787
7788 final long origId = Binder.clearCallingIdentity();
7789
7790 // If this process is running instrumentation, finish it.
7791 if (r != null && r.instrumentationClass != null) {
7792 Log.w(TAG, "Error in app " + r.processName
7793 + " running instrumentation " + r.instrumentationClass + ":");
7794 if (shortMsg != null) Log.w(TAG, " " + shortMsg);
7795 if (longMsg != null) Log.w(TAG, " " + longMsg);
7796 Bundle info = new Bundle();
7797 info.putString("shortMsg", shortMsg);
7798 info.putString("longMsg", longMsg);
7799 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7800 Binder.restoreCallingIdentity(origId);
7801 return 0;
7802 }
7803
7804 if (r != null) {
7805 if (!makeAppCrashingLocked(r, tag, shortMsg, longMsg, crashData)) {
7806 return 0;
7807 }
7808 } else {
7809 Log.w(TAG, "Some application object " + app + " tag " + tag
7810 + " has crashed, but I don't know who it is.");
7811 Log.w(TAG, "ShortMsg:" + shortMsg);
7812 Log.w(TAG, "LongMsg:" + longMsg);
7813 Binder.restoreCallingIdentity(origId);
7814 return 0;
7815 }
7816
7817 Message msg = Message.obtain();
7818 msg.what = SHOW_ERROR_MSG;
7819 HashMap data = new HashMap();
7820 data.put("result", result);
7821 data.put("app", r);
7822 data.put("flags", flags);
7823 data.put("shortMsg", shortMsg);
7824 data.put("longMsg", longMsg);
7825 if (r != null && (r.info.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7826 // For system processes, submit crash data to the server.
7827 data.put("crashData", crashData);
7828 }
7829 msg.obj = data;
7830 mHandler.sendMessage(msg);
7831
7832 Binder.restoreCallingIdentity(origId);
7833 }
7834
7835 int res = result.get();
7836
7837 synchronized (this) {
7838 if (r != null) {
7839 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7840 SystemClock.uptimeMillis());
7841 }
7842 }
7843
7844 return res;
7845 }
7846
7847 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7848 // assume our apps are happy - lazy create the list
7849 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7850
7851 synchronized (this) {
7852
7853 // iterate across all processes
7854 final int N = mLRUProcesses.size();
7855 for (int i = 0; i < N; i++) {
7856 ProcessRecord app = mLRUProcesses.get(i);
7857 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7858 // This one's in trouble, so we'll generate a report for it
7859 // crashes are higher priority (in case there's a crash *and* an anr)
7860 ActivityManager.ProcessErrorStateInfo report = null;
7861 if (app.crashing) {
7862 report = app.crashingReport;
7863 } else if (app.notResponding) {
7864 report = app.notRespondingReport;
7865 }
7866
7867 if (report != null) {
7868 if (errList == null) {
7869 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7870 }
7871 errList.add(report);
7872 } else {
7873 Log.w(TAG, "Missing app error report, app = " + app.processName +
7874 " crashing = " + app.crashing +
7875 " notResponding = " + app.notResponding);
7876 }
7877 }
7878 }
7879 }
7880
7881 return errList;
7882 }
7883
7884 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7885 // Lazy instantiation of list
7886 List<ActivityManager.RunningAppProcessInfo> runList = null;
7887 synchronized (this) {
7888 // Iterate across all processes
7889 final int N = mLRUProcesses.size();
7890 for (int i = 0; i < N; i++) {
7891 ProcessRecord app = mLRUProcesses.get(i);
7892 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7893 // Generate process state info for running application
7894 ActivityManager.RunningAppProcessInfo currApp =
7895 new ActivityManager.RunningAppProcessInfo(app.processName,
7896 app.pid, app.getPackageList());
7897 int adj = app.curAdj;
7898 if (adj >= CONTENT_PROVIDER_ADJ) {
7899 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7900 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7901 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007902 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7903 } else if (adj >= HOME_APP_ADJ) {
7904 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7905 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007906 } else if (adj >= SECONDARY_SERVER_ADJ) {
7907 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
7908 } else if (adj >= VISIBLE_APP_ADJ) {
7909 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7910 } else {
7911 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7912 }
7913 //Log.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
7914 // + " lru=" + currApp.lru);
7915 if (runList == null) {
7916 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7917 }
7918 runList.add(currApp);
7919 }
7920 }
7921 }
7922 return runList;
7923 }
7924
7925 @Override
7926 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
7927 synchronized (this) {
7928 if (checkCallingPermission(android.Manifest.permission.DUMP)
7929 != PackageManager.PERMISSION_GRANTED) {
7930 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7931 + Binder.getCallingPid()
7932 + ", uid=" + Binder.getCallingUid()
7933 + " without permission "
7934 + android.Manifest.permission.DUMP);
7935 return;
7936 }
7937 if (args.length != 0 && "service".equals(args[0])) {
7938 dumpService(fd, pw, args);
7939 return;
7940 }
7941 pw.println("Activities in Current Activity Manager State:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007942 dumpHistoryList(pw, mHistory, " ", "Hist", true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007943 pw.println(" ");
7944 pw.println(" Running activities (most recent first):");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007945 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946 if (mWaitingVisibleActivities.size() > 0) {
7947 pw.println(" ");
7948 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007949 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007950 }
7951 if (mStoppingActivities.size() > 0) {
7952 pw.println(" ");
7953 pw.println(" Activities waiting to stop:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007954 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955 }
7956 if (mFinishingActivities.size() > 0) {
7957 pw.println(" ");
7958 pw.println(" Activities waiting to finish:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007959 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007960 }
7961
7962 pw.println(" ");
7963 pw.println(" mPausingActivity: " + mPausingActivity);
7964 pw.println(" mResumedActivity: " + mResumedActivity);
7965 pw.println(" mFocusedActivity: " + mFocusedActivity);
7966 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
7967
7968 if (mRecentTasks.size() > 0) {
7969 pw.println(" ");
7970 pw.println("Recent tasks in Current Activity Manager State:");
7971
7972 final int N = mRecentTasks.size();
7973 for (int i=0; i<N; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007974 TaskRecord tr = mRecentTasks.get(i);
7975 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7976 pw.println(tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007977 mRecentTasks.get(i).dump(pw, " ");
7978 }
7979 }
7980
7981 pw.println(" ");
7982 pw.println(" mCurTask: " + mCurTask);
7983
7984 pw.println(" ");
7985 pw.println("Processes in Current Activity Manager State:");
7986
7987 boolean needSep = false;
7988 int numPers = 0;
7989
7990 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7991 final int NA = procs.size();
7992 for (int ia=0; ia<NA; ia++) {
7993 if (!needSep) {
7994 pw.println(" All known processes:");
7995 needSep = true;
7996 }
7997 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007998 pw.print(r.persistent ? " *PERS*" : " *APP*");
7999 pw.print(" UID "); pw.print(procs.keyAt(ia));
8000 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008001 r.dump(pw, " ");
8002 if (r.persistent) {
8003 numPers++;
8004 }
8005 }
8006 }
8007
8008 if (mLRUProcesses.size() > 0) {
8009 if (needSep) pw.println(" ");
8010 needSep = true;
8011 pw.println(" Running processes (most recent first):");
8012 dumpProcessList(pw, mLRUProcesses, " ",
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008013 "App ", "PERS", true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008014 needSep = true;
8015 }
8016
8017 synchronized (mPidsSelfLocked) {
8018 if (mPidsSelfLocked.size() > 0) {
8019 if (needSep) pw.println(" ");
8020 needSep = true;
8021 pw.println(" PID mappings:");
8022 for (int i=0; i<mPidsSelfLocked.size(); i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008023 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
8024 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008025 }
8026 }
8027 }
8028
8029 if (mForegroundProcesses.size() > 0) {
8030 if (needSep) pw.println(" ");
8031 needSep = true;
8032 pw.println(" Foreground Processes:");
8033 for (int i=0; i<mForegroundProcesses.size(); i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008034 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
8035 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008036 }
8037 }
8038
8039 if (mPersistentStartingProcesses.size() > 0) {
8040 if (needSep) pw.println(" ");
8041 needSep = true;
8042 pw.println(" Persisent processes that are starting:");
8043 dumpProcessList(pw, mPersistentStartingProcesses, " ",
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008044 "Starting Norm", "Restarting PERS", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045 }
8046
8047 if (mStartingProcesses.size() > 0) {
8048 if (needSep) pw.println(" ");
8049 needSep = true;
8050 pw.println(" Processes that are starting:");
8051 dumpProcessList(pw, mStartingProcesses, " ",
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008052 "Starting Norm", "Starting PERS", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008053 }
8054
8055 if (mRemovedProcesses.size() > 0) {
8056 if (needSep) pw.println(" ");
8057 needSep = true;
8058 pw.println(" Processes that are being removed:");
8059 dumpProcessList(pw, mRemovedProcesses, " ",
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008060 "Removed Norm", "Removed PERS", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008061 }
8062
8063 if (mProcessesOnHold.size() > 0) {
8064 if (needSep) pw.println(" ");
8065 needSep = true;
8066 pw.println(" Processes that are on old until the system is ready:");
8067 dumpProcessList(pw, mProcessesOnHold, " ",
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008068 "OnHold Norm", "OnHold PERS", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 }
8070
8071 if (mProcessCrashTimes.getMap().size() > 0) {
8072 if (needSep) pw.println(" ");
8073 needSep = true;
8074 pw.println(" Time since processes crashed:");
8075 long now = SystemClock.uptimeMillis();
8076 for (Map.Entry<String, SparseArray<Long>> procs
8077 : mProcessCrashTimes.getMap().entrySet()) {
8078 SparseArray<Long> uids = procs.getValue();
8079 final int N = uids.size();
8080 for (int i=0; i<N; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008081 pw.print(" Process "); pw.print(procs.getKey());
8082 pw.print(" uid "); pw.print(uids.keyAt(i));
8083 pw.print(": last crashed ");
8084 pw.print((now-uids.valueAt(i)));
8085 pw.println(" ms ago");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008086 }
8087 }
8088 }
8089
8090 if (mBadProcesses.getMap().size() > 0) {
8091 if (needSep) pw.println(" ");
8092 needSep = true;
8093 pw.println(" Bad processes:");
8094 for (Map.Entry<String, SparseArray<Long>> procs
8095 : mBadProcesses.getMap().entrySet()) {
8096 SparseArray<Long> uids = procs.getValue();
8097 final int N = uids.size();
8098 for (int i=0; i<N; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008099 pw.print(" Bad process "); pw.print(procs.getKey());
8100 pw.print(" uid "); pw.print(uids.keyAt(i));
8101 pw.print(": crashed at time ");
8102 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008103 }
8104 }
8105 }
8106
8107 pw.println(" ");
8108 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project4df24232009-03-05 14:34:35 -08008109 pw.println(" mHomeProcess: " + mHomeProcess);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008110 pw.println(" mConfiguration: " + mConfiguration);
8111 pw.println(" mStartRunning=" + mStartRunning
8112 + " mSystemReady=" + mSystemReady
8113 + " mBooting=" + mBooting
8114 + " mBooted=" + mBooted
8115 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn55280a92009-05-07 15:53:46 -07008116 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008117 pw.println(" mGoingToSleep=" + mGoingToSleep);
8118 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
8119 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
8120 + " mDebugTransient=" + mDebugTransient
8121 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
8122 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
8123 + " mWatcher=" + mWatcher);
8124 }
8125 }
8126
8127 /**
8128 * There are three ways to call this:
8129 * - no service specified: dump all the services
8130 * - a flattened component name that matched an existing service was specified as the
8131 * first arg: dump that one service
8132 * - the first arg isn't the flattened component name of an existing service:
8133 * dump all services whose component contains the first arg as a substring
8134 */
8135 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args) {
8136 String[] newArgs;
8137 String componentNameString;
8138 ServiceRecord r;
8139 if (args.length == 1) {
8140 componentNameString = null;
8141 newArgs = EMPTY_STRING_ARRAY;
8142 r = null;
8143 } else {
8144 componentNameString = args[1];
8145 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
8146 r = componentName != null ? mServices.get(componentName) : null;
8147 newArgs = new String[args.length - 2];
8148 if (args.length > 2) System.arraycopy(args, 2, newArgs, 0, args.length - 2);
8149 }
8150
8151 if (r != null) {
8152 dumpService(fd, pw, r, newArgs);
8153 } else {
8154 for (ServiceRecord r1 : mServices.values()) {
8155 if (componentNameString == null
8156 || r1.name.flattenToString().contains(componentNameString)) {
8157 dumpService(fd, pw, r1, newArgs);
8158 }
8159 }
8160 }
8161 }
8162
8163 /**
8164 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8165 * there is a thread associated with the service.
8166 */
8167 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
8168 pw.println(" Service " + r.name.flattenToString());
8169 if (r.app != null && r.app.thread != null) {
8170 try {
8171 // flush anything that is already in the PrintWriter since the thread is going
8172 // to write to the file descriptor directly
8173 pw.flush();
8174 r.app.thread.dumpService(fd, r, args);
8175 pw.print("\n");
8176 } catch (RemoteException e) {
8177 pw.println("got a RemoteException while dumping the service");
8178 }
8179 }
8180 }
8181
8182 void dumpBroadcasts(PrintWriter pw) {
8183 synchronized (this) {
8184 if (checkCallingPermission(android.Manifest.permission.DUMP)
8185 != PackageManager.PERMISSION_GRANTED) {
8186 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8187 + Binder.getCallingPid()
8188 + ", uid=" + Binder.getCallingUid()
8189 + " without permission "
8190 + android.Manifest.permission.DUMP);
8191 return;
8192 }
8193 pw.println("Broadcasts in Current Activity Manager State:");
8194
8195 if (mRegisteredReceivers.size() > 0) {
8196 pw.println(" ");
8197 pw.println(" Registered Receivers:");
8198 Iterator it = mRegisteredReceivers.values().iterator();
8199 while (it.hasNext()) {
8200 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008201 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008202 r.dump(pw, " ");
8203 }
8204 }
8205
8206 pw.println(" ");
8207 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008208 mReceiverResolver.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008209
8210 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8211 || mPendingBroadcast != null) {
8212 if (mParallelBroadcasts.size() > 0) {
8213 pw.println(" ");
8214 pw.println(" Active broadcasts:");
8215 }
8216 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8217 pw.println(" Broadcast #" + i + ":");
8218 mParallelBroadcasts.get(i).dump(pw, " ");
8219 }
8220 if (mOrderedBroadcasts.size() > 0) {
8221 pw.println(" ");
8222 pw.println(" Active serialized broadcasts:");
8223 }
8224 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8225 pw.println(" Serialized Broadcast #" + i + ":");
8226 mOrderedBroadcasts.get(i).dump(pw, " ");
8227 }
8228 pw.println(" ");
8229 pw.println(" Pending broadcast:");
8230 if (mPendingBroadcast != null) {
8231 mPendingBroadcast.dump(pw, " ");
8232 } else {
8233 pw.println(" (null)");
8234 }
8235 }
8236
8237 pw.println(" ");
8238 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
8239 if (mStickyBroadcasts != null) {
8240 pw.println(" ");
8241 pw.println(" Sticky broadcasts:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008242 StringBuilder sb = new StringBuilder(128);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008243 for (Map.Entry<String, ArrayList<Intent>> ent
8244 : mStickyBroadcasts.entrySet()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008245 pw.print(" * Sticky action "); pw.print(ent.getKey());
8246 pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008247 ArrayList<Intent> intents = ent.getValue();
8248 final int N = intents.size();
8249 for (int i=0; i<N; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008250 sb.setLength(0);
8251 sb.append(" Intent: ");
8252 intents.get(i).toShortString(sb, true, false);
8253 pw.println(sb.toString());
8254 Bundle bundle = intents.get(i).getExtras();
8255 if (bundle != null) {
8256 pw.print(" ");
8257 pw.println(bundle.toString());
8258 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008259 }
8260 }
8261 }
8262
8263 pw.println(" ");
8264 pw.println(" mHandler:");
8265 mHandler.dump(new PrintWriterPrinter(pw), " ");
8266 }
8267 }
8268
8269 void dumpServices(PrintWriter pw) {
8270 synchronized (this) {
8271 if (checkCallingPermission(android.Manifest.permission.DUMP)
8272 != PackageManager.PERMISSION_GRANTED) {
8273 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8274 + Binder.getCallingPid()
8275 + ", uid=" + Binder.getCallingUid()
8276 + " without permission "
8277 + android.Manifest.permission.DUMP);
8278 return;
8279 }
8280 pw.println("Services in Current Activity Manager State:");
8281
8282 boolean needSep = false;
8283
8284 if (mServices.size() > 0) {
8285 pw.println(" Active services:");
8286 Iterator<ServiceRecord> it = mServices.values().iterator();
8287 while (it.hasNext()) {
8288 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008289 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008290 r.dump(pw, " ");
8291 }
8292 needSep = true;
8293 }
8294
8295 if (mPendingServices.size() > 0) {
8296 if (needSep) pw.println(" ");
8297 pw.println(" Pending services:");
8298 for (int i=0; i<mPendingServices.size(); i++) {
8299 ServiceRecord r = mPendingServices.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008300 pw.print(" * Pending "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008301 r.dump(pw, " ");
8302 }
8303 needSep = true;
8304 }
8305
8306 if (mRestartingServices.size() > 0) {
8307 if (needSep) pw.println(" ");
8308 pw.println(" Restarting services:");
8309 for (int i=0; i<mRestartingServices.size(); i++) {
8310 ServiceRecord r = mRestartingServices.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008311 pw.print(" * Restarting "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008312 r.dump(pw, " ");
8313 }
8314 needSep = true;
8315 }
8316
8317 if (mStoppingServices.size() > 0) {
8318 if (needSep) pw.println(" ");
8319 pw.println(" Stopping services:");
8320 for (int i=0; i<mStoppingServices.size(); i++) {
8321 ServiceRecord r = mStoppingServices.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008322 pw.print(" * Stopping "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008323 r.dump(pw, " ");
8324 }
8325 needSep = true;
8326 }
8327
8328 if (mServiceConnections.size() > 0) {
8329 if (needSep) pw.println(" ");
8330 pw.println(" Connection bindings to services:");
8331 Iterator<ConnectionRecord> it
8332 = mServiceConnections.values().iterator();
8333 while (it.hasNext()) {
8334 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008335 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008336 r.dump(pw, " ");
8337 }
8338 }
8339 }
8340 }
8341
8342 void dumpProviders(PrintWriter pw) {
8343 synchronized (this) {
8344 if (checkCallingPermission(android.Manifest.permission.DUMP)
8345 != PackageManager.PERMISSION_GRANTED) {
8346 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8347 + Binder.getCallingPid()
8348 + ", uid=" + Binder.getCallingUid()
8349 + " without permission "
8350 + android.Manifest.permission.DUMP);
8351 return;
8352 }
8353
8354 pw.println("Content Providers in Current Activity Manager State:");
8355
8356 boolean needSep = false;
8357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008358 if (mProvidersByClass.size() > 0) {
8359 if (needSep) pw.println(" ");
8360 pw.println(" Published content providers (by class):");
8361 Iterator it = mProvidersByClass.entrySet().iterator();
8362 while (it.hasNext()) {
8363 Map.Entry e = (Map.Entry)it.next();
8364 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008365 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008366 r.dump(pw, " ");
8367 }
8368 needSep = true;
8369 }
8370
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008371 if (mProvidersByName.size() > 0) {
8372 pw.println(" ");
8373 pw.println(" Authority to provider mappings:");
8374 Iterator it = mProvidersByName.entrySet().iterator();
8375 while (it.hasNext()) {
8376 Map.Entry e = (Map.Entry)it.next();
8377 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
8378 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8379 pw.println(r);
8380 }
8381 needSep = true;
8382 }
8383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008384 if (mLaunchingProviders.size() > 0) {
8385 if (needSep) pw.println(" ");
8386 pw.println(" Launching content providers:");
8387 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008388 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8389 pw.println(mLaunchingProviders.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008390 }
8391 needSep = true;
8392 }
8393
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008394 if (mGrantedUriPermissions.size() > 0) {
8395 pw.println();
8396 pw.println("Granted Uri Permissions:");
8397 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8398 int uid = mGrantedUriPermissions.keyAt(i);
8399 HashMap<Uri, UriPermission> perms
8400 = mGrantedUriPermissions.valueAt(i);
8401 pw.print(" * UID "); pw.print(uid);
8402 pw.println(" holds:");
8403 for (UriPermission perm : perms.values()) {
8404 pw.print(" "); pw.println(perm);
8405 perm.dump(pw, " ");
8406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008407 }
8408 }
8409 }
8410 }
8411
8412 void dumpSenders(PrintWriter pw) {
8413 synchronized (this) {
8414 if (checkCallingPermission(android.Manifest.permission.DUMP)
8415 != PackageManager.PERMISSION_GRANTED) {
8416 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8417 + Binder.getCallingPid()
8418 + ", uid=" + Binder.getCallingUid()
8419 + " without permission "
8420 + android.Manifest.permission.DUMP);
8421 return;
8422 }
8423
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008424 pw.println("Pending Intents in Current Activity Manager State:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425
8426 if (this.mIntentSenderRecords.size() > 0) {
8427 Iterator<WeakReference<PendingIntentRecord>> it
8428 = mIntentSenderRecords.values().iterator();
8429 while (it.hasNext()) {
8430 WeakReference<PendingIntentRecord> ref = it.next();
8431 PendingIntentRecord rec = ref != null ? ref.get(): null;
8432 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008433 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008434 rec.dump(pw, " ");
8435 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008436 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008437 }
8438 }
8439 }
8440 }
8441 }
8442
8443 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008444 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008445 TaskRecord lastTask = null;
8446 for (int i=list.size()-1; i>=0; i--) {
8447 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008448 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008449 if (lastTask != r.task) {
8450 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008451 pw.print(prefix);
8452 pw.print(full ? "* " : " ");
8453 pw.println(lastTask);
8454 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008455 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008457 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008458 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8459 pw.print(" #"); pw.print(i); pw.print(": ");
8460 pw.println(r);
8461 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008462 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008463 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008464 }
8465 }
8466
8467 private static final int dumpProcessList(PrintWriter pw, List list,
8468 String prefix, String normalLabel, String persistentLabel,
8469 boolean inclOomAdj) {
8470 int numPers = 0;
8471 for (int i=list.size()-1; i>=0; i--) {
8472 ProcessRecord r = (ProcessRecord)list.get(i);
8473 if (false) {
8474 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
8475 + " #" + i + ":");
8476 r.dump(pw, prefix + " ");
8477 } else if (inclOomAdj) {
8478 pw.println(String.format("%s%s #%2d: oom_adj=%3d %s",
8479 prefix, (r.persistent ? persistentLabel : normalLabel),
8480 i, r.setAdj, r.toString()));
8481 } else {
8482 pw.println(String.format("%s%s #%2d: %s",
8483 prefix, (r.persistent ? persistentLabel : normalLabel),
8484 i, r.toString()));
8485 }
8486 if (r.persistent) {
8487 numPers++;
8488 }
8489 }
8490 return numPers;
8491 }
8492
8493 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
8494 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008495 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008496 long uptime = SystemClock.uptimeMillis();
8497 long realtime = SystemClock.elapsedRealtime();
8498
8499 if (isCheckinRequest) {
8500 // short checkin version
8501 pw.println(uptime + "," + realtime);
8502 pw.flush();
8503 } else {
8504 pw.println("Applications Memory Usage (kB):");
8505 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8506 }
8507 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8508 ProcessRecord r = (ProcessRecord)list.get(i);
8509 if (r.thread != null) {
8510 if (!isCheckinRequest) {
8511 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8512 pw.flush();
8513 }
8514 try {
8515 r.thread.asBinder().dump(fd, args);
8516 } catch (RemoteException e) {
8517 if (!isCheckinRequest) {
8518 pw.println("Got RemoteException!");
8519 pw.flush();
8520 }
8521 }
8522 }
8523 }
8524 }
8525
8526 /**
8527 * Searches array of arguments for the specified string
8528 * @param args array of argument strings
8529 * @param value value to search for
8530 * @return true if the value is contained in the array
8531 */
8532 private static boolean scanArgs(String[] args, String value) {
8533 if (args != null) {
8534 for (String arg : args) {
8535 if (value.equals(arg)) {
8536 return true;
8537 }
8538 }
8539 }
8540 return false;
8541 }
8542
8543 private final int indexOfTokenLocked(IBinder token, boolean required) {
8544 int count = mHistory.size();
8545
8546 // convert the token to an entry in the history.
8547 HistoryRecord r = null;
8548 int index = -1;
8549 for (int i=count-1; i>=0; i--) {
8550 Object o = mHistory.get(i);
8551 if (o == token) {
8552 r = (HistoryRecord)o;
8553 index = i;
8554 break;
8555 }
8556 }
8557 if (index < 0 && required) {
8558 RuntimeInit.crash(TAG, new InvalidTokenException(token));
8559 }
8560
8561 return index;
8562 }
8563
8564 static class InvalidTokenException extends Exception {
8565 InvalidTokenException(IBinder token) {
8566 super("Bad activity token: " + token);
8567 }
8568 }
8569
8570 private final void killServicesLocked(ProcessRecord app,
8571 boolean allowRestart) {
8572 // Report disconnected services.
8573 if (false) {
8574 // XXX we are letting the client link to the service for
8575 // death notifications.
8576 if (app.services.size() > 0) {
8577 Iterator it = app.services.iterator();
8578 while (it.hasNext()) {
8579 ServiceRecord r = (ServiceRecord)it.next();
8580 if (r.connections.size() > 0) {
8581 Iterator<ConnectionRecord> jt
8582 = r.connections.values().iterator();
8583 while (jt.hasNext()) {
8584 ConnectionRecord c = jt.next();
8585 if (c.binding.client != app) {
8586 try {
8587 //c.conn.connected(r.className, null);
8588 } catch (Exception e) {
8589 // todo: this should be asynchronous!
8590 Log.w(TAG, "Exception thrown disconnected servce "
8591 + r.shortName
8592 + " from app " + app.processName, e);
8593 }
8594 }
8595 }
8596 }
8597 }
8598 }
8599 }
8600
8601 // Clean up any connections this application has to other services.
8602 if (app.connections.size() > 0) {
8603 Iterator<ConnectionRecord> it = app.connections.iterator();
8604 while (it.hasNext()) {
8605 ConnectionRecord r = it.next();
8606 removeConnectionLocked(r, app, null);
8607 }
8608 }
8609 app.connections.clear();
8610
8611 if (app.services.size() != 0) {
8612 // Any services running in the application need to be placed
8613 // back in the pending list.
8614 Iterator it = app.services.iterator();
8615 while (it.hasNext()) {
8616 ServiceRecord sr = (ServiceRecord)it.next();
8617 synchronized (sr.stats.getBatteryStats()) {
8618 sr.stats.stopLaunchedLocked();
8619 }
8620 sr.app = null;
8621 sr.executeNesting = 0;
8622 mStoppingServices.remove(sr);
8623 if (sr.bindings.size() > 0) {
8624 Iterator<IntentBindRecord> bindings
8625 = sr.bindings.values().iterator();
8626 while (bindings.hasNext()) {
8627 IntentBindRecord b = bindings.next();
8628 if (DEBUG_SERVICE) Log.v(TAG, "Killing binding " + b
8629 + ": shouldUnbind=" + b.hasBound);
8630 b.binder = null;
8631 b.requested = b.received = b.hasBound = false;
8632 }
8633 }
8634
8635 if (sr.crashCount >= 2) {
8636 Log.w(TAG, "Service crashed " + sr.crashCount
8637 + " times, stopping: " + sr);
8638 EventLog.writeEvent(LOG_AM_SERVICE_CRASHED_TOO_MUCH,
8639 sr.crashCount, sr.shortName, app.pid);
8640 bringDownServiceLocked(sr, true);
8641 } else if (!allowRestart) {
8642 bringDownServiceLocked(sr, true);
8643 } else {
8644 scheduleServiceRestartLocked(sr);
8645 }
8646 }
8647
8648 if (!allowRestart) {
8649 app.services.clear();
8650 }
8651 }
8652
8653 app.executingServices.clear();
8654 }
8655
8656 private final void removeDyingProviderLocked(ProcessRecord proc,
8657 ContentProviderRecord cpr) {
8658 synchronized (cpr) {
8659 cpr.launchingApp = null;
8660 cpr.notifyAll();
8661 }
8662
8663 mProvidersByClass.remove(cpr.info.name);
8664 String names[] = cpr.info.authority.split(";");
8665 for (int j = 0; j < names.length; j++) {
8666 mProvidersByName.remove(names[j]);
8667 }
8668
8669 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8670 while (cit.hasNext()) {
8671 ProcessRecord capp = cit.next();
8672 if (!capp.persistent && capp.thread != null
8673 && capp.pid != 0
8674 && capp.pid != MY_PID) {
8675 Log.i(TAG, "Killing app " + capp.processName
8676 + " (pid " + capp.pid
8677 + ") because provider " + cpr.info.name
8678 + " is in dying process " + proc.processName);
8679 Process.killProcess(capp.pid);
8680 }
8681 }
8682
8683 mLaunchingProviders.remove(cpr);
8684 }
8685
8686 /**
8687 * Main code for cleaning up a process when it has gone away. This is
8688 * called both as a result of the process dying, or directly when stopping
8689 * a process when running in single process mode.
8690 */
8691 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8692 boolean restarting, int index) {
8693 if (index >= 0) {
8694 mLRUProcesses.remove(index);
8695 }
8696
8697 // Dismiss any open dialogs.
8698 if (app.crashDialog != null) {
8699 app.crashDialog.dismiss();
8700 app.crashDialog = null;
8701 }
8702 if (app.anrDialog != null) {
8703 app.anrDialog.dismiss();
8704 app.anrDialog = null;
8705 }
8706 if (app.waitDialog != null) {
8707 app.waitDialog.dismiss();
8708 app.waitDialog = null;
8709 }
8710
8711 app.crashing = false;
8712 app.notResponding = false;
8713
8714 app.resetPackageList();
8715 app.thread = null;
8716 app.forcingToForeground = null;
8717 app.foregroundServices = false;
8718
8719 killServicesLocked(app, true);
8720
8721 boolean restart = false;
8722
8723 int NL = mLaunchingProviders.size();
8724
8725 // Remove published content providers.
8726 if (!app.pubProviders.isEmpty()) {
8727 Iterator it = app.pubProviders.values().iterator();
8728 while (it.hasNext()) {
8729 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8730 cpr.provider = null;
8731 cpr.app = null;
8732
8733 // See if someone is waiting for this provider... in which
8734 // case we don't remove it, but just let it restart.
8735 int i = 0;
8736 if (!app.bad) {
8737 for (; i<NL; i++) {
8738 if (mLaunchingProviders.get(i) == cpr) {
8739 restart = true;
8740 break;
8741 }
8742 }
8743 } else {
8744 i = NL;
8745 }
8746
8747 if (i >= NL) {
8748 removeDyingProviderLocked(app, cpr);
8749 NL = mLaunchingProviders.size();
8750 }
8751 }
8752 app.pubProviders.clear();
8753 }
8754
8755 // Look through the content providers we are waiting to have launched,
8756 // and if any run in this process then either schedule a restart of
8757 // the process or kill the client waiting for it if this process has
8758 // gone bad.
8759 for (int i=0; i<NL; i++) {
8760 ContentProviderRecord cpr = (ContentProviderRecord)
8761 mLaunchingProviders.get(i);
8762 if (cpr.launchingApp == app) {
8763 if (!app.bad) {
8764 restart = true;
8765 } else {
8766 removeDyingProviderLocked(app, cpr);
8767 NL = mLaunchingProviders.size();
8768 }
8769 }
8770 }
8771
8772 // Unregister from connected content providers.
8773 if (!app.conProviders.isEmpty()) {
8774 Iterator it = app.conProviders.iterator();
8775 while (it.hasNext()) {
8776 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8777 cpr.clients.remove(app);
8778 }
8779 app.conProviders.clear();
8780 }
8781
8782 skipCurrentReceiverLocked(app);
8783
8784 // Unregister any receivers.
8785 if (app.receivers.size() > 0) {
8786 Iterator<ReceiverList> it = app.receivers.iterator();
8787 while (it.hasNext()) {
8788 removeReceiverLocked(it.next());
8789 }
8790 app.receivers.clear();
8791 }
8792
8793 // If the caller is restarting this app, then leave it in its
8794 // current lists and let the caller take care of it.
8795 if (restarting) {
8796 return;
8797 }
8798
8799 if (!app.persistent) {
8800 if (DEBUG_PROCESSES) Log.v(TAG,
8801 "Removing non-persistent process during cleanup: " + app);
8802 mProcessNames.remove(app.processName, app.info.uid);
8803 } else if (!app.removed) {
8804 // This app is persistent, so we need to keep its record around.
8805 // If it is not already on the pending app list, add it there
8806 // and start a new process for it.
8807 app.thread = null;
8808 app.forcingToForeground = null;
8809 app.foregroundServices = false;
8810 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8811 mPersistentStartingProcesses.add(app);
8812 restart = true;
8813 }
8814 }
8815 mProcessesOnHold.remove(app);
8816
The Android Open Source Project4df24232009-03-05 14:34:35 -08008817 if (app == mHomeProcess) {
8818 mHomeProcess = null;
8819 }
8820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008821 if (restart) {
8822 // We have components that still need to be running in the
8823 // process, so re-launch it.
8824 mProcessNames.put(app.processName, app.info.uid, app);
8825 startProcessLocked(app, "restart", app.processName);
8826 } else if (app.pid > 0 && app.pid != MY_PID) {
8827 // Goodbye!
8828 synchronized (mPidsSelfLocked) {
8829 mPidsSelfLocked.remove(app.pid);
8830 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8831 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008832 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008833 }
8834 }
8835
8836 // =========================================================
8837 // SERVICES
8838 // =========================================================
8839
8840 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8841 ActivityManager.RunningServiceInfo info =
8842 new ActivityManager.RunningServiceInfo();
8843 info.service = r.name;
8844 if (r.app != null) {
8845 info.pid = r.app.pid;
8846 }
8847 info.process = r.processName;
8848 info.foreground = r.isForeground;
8849 info.activeSince = r.createTime;
8850 info.started = r.startRequested;
8851 info.clientCount = r.connections.size();
8852 info.crashCount = r.crashCount;
8853 info.lastActivityTime = r.lastActivity;
8854 return info;
8855 }
8856
8857 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8858 int flags) {
8859 synchronized (this) {
8860 ArrayList<ActivityManager.RunningServiceInfo> res
8861 = new ArrayList<ActivityManager.RunningServiceInfo>();
8862
8863 if (mServices.size() > 0) {
8864 Iterator<ServiceRecord> it = mServices.values().iterator();
8865 while (it.hasNext() && res.size() < maxNum) {
8866 res.add(makeRunningServiceInfoLocked(it.next()));
8867 }
8868 }
8869
8870 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8871 ServiceRecord r = mRestartingServices.get(i);
8872 ActivityManager.RunningServiceInfo info =
8873 makeRunningServiceInfoLocked(r);
8874 info.restarting = r.nextRestartTime;
8875 res.add(info);
8876 }
8877
8878 return res;
8879 }
8880 }
8881
8882 private final ServiceRecord findServiceLocked(ComponentName name,
8883 IBinder token) {
8884 ServiceRecord r = mServices.get(name);
8885 return r == token ? r : null;
8886 }
8887
8888 private final class ServiceLookupResult {
8889 final ServiceRecord record;
8890 final String permission;
8891
8892 ServiceLookupResult(ServiceRecord _record, String _permission) {
8893 record = _record;
8894 permission = _permission;
8895 }
8896 };
8897
8898 private ServiceLookupResult findServiceLocked(Intent service,
8899 String resolvedType) {
8900 ServiceRecord r = null;
8901 if (service.getComponent() != null) {
8902 r = mServices.get(service.getComponent());
8903 }
8904 if (r == null) {
8905 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8906 r = mServicesByIntent.get(filter);
8907 }
8908
8909 if (r == null) {
8910 try {
8911 ResolveInfo rInfo =
8912 ActivityThread.getPackageManager().resolveService(
8913 service, resolvedType, 0);
8914 ServiceInfo sInfo =
8915 rInfo != null ? rInfo.serviceInfo : null;
8916 if (sInfo == null) {
8917 return null;
8918 }
8919
8920 ComponentName name = new ComponentName(
8921 sInfo.applicationInfo.packageName, sInfo.name);
8922 r = mServices.get(name);
8923 } catch (RemoteException ex) {
8924 // pm is in same process, this will never happen.
8925 }
8926 }
8927 if (r != null) {
8928 int callingPid = Binder.getCallingPid();
8929 int callingUid = Binder.getCallingUid();
8930 if (checkComponentPermission(r.permission,
8931 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8932 != PackageManager.PERMISSION_GRANTED) {
8933 Log.w(TAG, "Permission Denial: Accessing service " + r.name
8934 + " from pid=" + callingPid
8935 + ", uid=" + callingUid
8936 + " requires " + r.permission);
8937 return new ServiceLookupResult(null, r.permission);
8938 }
8939 return new ServiceLookupResult(r, null);
8940 }
8941 return null;
8942 }
8943
8944 private class ServiceRestarter implements Runnable {
8945 private ServiceRecord mService;
8946
8947 void setService(ServiceRecord service) {
8948 mService = service;
8949 }
8950
8951 public void run() {
8952 synchronized(ActivityManagerService.this) {
8953 performServiceRestartLocked(mService);
8954 }
8955 }
8956 }
8957
8958 private ServiceLookupResult retrieveServiceLocked(Intent service,
8959 String resolvedType, int callingPid, int callingUid) {
8960 ServiceRecord r = null;
8961 if (service.getComponent() != null) {
8962 r = mServices.get(service.getComponent());
8963 }
8964 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8965 r = mServicesByIntent.get(filter);
8966 if (r == null) {
8967 try {
8968 ResolveInfo rInfo =
8969 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008970 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008971 ServiceInfo sInfo =
8972 rInfo != null ? rInfo.serviceInfo : null;
8973 if (sInfo == null) {
8974 Log.w(TAG, "Unable to start service " + service +
8975 ": not found");
8976 return null;
8977 }
8978
8979 ComponentName name = new ComponentName(
8980 sInfo.applicationInfo.packageName, sInfo.name);
8981 r = mServices.get(name);
8982 if (r == null) {
8983 filter = new Intent.FilterComparison(service.cloneFilter());
8984 ServiceRestarter res = new ServiceRestarter();
8985 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8986 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8987 synchronized (stats) {
8988 ss = stats.getServiceStatsLocked(
8989 sInfo.applicationInfo.uid, sInfo.packageName,
8990 sInfo.name);
8991 }
8992 r = new ServiceRecord(ss, name, filter, sInfo, res);
8993 res.setService(r);
8994 mServices.put(name, r);
8995 mServicesByIntent.put(filter, r);
8996
8997 // Make sure this component isn't in the pending list.
8998 int N = mPendingServices.size();
8999 for (int i=0; i<N; i++) {
9000 ServiceRecord pr = mPendingServices.get(i);
9001 if (pr.name.equals(name)) {
9002 mPendingServices.remove(i);
9003 i--;
9004 N--;
9005 }
9006 }
9007 }
9008 } catch (RemoteException ex) {
9009 // pm is in same process, this will never happen.
9010 }
9011 }
9012 if (r != null) {
9013 if (checkComponentPermission(r.permission,
9014 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
9015 != PackageManager.PERMISSION_GRANTED) {
9016 Log.w(TAG, "Permission Denial: Accessing service " + r.name
9017 + " from pid=" + Binder.getCallingPid()
9018 + ", uid=" + Binder.getCallingUid()
9019 + " requires " + r.permission);
9020 return new ServiceLookupResult(null, r.permission);
9021 }
9022 return new ServiceLookupResult(r, null);
9023 }
9024 return null;
9025 }
9026
9027 private final void bumpServiceExecutingLocked(ServiceRecord r) {
9028 long now = SystemClock.uptimeMillis();
9029 if (r.executeNesting == 0 && r.app != null) {
9030 if (r.app.executingServices.size() == 0) {
9031 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9032 msg.obj = r.app;
9033 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9034 }
9035 r.app.executingServices.add(r);
9036 }
9037 r.executeNesting++;
9038 r.executingStart = now;
9039 }
9040
9041 private final void sendServiceArgsLocked(ServiceRecord r,
9042 boolean oomAdjusted) {
9043 final int N = r.startArgs.size();
9044 if (N == 0) {
9045 return;
9046 }
9047
9048 final int BASEID = r.lastStartId - N + 1;
9049 int i = 0;
9050 while (i < N) {
9051 try {
9052 Intent args = r.startArgs.get(i);
9053 if (DEBUG_SERVICE) Log.v(TAG, "Sending arguments to service: "
9054 + r.name + " " + r.intent + " args=" + args);
9055 bumpServiceExecutingLocked(r);
9056 if (!oomAdjusted) {
9057 oomAdjusted = true;
9058 updateOomAdjLocked(r.app);
9059 }
9060 r.app.thread.scheduleServiceArgs(r, BASEID+i, args);
9061 i++;
9062 } catch (Exception e) {
9063 break;
9064 }
9065 }
9066 if (i == N) {
9067 r.startArgs.clear();
9068 } else {
9069 while (i > 0) {
9070 r.startArgs.remove(0);
9071 i--;
9072 }
9073 }
9074 }
9075
9076 private final boolean requestServiceBindingLocked(ServiceRecord r,
9077 IntentBindRecord i, boolean rebind) {
9078 if (r.app == null || r.app.thread == null) {
9079 // If service is not currently running, can't yet bind.
9080 return false;
9081 }
9082 if ((!i.requested || rebind) && i.apps.size() > 0) {
9083 try {
9084 bumpServiceExecutingLocked(r);
9085 if (DEBUG_SERVICE) Log.v(TAG, "Connecting binding " + i
9086 + ": shouldUnbind=" + i.hasBound);
9087 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9088 if (!rebind) {
9089 i.requested = true;
9090 }
9091 i.hasBound = true;
9092 i.doRebind = false;
9093 } catch (RemoteException e) {
9094 return false;
9095 }
9096 }
9097 return true;
9098 }
9099
9100 private final void requestServiceBindingsLocked(ServiceRecord r) {
9101 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9102 while (bindings.hasNext()) {
9103 IntentBindRecord i = bindings.next();
9104 if (!requestServiceBindingLocked(r, i, false)) {
9105 break;
9106 }
9107 }
9108 }
9109
9110 private final void realStartServiceLocked(ServiceRecord r,
9111 ProcessRecord app) throws RemoteException {
9112 if (app.thread == null) {
9113 throw new RemoteException();
9114 }
9115
9116 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009117 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009118
9119 app.services.add(r);
9120 bumpServiceExecutingLocked(r);
9121 updateLRUListLocked(app, true);
9122
9123 boolean created = false;
9124 try {
9125 if (DEBUG_SERVICE) Log.v(TAG, "Scheduling start service: "
9126 + r.name + " " + r.intent);
9127 EventLog.writeEvent(LOG_AM_CREATE_SERVICE,
9128 System.identityHashCode(r), r.shortName,
9129 r.intent.getIntent().toString(), r.app.pid);
9130 synchronized (r.stats.getBatteryStats()) {
9131 r.stats.startLaunchedLocked();
9132 }
9133 app.thread.scheduleCreateService(r, r.serviceInfo);
9134 created = true;
9135 } finally {
9136 if (!created) {
9137 app.services.remove(r);
9138 scheduleServiceRestartLocked(r);
9139 }
9140 }
9141
9142 requestServiceBindingsLocked(r);
9143 sendServiceArgsLocked(r, true);
9144 }
9145
9146 private final void scheduleServiceRestartLocked(ServiceRecord r) {
9147 r.totalRestartCount++;
9148 if (r.restartDelay == 0) {
9149 r.restartCount++;
9150 r.restartDelay = SERVICE_RESTART_DURATION;
9151 } else {
9152 // If it has been a "reasonably long time" since the service
9153 // was started, then reset our restart duration back to
9154 // the beginning, so we don't infinitely increase the duration
9155 // on a service that just occasionally gets killed (which is
9156 // a normal case, due to process being killed to reclaim memory).
9157 long now = SystemClock.uptimeMillis();
9158 if (now > (r.restartTime+(SERVICE_RESTART_DURATION*2*2*2))) {
9159 r.restartCount = 1;
9160 r.restartDelay = SERVICE_RESTART_DURATION;
9161 } else {
9162 r.restartDelay *= 2;
9163 }
9164 }
9165 if (!mRestartingServices.contains(r)) {
9166 mRestartingServices.add(r);
9167 }
9168 mHandler.removeCallbacks(r.restarter);
9169 mHandler.postDelayed(r.restarter, r.restartDelay);
9170 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
9171 Log.w(TAG, "Scheduling restart of crashed service "
9172 + r.shortName + " in " + r.restartDelay + "ms");
9173 EventLog.writeEvent(LOG_AM_SCHEDULE_SERVICE_RESTART,
9174 r.shortName, r.restartDelay);
9175
9176 Message msg = Message.obtain();
9177 msg.what = SERVICE_ERROR_MSG;
9178 msg.obj = r;
9179 mHandler.sendMessage(msg);
9180 }
9181
9182 final void performServiceRestartLocked(ServiceRecord r) {
9183 if (!mRestartingServices.contains(r)) {
9184 return;
9185 }
9186 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9187 }
9188
9189 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9190 if (r.restartDelay == 0) {
9191 return false;
9192 }
9193 r.resetRestartCounter();
9194 mRestartingServices.remove(r);
9195 mHandler.removeCallbacks(r.restarter);
9196 return true;
9197 }
9198
9199 private final boolean bringUpServiceLocked(ServiceRecord r,
9200 int intentFlags, boolean whileRestarting) {
9201 //Log.i(TAG, "Bring up service:");
9202 //r.dump(" ");
9203
9204 if (r.app != null) {
9205 sendServiceArgsLocked(r, false);
9206 return true;
9207 }
9208
9209 if (!whileRestarting && r.restartDelay > 0) {
9210 // If waiting for a restart, then do nothing.
9211 return true;
9212 }
9213
9214 if (DEBUG_SERVICE) Log.v(TAG, "Bringing up service " + r.name
9215 + " " + r.intent);
9216
9217 final String appName = r.processName;
9218 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9219 if (app != null && app.thread != null) {
9220 try {
9221 realStartServiceLocked(r, app);
9222 return true;
9223 } catch (RemoteException e) {
9224 Log.w(TAG, "Exception when starting service " + r.shortName, e);
9225 }
9226
9227 // If a dead object exception was thrown -- fall through to
9228 // restart the application.
9229 }
9230
9231 if (!mPendingServices.contains(r)) {
9232 // Not running -- get it started, and enqueue this service record
9233 // to be executed when the app comes up.
9234 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9235 "service", r.name) == null) {
9236 Log.w(TAG, "Unable to launch app "
9237 + r.appInfo.packageName + "/"
9238 + r.appInfo.uid + " for service "
9239 + r.intent.getIntent() + ": process is bad");
9240 bringDownServiceLocked(r, true);
9241 return false;
9242 }
9243 mPendingServices.add(r);
9244 }
9245 return true;
9246 }
9247
9248 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
9249 //Log.i(TAG, "Bring down service:");
9250 //r.dump(" ");
9251
9252 // Does it still need to run?
9253 if (!force && r.startRequested) {
9254 return;
9255 }
9256 if (r.connections.size() > 0) {
9257 if (!force) {
9258 // XXX should probably keep a count of the number of auto-create
9259 // connections directly in the service.
9260 Iterator<ConnectionRecord> it = r.connections.values().iterator();
9261 while (it.hasNext()) {
9262 ConnectionRecord cr = it.next();
9263 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
9264 return;
9265 }
9266 }
9267 }
9268
9269 // Report to all of the connections that the service is no longer
9270 // available.
9271 Iterator<ConnectionRecord> it = r.connections.values().iterator();
9272 while (it.hasNext()) {
9273 ConnectionRecord c = it.next();
9274 try {
9275 // todo: shouldn't be a synchronous call!
9276 c.conn.connected(r.name, null);
9277 } catch (Exception e) {
9278 Log.w(TAG, "Failure disconnecting service " + r.name +
9279 " to connection " + c.conn.asBinder() +
9280 " (in " + c.binding.client.processName + ")", e);
9281 }
9282 }
9283 }
9284
9285 // Tell the service that it has been unbound.
9286 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9287 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9288 while (it.hasNext()) {
9289 IntentBindRecord ibr = it.next();
9290 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down binding " + ibr
9291 + ": hasBound=" + ibr.hasBound);
9292 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9293 try {
9294 bumpServiceExecutingLocked(r);
9295 updateOomAdjLocked(r.app);
9296 ibr.hasBound = false;
9297 r.app.thread.scheduleUnbindService(r,
9298 ibr.intent.getIntent());
9299 } catch (Exception e) {
9300 Log.w(TAG, "Exception when unbinding service "
9301 + r.shortName, e);
9302 serviceDoneExecutingLocked(r, true);
9303 }
9304 }
9305 }
9306 }
9307
9308 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down service " + r.name
9309 + " " + r.intent);
9310 EventLog.writeEvent(LOG_AM_DESTROY_SERVICE,
9311 System.identityHashCode(r), r.shortName,
9312 (r.app != null) ? r.app.pid : -1);
9313
9314 mServices.remove(r.name);
9315 mServicesByIntent.remove(r.intent);
9316 if (localLOGV) Log.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
9317 r.totalRestartCount = 0;
9318 unscheduleServiceRestartLocked(r);
9319
9320 // Also make sure it is not on the pending list.
9321 int N = mPendingServices.size();
9322 for (int i=0; i<N; i++) {
9323 if (mPendingServices.get(i) == r) {
9324 mPendingServices.remove(i);
9325 if (DEBUG_SERVICE) Log.v(
9326 TAG, "Removed pending service: " + r.shortName);
9327 i--;
9328 N--;
9329 }
9330 }
9331
9332 if (r.app != null) {
9333 synchronized (r.stats.getBatteryStats()) {
9334 r.stats.stopLaunchedLocked();
9335 }
9336 r.app.services.remove(r);
9337 if (r.app.thread != null) {
9338 updateServiceForegroundLocked(r.app, false);
9339 try {
9340 Log.i(TAG, "Stopping service: " + r.shortName);
9341 bumpServiceExecutingLocked(r);
9342 mStoppingServices.add(r);
9343 updateOomAdjLocked(r.app);
9344 r.app.thread.scheduleStopService(r);
9345 } catch (Exception e) {
9346 Log.w(TAG, "Exception when stopping service "
9347 + r.shortName, e);
9348 serviceDoneExecutingLocked(r, true);
9349 }
9350 } else {
9351 if (DEBUG_SERVICE) Log.v(
9352 TAG, "Removed service that has no process: " + r.shortName);
9353 }
9354 } else {
9355 if (DEBUG_SERVICE) Log.v(
9356 TAG, "Removed service that is not running: " + r.shortName);
9357 }
9358 }
9359
9360 ComponentName startServiceLocked(IApplicationThread caller,
9361 Intent service, String resolvedType,
9362 int callingPid, int callingUid) {
9363 synchronized(this) {
9364 if (DEBUG_SERVICE) Log.v(TAG, "startService: " + service
9365 + " type=" + resolvedType + " args=" + service.getExtras());
9366
9367 if (caller != null) {
9368 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9369 if (callerApp == null) {
9370 throw new SecurityException(
9371 "Unable to find app for caller " + caller
9372 + " (pid=" + Binder.getCallingPid()
9373 + ") when starting service " + service);
9374 }
9375 }
9376
9377 ServiceLookupResult res =
9378 retrieveServiceLocked(service, resolvedType,
9379 callingPid, callingUid);
9380 if (res == null) {
9381 return null;
9382 }
9383 if (res.record == null) {
9384 return new ComponentName("!", res.permission != null
9385 ? res.permission : "private to package");
9386 }
9387 ServiceRecord r = res.record;
9388 if (unscheduleServiceRestartLocked(r)) {
9389 if (DEBUG_SERVICE) Log.v(TAG, "START SERVICE WHILE RESTART PENDING: "
9390 + r.shortName);
9391 }
9392 r.startRequested = true;
9393 r.startArgs.add(service);
9394 r.lastStartId++;
9395 if (r.lastStartId < 1) {
9396 r.lastStartId = 1;
9397 }
9398 r.lastActivity = SystemClock.uptimeMillis();
9399 synchronized (r.stats.getBatteryStats()) {
9400 r.stats.startRunningLocked();
9401 }
9402 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9403 return new ComponentName("!", "Service process is bad");
9404 }
9405 return r.name;
9406 }
9407 }
9408
9409 public ComponentName startService(IApplicationThread caller, Intent service,
9410 String resolvedType) {
9411 // Refuse possible leaked file descriptors
9412 if (service != null && service.hasFileDescriptors() == true) {
9413 throw new IllegalArgumentException("File descriptors passed in Intent");
9414 }
9415
9416 synchronized(this) {
9417 final int callingPid = Binder.getCallingPid();
9418 final int callingUid = Binder.getCallingUid();
9419 final long origId = Binder.clearCallingIdentity();
9420 ComponentName res = startServiceLocked(caller, service,
9421 resolvedType, callingPid, callingUid);
9422 Binder.restoreCallingIdentity(origId);
9423 return res;
9424 }
9425 }
9426
9427 ComponentName startServiceInPackage(int uid,
9428 Intent service, String resolvedType) {
9429 synchronized(this) {
9430 final long origId = Binder.clearCallingIdentity();
9431 ComponentName res = startServiceLocked(null, service,
9432 resolvedType, -1, uid);
9433 Binder.restoreCallingIdentity(origId);
9434 return res;
9435 }
9436 }
9437
9438 public int stopService(IApplicationThread caller, Intent service,
9439 String resolvedType) {
9440 // Refuse possible leaked file descriptors
9441 if (service != null && service.hasFileDescriptors() == true) {
9442 throw new IllegalArgumentException("File descriptors passed in Intent");
9443 }
9444
9445 synchronized(this) {
9446 if (DEBUG_SERVICE) Log.v(TAG, "stopService: " + service
9447 + " type=" + resolvedType);
9448
9449 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9450 if (caller != null && callerApp == null) {
9451 throw new SecurityException(
9452 "Unable to find app for caller " + caller
9453 + " (pid=" + Binder.getCallingPid()
9454 + ") when stopping service " + service);
9455 }
9456
9457 // If this service is active, make sure it is stopped.
9458 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9459 if (r != null) {
9460 if (r.record != null) {
9461 synchronized (r.record.stats.getBatteryStats()) {
9462 r.record.stats.stopRunningLocked();
9463 }
9464 r.record.startRequested = false;
9465 final long origId = Binder.clearCallingIdentity();
9466 bringDownServiceLocked(r.record, false);
9467 Binder.restoreCallingIdentity(origId);
9468 return 1;
9469 }
9470 return -1;
9471 }
9472 }
9473
9474 return 0;
9475 }
9476
9477 public IBinder peekService(Intent service, String resolvedType) {
9478 // Refuse possible leaked file descriptors
9479 if (service != null && service.hasFileDescriptors() == true) {
9480 throw new IllegalArgumentException("File descriptors passed in Intent");
9481 }
9482
9483 IBinder ret = null;
9484
9485 synchronized(this) {
9486 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9487
9488 if (r != null) {
9489 // r.record is null if findServiceLocked() failed the caller permission check
9490 if (r.record == null) {
9491 throw new SecurityException(
9492 "Permission Denial: Accessing service " + r.record.name
9493 + " from pid=" + Binder.getCallingPid()
9494 + ", uid=" + Binder.getCallingUid()
9495 + " requires " + r.permission);
9496 }
9497 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9498 if (ib != null) {
9499 ret = ib.binder;
9500 }
9501 }
9502 }
9503
9504 return ret;
9505 }
9506
9507 public boolean stopServiceToken(ComponentName className, IBinder token,
9508 int startId) {
9509 synchronized(this) {
9510 if (DEBUG_SERVICE) Log.v(TAG, "stopServiceToken: " + className
9511 + " " + token + " startId=" + startId);
9512 ServiceRecord r = findServiceLocked(className, token);
9513 if (r != null && (startId < 0 || r.lastStartId == startId)) {
9514 synchronized (r.stats.getBatteryStats()) {
9515 r.stats.stopRunningLocked();
9516 r.startRequested = false;
9517 }
9518 final long origId = Binder.clearCallingIdentity();
9519 bringDownServiceLocked(r, false);
9520 Binder.restoreCallingIdentity(origId);
9521 return true;
9522 }
9523 }
9524 return false;
9525 }
9526
9527 public void setServiceForeground(ComponentName className, IBinder token,
9528 boolean isForeground) {
9529 synchronized(this) {
9530 ServiceRecord r = findServiceLocked(className, token);
9531 if (r != null) {
9532 if (r.isForeground != isForeground) {
9533 final long origId = Binder.clearCallingIdentity();
9534 r.isForeground = isForeground;
9535 if (r.app != null) {
9536 updateServiceForegroundLocked(r.app, true);
9537 }
9538 Binder.restoreCallingIdentity(origId);
9539 }
9540 }
9541 }
9542 }
9543
9544 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9545 boolean anyForeground = false;
9546 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
9547 if (sr.isForeground) {
9548 anyForeground = true;
9549 break;
9550 }
9551 }
9552 if (anyForeground != proc.foregroundServices) {
9553 proc.foregroundServices = anyForeground;
9554 if (oomAdj) {
9555 updateOomAdjLocked();
9556 }
9557 }
9558 }
9559
9560 public int bindService(IApplicationThread caller, IBinder token,
9561 Intent service, String resolvedType,
9562 IServiceConnection connection, int flags) {
9563 // Refuse possible leaked file descriptors
9564 if (service != null && service.hasFileDescriptors() == true) {
9565 throw new IllegalArgumentException("File descriptors passed in Intent");
9566 }
9567
9568 synchronized(this) {
9569 if (DEBUG_SERVICE) Log.v(TAG, "bindService: " + service
9570 + " type=" + resolvedType + " conn=" + connection.asBinder()
9571 + " flags=0x" + Integer.toHexString(flags));
9572 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9573 if (callerApp == null) {
9574 throw new SecurityException(
9575 "Unable to find app for caller " + caller
9576 + " (pid=" + Binder.getCallingPid()
9577 + ") when binding service " + service);
9578 }
9579
9580 HistoryRecord activity = null;
9581 if (token != null) {
9582 int aindex = indexOfTokenLocked(token, false);
9583 if (aindex < 0) {
9584 Log.w(TAG, "Binding with unknown activity: " + token);
9585 return 0;
9586 }
9587 activity = (HistoryRecord)mHistory.get(aindex);
9588 }
9589
9590 ServiceLookupResult res =
9591 retrieveServiceLocked(service, resolvedType,
9592 Binder.getCallingPid(), Binder.getCallingUid());
9593 if (res == null) {
9594 return 0;
9595 }
9596 if (res.record == null) {
9597 return -1;
9598 }
9599 ServiceRecord s = res.record;
9600
9601 final long origId = Binder.clearCallingIdentity();
9602
9603 if (unscheduleServiceRestartLocked(s)) {
9604 if (DEBUG_SERVICE) Log.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
9605 + s.shortName);
9606 }
9607
9608 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9609 ConnectionRecord c = new ConnectionRecord(b, activity,
9610 connection, flags);
9611
9612 IBinder binder = connection.asBinder();
9613 s.connections.put(binder, c);
9614 b.connections.add(c);
9615 if (activity != null) {
9616 if (activity.connections == null) {
9617 activity.connections = new HashSet<ConnectionRecord>();
9618 }
9619 activity.connections.add(c);
9620 }
9621 b.client.connections.add(c);
9622 mServiceConnections.put(binder, c);
9623
9624 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9625 s.lastActivity = SystemClock.uptimeMillis();
9626 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9627 return 0;
9628 }
9629 }
9630
9631 if (s.app != null) {
9632 // This could have made the service more important.
9633 updateOomAdjLocked(s.app);
9634 }
9635
9636 if (DEBUG_SERVICE) Log.v(TAG, "Bind " + s + " with " + b
9637 + ": received=" + b.intent.received
9638 + " apps=" + b.intent.apps.size()
9639 + " doRebind=" + b.intent.doRebind);
9640
9641 if (s.app != null && b.intent.received) {
9642 // Service is already running, so we can immediately
9643 // publish the connection.
9644 try {
9645 c.conn.connected(s.name, b.intent.binder);
9646 } catch (Exception e) {
9647 Log.w(TAG, "Failure sending service " + s.shortName
9648 + " to connection " + c.conn.asBinder()
9649 + " (in " + c.binding.client.processName + ")", e);
9650 }
9651
9652 // If this is the first app connected back to this binding,
9653 // and the service had previously asked to be told when
9654 // rebound, then do so.
9655 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9656 requestServiceBindingLocked(s, b.intent, true);
9657 }
9658 } else if (!b.intent.requested) {
9659 requestServiceBindingLocked(s, b.intent, false);
9660 }
9661
9662 Binder.restoreCallingIdentity(origId);
9663 }
9664
9665 return 1;
9666 }
9667
9668 private void removeConnectionLocked(
9669 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
9670 IBinder binder = c.conn.asBinder();
9671 AppBindRecord b = c.binding;
9672 ServiceRecord s = b.service;
9673 s.connections.remove(binder);
9674 b.connections.remove(c);
9675 if (c.activity != null && c.activity != skipAct) {
9676 if (c.activity.connections != null) {
9677 c.activity.connections.remove(c);
9678 }
9679 }
9680 if (b.client != skipApp) {
9681 b.client.connections.remove(c);
9682 }
9683 mServiceConnections.remove(binder);
9684
9685 if (b.connections.size() == 0) {
9686 b.intent.apps.remove(b.client);
9687 }
9688
9689 if (DEBUG_SERVICE) Log.v(TAG, "Disconnecting binding " + b.intent
9690 + ": shouldUnbind=" + b.intent.hasBound);
9691 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9692 && b.intent.hasBound) {
9693 try {
9694 bumpServiceExecutingLocked(s);
9695 updateOomAdjLocked(s.app);
9696 b.intent.hasBound = false;
9697 // Assume the client doesn't want to know about a rebind;
9698 // we will deal with that later if it asks for one.
9699 b.intent.doRebind = false;
9700 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9701 } catch (Exception e) {
9702 Log.w(TAG, "Exception when unbinding service " + s.shortName, e);
9703 serviceDoneExecutingLocked(s, true);
9704 }
9705 }
9706
9707 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9708 bringDownServiceLocked(s, false);
9709 }
9710 }
9711
9712 public boolean unbindService(IServiceConnection connection) {
9713 synchronized (this) {
9714 IBinder binder = connection.asBinder();
9715 if (DEBUG_SERVICE) Log.v(TAG, "unbindService: conn=" + binder);
9716 ConnectionRecord r = mServiceConnections.get(binder);
9717 if (r == null) {
9718 Log.w(TAG, "Unbind failed: could not find connection for "
9719 + connection.asBinder());
9720 return false;
9721 }
9722
9723 final long origId = Binder.clearCallingIdentity();
9724
9725 removeConnectionLocked(r, null, null);
9726
9727 if (r.binding.service.app != null) {
9728 // This could have made the service less important.
9729 updateOomAdjLocked(r.binding.service.app);
9730 }
9731
9732 Binder.restoreCallingIdentity(origId);
9733 }
9734
9735 return true;
9736 }
9737
9738 public void publishService(IBinder token, Intent intent, IBinder service) {
9739 // Refuse possible leaked file descriptors
9740 if (intent != null && intent.hasFileDescriptors() == true) {
9741 throw new IllegalArgumentException("File descriptors passed in Intent");
9742 }
9743
9744 synchronized(this) {
9745 if (!(token instanceof ServiceRecord)) {
9746 throw new IllegalArgumentException("Invalid service token");
9747 }
9748 ServiceRecord r = (ServiceRecord)token;
9749
9750 final long origId = Binder.clearCallingIdentity();
9751
9752 if (DEBUG_SERVICE) Log.v(TAG, "PUBLISHING SERVICE " + r.name
9753 + " " + intent + ": " + service);
9754 if (r != null) {
9755 Intent.FilterComparison filter
9756 = new Intent.FilterComparison(intent);
9757 IntentBindRecord b = r.bindings.get(filter);
9758 if (b != null && !b.received) {
9759 b.binder = service;
9760 b.requested = true;
9761 b.received = true;
9762 if (r.connections.size() > 0) {
9763 Iterator<ConnectionRecord> it
9764 = r.connections.values().iterator();
9765 while (it.hasNext()) {
9766 ConnectionRecord c = it.next();
9767 if (!filter.equals(c.binding.intent.intent)) {
9768 if (DEBUG_SERVICE) Log.v(
9769 TAG, "Not publishing to: " + c);
9770 if (DEBUG_SERVICE) Log.v(
9771 TAG, "Bound intent: " + c.binding.intent.intent);
9772 if (DEBUG_SERVICE) Log.v(
9773 TAG, "Published intent: " + intent);
9774 continue;
9775 }
9776 if (DEBUG_SERVICE) Log.v(TAG, "Publishing to: " + c);
9777 try {
9778 c.conn.connected(r.name, service);
9779 } catch (Exception e) {
9780 Log.w(TAG, "Failure sending service " + r.name +
9781 " to connection " + c.conn.asBinder() +
9782 " (in " + c.binding.client.processName + ")", e);
9783 }
9784 }
9785 }
9786 }
9787
9788 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9789
9790 Binder.restoreCallingIdentity(origId);
9791 }
9792 }
9793 }
9794
9795 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9796 // Refuse possible leaked file descriptors
9797 if (intent != null && intent.hasFileDescriptors() == true) {
9798 throw new IllegalArgumentException("File descriptors passed in Intent");
9799 }
9800
9801 synchronized(this) {
9802 if (!(token instanceof ServiceRecord)) {
9803 throw new IllegalArgumentException("Invalid service token");
9804 }
9805 ServiceRecord r = (ServiceRecord)token;
9806
9807 final long origId = Binder.clearCallingIdentity();
9808
9809 if (r != null) {
9810 Intent.FilterComparison filter
9811 = new Intent.FilterComparison(intent);
9812 IntentBindRecord b = r.bindings.get(filter);
9813 if (DEBUG_SERVICE) Log.v(TAG, "unbindFinished in " + r
9814 + " at " + b + ": apps="
9815 + (b != null ? b.apps.size() : 0));
9816 if (b != null) {
9817 if (b.apps.size() > 0) {
9818 // Applications have already bound since the last
9819 // unbind, so just rebind right here.
9820 requestServiceBindingLocked(r, b, true);
9821 } else {
9822 // Note to tell the service the next time there is
9823 // a new client.
9824 b.doRebind = true;
9825 }
9826 }
9827
9828 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9829
9830 Binder.restoreCallingIdentity(origId);
9831 }
9832 }
9833 }
9834
9835 public void serviceDoneExecuting(IBinder token) {
9836 synchronized(this) {
9837 if (!(token instanceof ServiceRecord)) {
9838 throw new IllegalArgumentException("Invalid service token");
9839 }
9840 ServiceRecord r = (ServiceRecord)token;
9841 boolean inStopping = mStoppingServices.contains(token);
9842 if (r != null) {
9843 if (DEBUG_SERVICE) Log.v(TAG, "DONE EXECUTING SERVICE " + r.name
9844 + ": nesting=" + r.executeNesting
9845 + ", inStopping=" + inStopping);
9846 if (r != token) {
9847 Log.w(TAG, "Done executing service " + r.name
9848 + " with incorrect token: given " + token
9849 + ", expected " + r);
9850 return;
9851 }
9852
9853 final long origId = Binder.clearCallingIdentity();
9854 serviceDoneExecutingLocked(r, inStopping);
9855 Binder.restoreCallingIdentity(origId);
9856 } else {
9857 Log.w(TAG, "Done executing unknown service " + r.name
9858 + " with token " + token);
9859 }
9860 }
9861 }
9862
9863 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
9864 r.executeNesting--;
9865 if (r.executeNesting <= 0 && r.app != null) {
9866 r.app.executingServices.remove(r);
9867 if (r.app.executingServices.size() == 0) {
9868 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9869 }
9870 if (inStopping) {
9871 mStoppingServices.remove(r);
9872 }
9873 updateOomAdjLocked(r.app);
9874 }
9875 }
9876
9877 void serviceTimeout(ProcessRecord proc) {
9878 synchronized(this) {
9879 if (proc.executingServices.size() == 0 || proc.thread == null) {
9880 return;
9881 }
9882 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9883 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9884 ServiceRecord timeout = null;
9885 long nextTime = 0;
9886 while (it.hasNext()) {
9887 ServiceRecord sr = it.next();
9888 if (sr.executingStart < maxTime) {
9889 timeout = sr;
9890 break;
9891 }
9892 if (sr.executingStart > nextTime) {
9893 nextTime = sr.executingStart;
9894 }
9895 }
9896 if (timeout != null && mLRUProcesses.contains(proc)) {
9897 Log.w(TAG, "Timeout executing service: " + timeout);
9898 appNotRespondingLocked(proc, null, "Executing service "
9899 + timeout.name);
9900 } else {
9901 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9902 msg.obj = proc;
9903 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9904 }
9905 }
9906 }
9907
9908 // =========================================================
9909 // BROADCASTS
9910 // =========================================================
9911
9912 private final List getStickies(String action, IntentFilter filter,
9913 List cur) {
9914 final ContentResolver resolver = mContext.getContentResolver();
9915 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9916 if (list == null) {
9917 return cur;
9918 }
9919 int N = list.size();
9920 for (int i=0; i<N; i++) {
9921 Intent intent = list.get(i);
9922 if (filter.match(resolver, intent, true, TAG) >= 0) {
9923 if (cur == null) {
9924 cur = new ArrayList<Intent>();
9925 }
9926 cur.add(intent);
9927 }
9928 }
9929 return cur;
9930 }
9931
9932 private final void scheduleBroadcastsLocked() {
9933 if (DEBUG_BROADCAST) Log.v(TAG, "Schedule broadcasts: current="
9934 + mBroadcastsScheduled);
9935
9936 if (mBroadcastsScheduled) {
9937 return;
9938 }
9939 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9940 mBroadcastsScheduled = true;
9941 }
9942
9943 public Intent registerReceiver(IApplicationThread caller,
9944 IIntentReceiver receiver, IntentFilter filter, String permission) {
9945 synchronized(this) {
9946 ProcessRecord callerApp = null;
9947 if (caller != null) {
9948 callerApp = getRecordForAppLocked(caller);
9949 if (callerApp == null) {
9950 throw new SecurityException(
9951 "Unable to find app for caller " + caller
9952 + " (pid=" + Binder.getCallingPid()
9953 + ") when registering receiver " + receiver);
9954 }
9955 }
9956
9957 List allSticky = null;
9958
9959 // Look for any matching sticky broadcasts...
9960 Iterator actions = filter.actionsIterator();
9961 if (actions != null) {
9962 while (actions.hasNext()) {
9963 String action = (String)actions.next();
9964 allSticky = getStickies(action, filter, allSticky);
9965 }
9966 } else {
9967 allSticky = getStickies(null, filter, allSticky);
9968 }
9969
9970 // The first sticky in the list is returned directly back to
9971 // the client.
9972 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9973
9974 if (DEBUG_BROADCAST) Log.v(TAG, "Register receiver " + filter
9975 + ": " + sticky);
9976
9977 if (receiver == null) {
9978 return sticky;
9979 }
9980
9981 ReceiverList rl
9982 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9983 if (rl == null) {
9984 rl = new ReceiverList(this, callerApp,
9985 Binder.getCallingPid(),
9986 Binder.getCallingUid(), receiver);
9987 if (rl.app != null) {
9988 rl.app.receivers.add(rl);
9989 } else {
9990 try {
9991 receiver.asBinder().linkToDeath(rl, 0);
9992 } catch (RemoteException e) {
9993 return sticky;
9994 }
9995 rl.linkedToDeath = true;
9996 }
9997 mRegisteredReceivers.put(receiver.asBinder(), rl);
9998 }
9999 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10000 rl.add(bf);
10001 if (!bf.debugCheck()) {
10002 Log.w(TAG, "==> For Dynamic broadast");
10003 }
10004 mReceiverResolver.addFilter(bf);
10005
10006 // Enqueue broadcasts for all existing stickies that match
10007 // this filter.
10008 if (allSticky != null) {
10009 ArrayList receivers = new ArrayList();
10010 receivers.add(bf);
10011
10012 int N = allSticky.size();
10013 for (int i=0; i<N; i++) {
10014 Intent intent = (Intent)allSticky.get(i);
10015 BroadcastRecord r = new BroadcastRecord(intent, null,
10016 null, -1, -1, null, receivers, null, 0, null, null,
10017 false);
10018 if (mParallelBroadcasts.size() == 0) {
10019 scheduleBroadcastsLocked();
10020 }
10021 mParallelBroadcasts.add(r);
10022 }
10023 }
10024
10025 return sticky;
10026 }
10027 }
10028
10029 public void unregisterReceiver(IIntentReceiver receiver) {
10030 if (DEBUG_BROADCAST) Log.v(TAG, "Unregister receiver: " + receiver);
10031
10032 boolean doNext = false;
10033
10034 synchronized(this) {
10035 ReceiverList rl
10036 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10037 if (rl != null) {
10038 if (rl.curBroadcast != null) {
10039 BroadcastRecord r = rl.curBroadcast;
10040 doNext = finishReceiverLocked(
10041 receiver.asBinder(), r.resultCode, r.resultData,
10042 r.resultExtras, r.resultAbort, true);
10043 }
10044
10045 if (rl.app != null) {
10046 rl.app.receivers.remove(rl);
10047 }
10048 removeReceiverLocked(rl);
10049 if (rl.linkedToDeath) {
10050 rl.linkedToDeath = false;
10051 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10052 }
10053 }
10054 }
10055
10056 if (!doNext) {
10057 return;
10058 }
10059
10060 final long origId = Binder.clearCallingIdentity();
10061 processNextBroadcast(false);
10062 trimApplications();
10063 Binder.restoreCallingIdentity(origId);
10064 }
10065
10066 void removeReceiverLocked(ReceiverList rl) {
10067 mRegisteredReceivers.remove(rl.receiver.asBinder());
10068 int N = rl.size();
10069 for (int i=0; i<N; i++) {
10070 mReceiverResolver.removeFilter(rl.get(i));
10071 }
10072 }
10073
10074 private final int broadcastIntentLocked(ProcessRecord callerApp,
10075 String callerPackage, Intent intent, String resolvedType,
10076 IIntentReceiver resultTo, int resultCode, String resultData,
10077 Bundle map, String requiredPermission,
10078 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10079 intent = new Intent(intent);
10080
10081 if (DEBUG_BROADCAST) Log.v(
10082 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10083 + " ordered=" + ordered);
10084 if ((resultTo != null) && !ordered) {
10085 Log.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
10086 }
10087
10088 // Handle special intents: if this broadcast is from the package
10089 // manager about a package being removed, we need to remove all of
10090 // its activities from the history stack.
10091 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10092 intent.getAction());
10093 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10094 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
10095 || uidRemoved) {
10096 if (checkComponentPermission(
10097 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10098 callingPid, callingUid, -1)
10099 == PackageManager.PERMISSION_GRANTED) {
10100 if (uidRemoved) {
10101 final Bundle intentExtras = intent.getExtras();
10102 final int uid = intentExtras != null
10103 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10104 if (uid >= 0) {
10105 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10106 synchronized (bs) {
10107 bs.removeUidStatsLocked(uid);
10108 }
10109 }
10110 } else {
10111 Uri data = intent.getData();
10112 String ssp;
10113 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10114 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10115 uninstallPackageLocked(ssp,
10116 intent.getIntExtra(Intent.EXTRA_UID, -1), false);
10117 }
10118 }
10119 }
10120 } else {
10121 String msg = "Permission Denial: " + intent.getAction()
10122 + " broadcast from " + callerPackage + " (pid=" + callingPid
10123 + ", uid=" + callingUid + ")"
10124 + " requires "
10125 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
10126 Log.w(TAG, msg);
10127 throw new SecurityException(msg);
10128 }
10129 }
10130
10131 /*
10132 * If this is the time zone changed action, queue up a message that will reset the timezone
10133 * of all currently running processes. This message will get queued up before the broadcast
10134 * happens.
10135 */
10136 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10137 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10138 }
10139
10140 // Add to the sticky list if requested.
10141 if (sticky) {
10142 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10143 callingPid, callingUid)
10144 != PackageManager.PERMISSION_GRANTED) {
10145 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10146 + callingPid + ", uid=" + callingUid
10147 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
10148 Log.w(TAG, msg);
10149 throw new SecurityException(msg);
10150 }
10151 if (requiredPermission != null) {
10152 Log.w(TAG, "Can't broadcast sticky intent " + intent
10153 + " and enforce permission " + requiredPermission);
10154 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10155 }
10156 if (intent.getComponent() != null) {
10157 throw new SecurityException(
10158 "Sticky broadcasts can't target a specific component");
10159 }
10160 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10161 if (list == null) {
10162 list = new ArrayList<Intent>();
10163 mStickyBroadcasts.put(intent.getAction(), list);
10164 }
10165 int N = list.size();
10166 int i;
10167 for (i=0; i<N; i++) {
10168 if (intent.filterEquals(list.get(i))) {
10169 // This sticky already exists, replace it.
10170 list.set(i, new Intent(intent));
10171 break;
10172 }
10173 }
10174 if (i >= N) {
10175 list.add(new Intent(intent));
10176 }
10177 }
10178
10179 final ContentResolver resolver = mContext.getContentResolver();
10180
10181 // Figure out who all will receive this broadcast.
10182 List receivers = null;
10183 List<BroadcastFilter> registeredReceivers = null;
10184 try {
10185 if (intent.getComponent() != null) {
10186 // Broadcast is going to one specific receiver class...
10187 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010188 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010189 if (ai != null) {
10190 receivers = new ArrayList();
10191 ResolveInfo ri = new ResolveInfo();
10192 ri.activityInfo = ai;
10193 receivers.add(ri);
10194 }
10195 } else {
10196 // Need to resolve the intent to interested receivers...
10197 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10198 == 0) {
10199 receivers =
10200 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010201 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010202 }
10203 registeredReceivers = mReceiverResolver.queryIntent(resolver,
10204 intent, resolvedType, false);
10205 }
10206 } catch (RemoteException ex) {
10207 // pm is in same process, this will never happen.
10208 }
10209
10210 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10211 if (!ordered && NR > 0) {
10212 // If we are not serializing this broadcast, then send the
10213 // registered receivers separately so they don't wait for the
10214 // components to be launched.
10215 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10216 callerPackage, callingPid, callingUid, requiredPermission,
10217 registeredReceivers, resultTo, resultCode, resultData, map,
10218 ordered);
10219 if (DEBUG_BROADCAST) Log.v(
10220 TAG, "Enqueueing parallel broadcast " + r
10221 + ": prev had " + mParallelBroadcasts.size());
10222 mParallelBroadcasts.add(r);
10223 scheduleBroadcastsLocked();
10224 registeredReceivers = null;
10225 NR = 0;
10226 }
10227
10228 // Merge into one list.
10229 int ir = 0;
10230 if (receivers != null) {
10231 // A special case for PACKAGE_ADDED: do not allow the package
10232 // being added to see this broadcast. This prevents them from
10233 // using this as a back door to get run as soon as they are
10234 // installed. Maybe in the future we want to have a special install
10235 // broadcast or such for apps, but we'd like to deliberately make
10236 // this decision.
The Android Open Source Project10592532009-03-18 17:39:46 -070010237 boolean skip = false;
10238 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackbornf63220f2009-03-24 18:38:43 -070010239 skip = true;
The Android Open Source Project10592532009-03-18 17:39:46 -070010240 } else if (intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())) {
10241 skip = true;
10242 } else if (intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10243 skip = true;
10244 }
10245 String skipPackage = (skip && intent.getData() != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010246 ? intent.getData().getSchemeSpecificPart()
10247 : null;
10248 if (skipPackage != null && receivers != null) {
10249 int NT = receivers.size();
10250 for (int it=0; it<NT; it++) {
10251 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10252 if (curt.activityInfo.packageName.equals(skipPackage)) {
10253 receivers.remove(it);
10254 it--;
10255 NT--;
10256 }
10257 }
10258 }
10259
10260 int NT = receivers != null ? receivers.size() : 0;
10261 int it = 0;
10262 ResolveInfo curt = null;
10263 BroadcastFilter curr = null;
10264 while (it < NT && ir < NR) {
10265 if (curt == null) {
10266 curt = (ResolveInfo)receivers.get(it);
10267 }
10268 if (curr == null) {
10269 curr = registeredReceivers.get(ir);
10270 }
10271 if (curr.getPriority() >= curt.priority) {
10272 // Insert this broadcast record into the final list.
10273 receivers.add(it, curr);
10274 ir++;
10275 curr = null;
10276 it++;
10277 NT++;
10278 } else {
10279 // Skip to the next ResolveInfo in the final list.
10280 it++;
10281 curt = null;
10282 }
10283 }
10284 }
10285 while (ir < NR) {
10286 if (receivers == null) {
10287 receivers = new ArrayList();
10288 }
10289 receivers.add(registeredReceivers.get(ir));
10290 ir++;
10291 }
10292
10293 if ((receivers != null && receivers.size() > 0)
10294 || resultTo != null) {
10295 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10296 callerPackage, callingPid, callingUid, requiredPermission,
10297 receivers, resultTo, resultCode, resultData, map, ordered);
10298 if (DEBUG_BROADCAST) Log.v(
10299 TAG, "Enqueueing ordered broadcast " + r
10300 + ": prev had " + mOrderedBroadcasts.size());
10301 if (DEBUG_BROADCAST) {
10302 int seq = r.intent.getIntExtra("seq", -1);
10303 Log.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
10304 }
10305 mOrderedBroadcasts.add(r);
10306 scheduleBroadcastsLocked();
10307 }
10308
10309 return BROADCAST_SUCCESS;
10310 }
10311
10312 public final int broadcastIntent(IApplicationThread caller,
10313 Intent intent, String resolvedType, IIntentReceiver resultTo,
10314 int resultCode, String resultData, Bundle map,
10315 String requiredPermission, boolean serialized, boolean sticky) {
10316 // Refuse possible leaked file descriptors
10317 if (intent != null && intent.hasFileDescriptors() == true) {
10318 throw new IllegalArgumentException("File descriptors passed in Intent");
10319 }
10320
10321 synchronized(this) {
10322 if (!mSystemReady) {
10323 // if the caller really truly claims to know what they're doing, go
10324 // ahead and allow the broadcast without launching any receivers
10325 int flags = intent.getFlags();
10326 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10327 intent = new Intent(intent);
10328 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10329 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
10330 Log.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10331 + " before boot completion");
10332 throw new IllegalStateException("Cannot broadcast before boot completed");
10333 }
10334 }
10335
10336 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10337 final int callingPid = Binder.getCallingPid();
10338 final int callingUid = Binder.getCallingUid();
10339 final long origId = Binder.clearCallingIdentity();
10340 int res = broadcastIntentLocked(callerApp,
10341 callerApp != null ? callerApp.info.packageName : null,
10342 intent, resolvedType, resultTo,
10343 resultCode, resultData, map, requiredPermission, serialized,
10344 sticky, callingPid, callingUid);
10345 Binder.restoreCallingIdentity(origId);
10346 return res;
10347 }
10348 }
10349
10350 int broadcastIntentInPackage(String packageName, int uid,
10351 Intent intent, String resolvedType, IIntentReceiver resultTo,
10352 int resultCode, String resultData, Bundle map,
10353 String requiredPermission, boolean serialized, boolean sticky) {
10354 synchronized(this) {
10355 final long origId = Binder.clearCallingIdentity();
10356 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10357 resultTo, resultCode, resultData, map, requiredPermission,
10358 serialized, sticky, -1, uid);
10359 Binder.restoreCallingIdentity(origId);
10360 return res;
10361 }
10362 }
10363
10364 public final void unbroadcastIntent(IApplicationThread caller,
10365 Intent intent) {
10366 // Refuse possible leaked file descriptors
10367 if (intent != null && intent.hasFileDescriptors() == true) {
10368 throw new IllegalArgumentException("File descriptors passed in Intent");
10369 }
10370
10371 synchronized(this) {
10372 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10373 != PackageManager.PERMISSION_GRANTED) {
10374 String msg = "Permission Denial: unbroadcastIntent() from pid="
10375 + Binder.getCallingPid()
10376 + ", uid=" + Binder.getCallingUid()
10377 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
10378 Log.w(TAG, msg);
10379 throw new SecurityException(msg);
10380 }
10381 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10382 if (list != null) {
10383 int N = list.size();
10384 int i;
10385 for (i=0; i<N; i++) {
10386 if (intent.filterEquals(list.get(i))) {
10387 list.remove(i);
10388 break;
10389 }
10390 }
10391 }
10392 }
10393 }
10394
10395 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10396 String resultData, Bundle resultExtras, boolean resultAbort,
10397 boolean explicit) {
10398 if (mOrderedBroadcasts.size() == 0) {
10399 if (explicit) {
10400 Log.w(TAG, "finishReceiver called but no pending broadcasts");
10401 }
10402 return false;
10403 }
10404 BroadcastRecord r = mOrderedBroadcasts.get(0);
10405 if (r.receiver == null) {
10406 if (explicit) {
10407 Log.w(TAG, "finishReceiver called but none active");
10408 }
10409 return false;
10410 }
10411 if (r.receiver != receiver) {
10412 Log.w(TAG, "finishReceiver called but active receiver is different");
10413 return false;
10414 }
10415 int state = r.state;
10416 r.state = r.IDLE;
10417 if (state == r.IDLE) {
10418 if (explicit) {
10419 Log.w(TAG, "finishReceiver called but state is IDLE");
10420 }
10421 }
10422 r.receiver = null;
10423 r.intent.setComponent(null);
10424 if (r.curApp != null) {
10425 r.curApp.curReceiver = null;
10426 }
10427 if (r.curFilter != null) {
10428 r.curFilter.receiverList.curBroadcast = null;
10429 }
10430 r.curFilter = null;
10431 r.curApp = null;
10432 r.curComponent = null;
10433 r.curReceiver = null;
10434 mPendingBroadcast = null;
10435
10436 r.resultCode = resultCode;
10437 r.resultData = resultData;
10438 r.resultExtras = resultExtras;
10439 r.resultAbort = resultAbort;
10440
10441 // We will process the next receiver right now if this is finishing
10442 // an app receiver (which is always asynchronous) or after we have
10443 // come back from calling a receiver.
10444 return state == BroadcastRecord.APP_RECEIVE
10445 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10446 }
10447
10448 public void finishReceiver(IBinder who, int resultCode, String resultData,
10449 Bundle resultExtras, boolean resultAbort) {
10450 if (DEBUG_BROADCAST) Log.v(TAG, "Finish receiver: " + who);
10451
10452 // Refuse possible leaked file descriptors
10453 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10454 throw new IllegalArgumentException("File descriptors passed in Bundle");
10455 }
10456
10457 boolean doNext;
10458
10459 final long origId = Binder.clearCallingIdentity();
10460
10461 synchronized(this) {
10462 doNext = finishReceiverLocked(
10463 who, resultCode, resultData, resultExtras, resultAbort, true);
10464 }
10465
10466 if (doNext) {
10467 processNextBroadcast(false);
10468 }
10469 trimApplications();
10470
10471 Binder.restoreCallingIdentity(origId);
10472 }
10473
10474 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10475 if (r.nextReceiver > 0) {
10476 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10477 if (curReceiver instanceof BroadcastFilter) {
10478 BroadcastFilter bf = (BroadcastFilter) curReceiver;
10479 EventLog.writeEvent(LOG_AM_BROADCAST_DISCARD_FILTER,
10480 System.identityHashCode(r),
10481 r.intent.getAction(),
10482 r.nextReceiver - 1,
10483 System.identityHashCode(bf));
10484 } else {
10485 EventLog.writeEvent(LOG_AM_BROADCAST_DISCARD_APP,
10486 System.identityHashCode(r),
10487 r.intent.getAction(),
10488 r.nextReceiver - 1,
10489 ((ResolveInfo)curReceiver).toString());
10490 }
10491 } else {
10492 Log.w(TAG, "Discarding broadcast before first receiver is invoked: "
10493 + r);
10494 EventLog.writeEvent(LOG_AM_BROADCAST_DISCARD_APP,
10495 System.identityHashCode(r),
10496 r.intent.getAction(),
10497 r.nextReceiver,
10498 "NONE");
10499 }
10500 }
10501
10502 private final void broadcastTimeout() {
10503 synchronized (this) {
10504 if (mOrderedBroadcasts.size() == 0) {
10505 return;
10506 }
10507 long now = SystemClock.uptimeMillis();
10508 BroadcastRecord r = mOrderedBroadcasts.get(0);
10509 if ((r.startTime+BROADCAST_TIMEOUT) > now) {
10510 if (DEBUG_BROADCAST) Log.v(TAG,
10511 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10512 + (r.startTime + BROADCAST_TIMEOUT));
10513 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10514 mHandler.sendMessageAtTime(msg, r.startTime+BROADCAST_TIMEOUT);
10515 return;
10516 }
10517
10518 Log.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
10519 r.startTime = now;
10520 r.anrCount++;
10521
10522 // Current receiver has passed its expiration date.
10523 if (r.nextReceiver <= 0) {
10524 Log.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10525 return;
10526 }
10527
10528 ProcessRecord app = null;
10529
10530 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10531 Log.w(TAG, "Receiver during timeout: " + curReceiver);
10532 logBroadcastReceiverDiscard(r);
10533 if (curReceiver instanceof BroadcastFilter) {
10534 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10535 if (bf.receiverList.pid != 0
10536 && bf.receiverList.pid != MY_PID) {
10537 synchronized (this.mPidsSelfLocked) {
10538 app = this.mPidsSelfLocked.get(
10539 bf.receiverList.pid);
10540 }
10541 }
10542 } else {
10543 app = r.curApp;
10544 }
10545
10546 if (app != null) {
10547 appNotRespondingLocked(app, null, "Broadcast of " + r.intent.toString());
10548 }
10549
10550 if (mPendingBroadcast == r) {
10551 mPendingBroadcast = null;
10552 }
10553
10554 // Move on to the next receiver.
10555 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10556 r.resultExtras, r.resultAbort, true);
10557 scheduleBroadcastsLocked();
10558 }
10559 }
10560
10561 private final void processCurBroadcastLocked(BroadcastRecord r,
10562 ProcessRecord app) throws RemoteException {
10563 if (app.thread == null) {
10564 throw new RemoteException();
10565 }
10566 r.receiver = app.thread.asBinder();
10567 r.curApp = app;
10568 app.curReceiver = r;
10569 updateLRUListLocked(app, true);
10570
10571 // Tell the application to launch this receiver.
10572 r.intent.setComponent(r.curComponent);
10573
10574 boolean started = false;
10575 try {
10576 if (DEBUG_BROADCAST) Log.v(TAG,
10577 "Delivering to component " + r.curComponent
10578 + ": " + r);
10579 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10580 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10581 started = true;
10582 } finally {
10583 if (!started) {
10584 r.receiver = null;
10585 r.curApp = null;
10586 app.curReceiver = null;
10587 }
10588 }
10589
10590 }
10591
10592 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
10593 Intent intent, int resultCode, String data,
10594 Bundle extras, boolean ordered) throws RemoteException {
10595 if (app != null && app.thread != null) {
10596 // If we have an app thread, do the call through that so it is
10597 // correctly ordered with other one-way calls.
10598 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
10599 data, extras, ordered);
10600 } else {
10601 receiver.performReceive(intent, resultCode, data, extras, ordered);
10602 }
10603 }
10604
10605 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10606 BroadcastFilter filter, boolean ordered) {
10607 boolean skip = false;
10608 if (filter.requiredPermission != null) {
10609 int perm = checkComponentPermission(filter.requiredPermission,
10610 r.callingPid, r.callingUid, -1);
10611 if (perm != PackageManager.PERMISSION_GRANTED) {
10612 Log.w(TAG, "Permission Denial: broadcasting "
10613 + r.intent.toString()
10614 + " from " + r.callerPackage + " (pid="
10615 + r.callingPid + ", uid=" + r.callingUid + ")"
10616 + " requires " + filter.requiredPermission
10617 + " due to registered receiver " + filter);
10618 skip = true;
10619 }
10620 }
10621 if (r.requiredPermission != null) {
10622 int perm = checkComponentPermission(r.requiredPermission,
10623 filter.receiverList.pid, filter.receiverList.uid, -1);
10624 if (perm != PackageManager.PERMISSION_GRANTED) {
10625 Log.w(TAG, "Permission Denial: receiving "
10626 + r.intent.toString()
10627 + " to " + filter.receiverList.app
10628 + " (pid=" + filter.receiverList.pid
10629 + ", uid=" + filter.receiverList.uid + ")"
10630 + " requires " + r.requiredPermission
10631 + " due to sender " + r.callerPackage
10632 + " (uid " + r.callingUid + ")");
10633 skip = true;
10634 }
10635 }
10636
10637 if (!skip) {
10638 // If this is not being sent as an ordered broadcast, then we
10639 // don't want to touch the fields that keep track of the current
10640 // state of ordered broadcasts.
10641 if (ordered) {
10642 r.receiver = filter.receiverList.receiver.asBinder();
10643 r.curFilter = filter;
10644 filter.receiverList.curBroadcast = r;
10645 r.state = BroadcastRecord.CALL_IN_RECEIVE;
10646 }
10647 try {
10648 if (DEBUG_BROADCAST) {
10649 int seq = r.intent.getIntExtra("seq", -1);
10650 Log.i(TAG, "Sending broadcast " + r.intent.getAction() + " seq=" + seq
10651 + " app=" + filter.receiverList.app);
10652 }
10653 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10654 new Intent(r.intent), r.resultCode,
10655 r.resultData, r.resultExtras, r.ordered);
10656 if (ordered) {
10657 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10658 }
10659 } catch (RemoteException e) {
10660 Log.w(TAG, "Failure sending broadcast " + r.intent, e);
10661 if (ordered) {
10662 r.receiver = null;
10663 r.curFilter = null;
10664 filter.receiverList.curBroadcast = null;
10665 }
10666 }
10667 }
10668 }
10669
10670 private final void processNextBroadcast(boolean fromMsg) {
10671 synchronized(this) {
10672 BroadcastRecord r;
10673
10674 if (DEBUG_BROADCAST) Log.v(TAG, "processNextBroadcast: "
10675 + mParallelBroadcasts.size() + " broadcasts, "
10676 + mOrderedBroadcasts.size() + " serialized broadcasts");
10677
10678 updateCpuStats();
10679
10680 if (fromMsg) {
10681 mBroadcastsScheduled = false;
10682 }
10683
10684 // First, deliver any non-serialized broadcasts right away.
10685 while (mParallelBroadcasts.size() > 0) {
10686 r = mParallelBroadcasts.remove(0);
10687 final int N = r.receivers.size();
10688 for (int i=0; i<N; i++) {
10689 Object target = r.receivers.get(i);
10690 if (DEBUG_BROADCAST) Log.v(TAG,
10691 "Delivering non-serialized to registered "
10692 + target + ": " + r);
10693 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10694 }
10695 }
10696
10697 // Now take care of the next serialized one...
10698
10699 // If we are waiting for a process to come up to handle the next
10700 // broadcast, then do nothing at this point. Just in case, we
10701 // check that the process we're waiting for still exists.
10702 if (mPendingBroadcast != null) {
10703 Log.i(TAG, "processNextBroadcast: waiting for "
10704 + mPendingBroadcast.curApp);
10705
10706 boolean isDead;
10707 synchronized (mPidsSelfLocked) {
10708 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10709 }
10710 if (!isDead) {
10711 // It's still alive, so keep waiting
10712 return;
10713 } else {
10714 Log.w(TAG, "pending app " + mPendingBroadcast.curApp
10715 + " died before responding to broadcast");
10716 mPendingBroadcast = null;
10717 }
10718 }
10719
10720 do {
10721 if (mOrderedBroadcasts.size() == 0) {
10722 // No more broadcasts pending, so all done!
10723 scheduleAppGcsLocked();
10724 return;
10725 }
10726 r = mOrderedBroadcasts.get(0);
10727 boolean forceReceive = false;
10728
10729 // Ensure that even if something goes awry with the timeout
10730 // detection, we catch "hung" broadcasts here, discard them,
10731 // and continue to make progress.
10732 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
10733 long now = SystemClock.uptimeMillis();
10734 if (r.dispatchTime > 0) {
10735 if ((numReceivers > 0) &&
10736 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
10737 Log.w(TAG, "Hung broadcast discarded after timeout failure:"
10738 + " now=" + now
10739 + " dispatchTime=" + r.dispatchTime
10740 + " startTime=" + r.startTime
10741 + " intent=" + r.intent
10742 + " numReceivers=" + numReceivers
10743 + " nextReceiver=" + r.nextReceiver
10744 + " state=" + r.state);
10745 broadcastTimeout(); // forcibly finish this broadcast
10746 forceReceive = true;
10747 r.state = BroadcastRecord.IDLE;
10748 }
10749 }
10750
10751 if (r.state != BroadcastRecord.IDLE) {
10752 if (DEBUG_BROADCAST) Log.d(TAG,
10753 "processNextBroadcast() called when not idle (state="
10754 + r.state + ")");
10755 return;
10756 }
10757
10758 if (r.receivers == null || r.nextReceiver >= numReceivers
10759 || r.resultAbort || forceReceive) {
10760 // No more receivers for this broadcast! Send the final
10761 // result if requested...
10762 if (r.resultTo != null) {
10763 try {
10764 if (DEBUG_BROADCAST) {
10765 int seq = r.intent.getIntExtra("seq", -1);
10766 Log.i(TAG, "Finishing broadcast " + r.intent.getAction()
10767 + " seq=" + seq + " app=" + r.callerApp);
10768 }
10769 performReceive(r.callerApp, r.resultTo,
10770 new Intent(r.intent), r.resultCode,
10771 r.resultData, r.resultExtras, false);
10772 } catch (RemoteException e) {
10773 Log.w(TAG, "Failure sending broadcast result of " + r.intent, e);
10774 }
10775 }
10776
10777 if (DEBUG_BROADCAST) Log.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
10778 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10779
10780 // ... and on to the next...
10781 mOrderedBroadcasts.remove(0);
10782 r = null;
10783 continue;
10784 }
10785 } while (r == null);
10786
10787 // Get the next receiver...
10788 int recIdx = r.nextReceiver++;
10789
10790 // Keep track of when this receiver started, and make sure there
10791 // is a timeout message pending to kill it if need be.
10792 r.startTime = SystemClock.uptimeMillis();
10793 if (recIdx == 0) {
10794 r.dispatchTime = r.startTime;
10795
10796 if (DEBUG_BROADCAST) Log.v(TAG,
10797 "Submitting BROADCAST_TIMEOUT_MSG for "
10798 + (r.startTime + BROADCAST_TIMEOUT));
10799 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10800 mHandler.sendMessageAtTime(msg, r.startTime+BROADCAST_TIMEOUT);
10801 }
10802
10803 Object nextReceiver = r.receivers.get(recIdx);
10804 if (nextReceiver instanceof BroadcastFilter) {
10805 // Simple case: this is a registered receiver who gets
10806 // a direct call.
10807 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
10808 if (DEBUG_BROADCAST) Log.v(TAG,
10809 "Delivering serialized to registered "
10810 + filter + ": " + r);
10811 deliverToRegisteredReceiver(r, filter, r.ordered);
10812 if (r.receiver == null || !r.ordered) {
10813 // The receiver has already finished, so schedule to
10814 // process the next one.
10815 r.state = BroadcastRecord.IDLE;
10816 scheduleBroadcastsLocked();
10817 }
10818 return;
10819 }
10820
10821 // Hard case: need to instantiate the receiver, possibly
10822 // starting its application process to host it.
10823
10824 ResolveInfo info =
10825 (ResolveInfo)nextReceiver;
10826
10827 boolean skip = false;
10828 int perm = checkComponentPermission(info.activityInfo.permission,
10829 r.callingPid, r.callingUid,
10830 info.activityInfo.exported
10831 ? -1 : info.activityInfo.applicationInfo.uid);
10832 if (perm != PackageManager.PERMISSION_GRANTED) {
10833 Log.w(TAG, "Permission Denial: broadcasting "
10834 + r.intent.toString()
10835 + " from " + r.callerPackage + " (pid=" + r.callingPid
10836 + ", uid=" + r.callingUid + ")"
10837 + " requires " + info.activityInfo.permission
10838 + " due to receiver " + info.activityInfo.packageName
10839 + "/" + info.activityInfo.name);
10840 skip = true;
10841 }
10842 if (r.callingUid != Process.SYSTEM_UID &&
10843 r.requiredPermission != null) {
10844 try {
10845 perm = ActivityThread.getPackageManager().
10846 checkPermission(r.requiredPermission,
10847 info.activityInfo.applicationInfo.packageName);
10848 } catch (RemoteException e) {
10849 perm = PackageManager.PERMISSION_DENIED;
10850 }
10851 if (perm != PackageManager.PERMISSION_GRANTED) {
10852 Log.w(TAG, "Permission Denial: receiving "
10853 + r.intent + " to "
10854 + info.activityInfo.applicationInfo.packageName
10855 + " requires " + r.requiredPermission
10856 + " due to sender " + r.callerPackage
10857 + " (uid " + r.callingUid + ")");
10858 skip = true;
10859 }
10860 }
10861 if (r.curApp != null && r.curApp.crashing) {
10862 // If the target process is crashing, just skip it.
10863 skip = true;
10864 }
10865
10866 if (skip) {
10867 r.receiver = null;
10868 r.curFilter = null;
10869 r.state = BroadcastRecord.IDLE;
10870 scheduleBroadcastsLocked();
10871 return;
10872 }
10873
10874 r.state = BroadcastRecord.APP_RECEIVE;
10875 String targetProcess = info.activityInfo.processName;
10876 r.curComponent = new ComponentName(
10877 info.activityInfo.applicationInfo.packageName,
10878 info.activityInfo.name);
10879 r.curReceiver = info.activityInfo;
10880
10881 // Is this receiver's application already running?
10882 ProcessRecord app = getProcessRecordLocked(targetProcess,
10883 info.activityInfo.applicationInfo.uid);
10884 if (app != null && app.thread != null) {
10885 try {
10886 processCurBroadcastLocked(r, app);
10887 return;
10888 } catch (RemoteException e) {
10889 Log.w(TAG, "Exception when sending broadcast to "
10890 + r.curComponent, e);
10891 }
10892
10893 // If a dead object exception was thrown -- fall through to
10894 // restart the application.
10895 }
10896
10897 // Not running -- get it started, and enqueue this history record
10898 // to be executed when the app comes up.
10899 if ((r.curApp=startProcessLocked(targetProcess,
10900 info.activityInfo.applicationInfo, true,
10901 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
10902 "broadcast", r.curComponent)) == null) {
10903 // Ah, this recipient is unavailable. Finish it if necessary,
10904 // and mark the broadcast record as ready for the next.
10905 Log.w(TAG, "Unable to launch app "
10906 + info.activityInfo.applicationInfo.packageName + "/"
10907 + info.activityInfo.applicationInfo.uid + " for broadcast "
10908 + r.intent + ": process is bad");
10909 logBroadcastReceiverDiscard(r);
10910 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10911 r.resultExtras, r.resultAbort, true);
10912 scheduleBroadcastsLocked();
10913 r.state = BroadcastRecord.IDLE;
10914 return;
10915 }
10916
10917 mPendingBroadcast = r;
10918 }
10919 }
10920
10921 // =========================================================
10922 // INSTRUMENTATION
10923 // =========================================================
10924
10925 public boolean startInstrumentation(ComponentName className,
10926 String profileFile, int flags, Bundle arguments,
10927 IInstrumentationWatcher watcher) {
10928 // Refuse possible leaked file descriptors
10929 if (arguments != null && arguments.hasFileDescriptors()) {
10930 throw new IllegalArgumentException("File descriptors passed in Bundle");
10931 }
10932
10933 synchronized(this) {
10934 InstrumentationInfo ii = null;
10935 ApplicationInfo ai = null;
10936 try {
10937 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010938 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010939 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010940 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010941 } catch (PackageManager.NameNotFoundException e) {
10942 }
10943 if (ii == null) {
10944 reportStartInstrumentationFailure(watcher, className,
10945 "Unable to find instrumentation info for: " + className);
10946 return false;
10947 }
10948 if (ai == null) {
10949 reportStartInstrumentationFailure(watcher, className,
10950 "Unable to find instrumentation target package: " + ii.targetPackage);
10951 return false;
10952 }
10953
10954 int match = mContext.getPackageManager().checkSignatures(
10955 ii.targetPackage, ii.packageName);
10956 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10957 String msg = "Permission Denial: starting instrumentation "
10958 + className + " from pid="
10959 + Binder.getCallingPid()
10960 + ", uid=" + Binder.getCallingPid()
10961 + " not allowed because package " + ii.packageName
10962 + " does not have a signature matching the target "
10963 + ii.targetPackage;
10964 reportStartInstrumentationFailure(watcher, className, msg);
10965 throw new SecurityException(msg);
10966 }
10967
10968 final long origId = Binder.clearCallingIdentity();
10969 uninstallPackageLocked(ii.targetPackage, -1, true);
10970 ProcessRecord app = addAppLocked(ai);
10971 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010972 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 app.instrumentationProfileFile = profileFile;
10974 app.instrumentationArguments = arguments;
10975 app.instrumentationWatcher = watcher;
10976 app.instrumentationResultClass = className;
10977 Binder.restoreCallingIdentity(origId);
10978 }
10979
10980 return true;
10981 }
10982
10983 /**
10984 * Report errors that occur while attempting to start Instrumentation. Always writes the
10985 * error to the logs, but if somebody is watching, send the report there too. This enables
10986 * the "am" command to report errors with more information.
10987 *
10988 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10989 * @param cn The component name of the instrumentation.
10990 * @param report The error report.
10991 */
10992 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10993 ComponentName cn, String report) {
10994 Log.w(TAG, report);
10995 try {
10996 if (watcher != null) {
10997 Bundle results = new Bundle();
10998 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10999 results.putString("Error", report);
11000 watcher.instrumentationStatus(cn, -1, results);
11001 }
11002 } catch (RemoteException e) {
11003 Log.w(TAG, e);
11004 }
11005 }
11006
11007 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11008 if (app.instrumentationWatcher != null) {
11009 try {
11010 // NOTE: IInstrumentationWatcher *must* be oneway here
11011 app.instrumentationWatcher.instrumentationFinished(
11012 app.instrumentationClass,
11013 resultCode,
11014 results);
11015 } catch (RemoteException e) {
11016 }
11017 }
11018 app.instrumentationWatcher = null;
11019 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011020 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011021 app.instrumentationProfileFile = null;
11022 app.instrumentationArguments = null;
11023
11024 uninstallPackageLocked(app.processName, -1, false);
11025 }
11026
11027 public void finishInstrumentation(IApplicationThread target,
11028 int resultCode, Bundle results) {
11029 // Refuse possible leaked file descriptors
11030 if (results != null && results.hasFileDescriptors()) {
11031 throw new IllegalArgumentException("File descriptors passed in Intent");
11032 }
11033
11034 synchronized(this) {
11035 ProcessRecord app = getRecordForAppLocked(target);
11036 if (app == null) {
11037 Log.w(TAG, "finishInstrumentation: no app for " + target);
11038 return;
11039 }
11040 final long origId = Binder.clearCallingIdentity();
11041 finishInstrumentationLocked(app, resultCode, results);
11042 Binder.restoreCallingIdentity(origId);
11043 }
11044 }
11045
11046 // =========================================================
11047 // CONFIGURATION
11048 // =========================================================
11049
11050 public ConfigurationInfo getDeviceConfigurationInfo() {
11051 ConfigurationInfo config = new ConfigurationInfo();
11052 synchronized (this) {
11053 config.reqTouchScreen = mConfiguration.touchscreen;
11054 config.reqKeyboardType = mConfiguration.keyboard;
11055 config.reqNavigation = mConfiguration.navigation;
11056 if (mConfiguration.navigation != Configuration.NAVIGATION_NONAV) {
11057 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11058 }
11059 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED) {
11060 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11061 }
11062 }
11063 return config;
11064 }
11065
11066 public Configuration getConfiguration() {
11067 Configuration ci;
11068 synchronized(this) {
11069 ci = new Configuration(mConfiguration);
11070 }
11071 return ci;
11072 }
11073
11074 public void updateConfiguration(Configuration values) {
11075 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11076 "updateConfiguration()");
11077
11078 synchronized(this) {
11079 if (values == null && mWindowManager != null) {
11080 // sentinel: fetch the current configuration from the window manager
11081 values = mWindowManager.computeNewConfiguration();
11082 }
11083
11084 final long origId = Binder.clearCallingIdentity();
11085 updateConfigurationLocked(values, null);
11086 Binder.restoreCallingIdentity(origId);
11087 }
11088 }
11089
11090 /**
11091 * Do either or both things: (1) change the current configuration, and (2)
11092 * make sure the given activity is running with the (now) current
11093 * configuration. Returns true if the activity has been left running, or
11094 * false if <var>starting</var> is being destroyed to match the new
11095 * configuration.
11096 */
11097 public boolean updateConfigurationLocked(Configuration values,
11098 HistoryRecord starting) {
11099 int changes = 0;
11100
11101 boolean kept = true;
11102
11103 if (values != null) {
11104 Configuration newConfig = new Configuration(mConfiguration);
11105 changes = newConfig.updateFrom(values);
11106 if (changes != 0) {
11107 if (DEBUG_SWITCH) {
11108 Log.i(TAG, "Updating configuration to: " + values);
11109 }
11110
11111 EventLog.writeEvent(LOG_CONFIGURATION_CHANGED, changes);
11112
11113 if (values.locale != null) {
11114 saveLocaleLocked(values.locale,
11115 !values.locale.equals(mConfiguration.locale),
11116 values.userSetLocale);
11117 }
11118
11119 mConfiguration = newConfig;
11120
11121 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11122 msg.obj = new Configuration(mConfiguration);
11123 mHandler.sendMessage(msg);
11124
11125 final int N = mLRUProcesses.size();
11126 for (int i=0; i<N; i++) {
11127 ProcessRecord app = mLRUProcesses.get(i);
11128 try {
11129 if (app.thread != null) {
11130 app.thread.scheduleConfigurationChanged(mConfiguration);
11131 }
11132 } catch (Exception e) {
11133 }
11134 }
11135 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
11136 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11137 null, false, false, MY_PID, Process.SYSTEM_UID);
11138 }
11139 }
11140
11141 if (changes != 0 && starting == null) {
11142 // If the configuration changed, and the caller is not already
11143 // in the process of starting an activity, then find the top
11144 // activity to check if its configuration needs to change.
11145 starting = topRunningActivityLocked(null);
11146 }
11147
11148 if (starting != null) {
11149 kept = ensureActivityConfigurationLocked(starting, changes);
11150 if (kept) {
11151 // If this didn't result in the starting activity being
11152 // destroyed, then we need to make sure at this point that all
11153 // other activities are made visible.
11154 if (DEBUG_SWITCH) Log.i(TAG, "Config didn't destroy " + starting
11155 + ", ensuring others are correct.");
11156 ensureActivitiesVisibleLocked(starting, changes);
11157 }
11158 }
11159
11160 return kept;
11161 }
11162
11163 private final boolean relaunchActivityLocked(HistoryRecord r,
11164 int changes, boolean andResume) {
11165 List<ResultInfo> results = null;
11166 List<Intent> newIntents = null;
11167 if (andResume) {
11168 results = r.results;
11169 newIntents = r.newIntents;
11170 }
11171 if (DEBUG_SWITCH) Log.v(TAG, "Relaunching: " + r
11172 + " with results=" + results + " newIntents=" + newIntents
11173 + " andResume=" + andResume);
11174 EventLog.writeEvent(andResume ? LOG_AM_RELAUNCH_RESUME_ACTIVITY
11175 : LOG_AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
11176 r.task.taskId, r.shortComponentName);
11177
11178 r.startFreezingScreenLocked(r.app, 0);
11179
11180 try {
11181 if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting resumed " + r);
11182 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
11183 changes, !andResume);
11184 // Note: don't need to call pauseIfSleepingLocked() here, because
11185 // the caller will only pass in 'andResume' if this activity is
11186 // currently resumed, which implies we aren't sleeping.
11187 } catch (RemoteException e) {
11188 return false;
11189 }
11190
11191 if (andResume) {
11192 r.results = null;
11193 r.newIntents = null;
11194 }
11195
11196 return true;
11197 }
11198
11199 /**
11200 * Make sure the given activity matches the current configuration. Returns
11201 * false if the activity had to be destroyed. Returns true if the
11202 * configuration is the same, or the activity will remain running as-is
11203 * for whatever reason. Ensures the HistoryRecord is updated with the
11204 * correct configuration and all other bookkeeping is handled.
11205 */
11206 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
11207 int globalChanges) {
11208 if (DEBUG_SWITCH) Log.i(TAG, "Ensuring correct configuration: " + r);
11209
11210 // Short circuit: if the two configurations are the exact same
11211 // object (the common case), then there is nothing to do.
11212 Configuration newConfig = mConfiguration;
11213 if (r.configuration == newConfig) {
11214 if (DEBUG_SWITCH) Log.i(TAG, "Configuration unchanged in " + r);
11215 return true;
11216 }
11217
11218 // We don't worry about activities that are finishing.
11219 if (r.finishing) {
11220 if (DEBUG_SWITCH) Log.i(TAG,
11221 "Configuration doesn't matter in finishing " + r);
11222 r.stopFreezingScreenLocked(false);
11223 return true;
11224 }
11225
11226 // Okay we now are going to make this activity have the new config.
11227 // But then we need to figure out how it needs to deal with that.
11228 Configuration oldConfig = r.configuration;
11229 r.configuration = newConfig;
11230
11231 // If the activity isn't currently running, just leave the new
11232 // configuration and it will pick that up next time it starts.
11233 if (r.app == null || r.app.thread == null) {
11234 if (DEBUG_SWITCH) Log.i(TAG,
11235 "Configuration doesn't matter not running " + r);
11236 r.stopFreezingScreenLocked(false);
11237 return true;
11238 }
11239
11240 // If the activity isn't persistent, there is a chance we will
11241 // need to restart it.
11242 if (!r.persistent) {
11243
11244 // Figure out what has changed between the two configurations.
11245 int changes = oldConfig.diff(newConfig);
11246 if (DEBUG_SWITCH) {
11247 Log.i(TAG, "Checking to restart " + r.info.name + ": changed=0x"
11248 + Integer.toHexString(changes) + ", handles=0x"
11249 + Integer.toHexString(r.info.configChanges));
11250 }
11251 if ((changes&(~r.info.configChanges)) != 0) {
11252 // Aha, the activity isn't handling the change, so DIE DIE DIE.
11253 r.configChangeFlags |= changes;
11254 r.startFreezingScreenLocked(r.app, globalChanges);
11255 if (r.app == null || r.app.thread == null) {
11256 if (DEBUG_SWITCH) Log.i(TAG, "Switch is destroying non-running " + r);
11257 destroyActivityLocked(r, true);
11258 } else if (r.state == ActivityState.PAUSING) {
11259 // A little annoying: we are waiting for this activity to
11260 // finish pausing. Let's not do anything now, but just
11261 // flag that it needs to be restarted when done pausing.
11262 r.configDestroy = true;
11263 return true;
11264 } else if (r.state == ActivityState.RESUMED) {
11265 // Try to optimize this case: the configuration is changing
11266 // and we need to restart the top, resumed activity.
11267 // Instead of doing the normal handshaking, just say
11268 // "restart!".
11269 if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting resumed " + r);
11270 relaunchActivityLocked(r, r.configChangeFlags, true);
11271 r.configChangeFlags = 0;
11272 } else {
11273 if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting non-resumed " + r);
11274 relaunchActivityLocked(r, r.configChangeFlags, false);
11275 r.configChangeFlags = 0;
11276 }
11277
11278 // All done... tell the caller we weren't able to keep this
11279 // activity around.
11280 return false;
11281 }
11282 }
11283
11284 // Default case: the activity can handle this new configuration, so
11285 // hand it over. Note that we don't need to give it the new
11286 // configuration, since we always send configuration changes to all
11287 // process when they happen so it can just use whatever configuration
11288 // it last got.
11289 if (r.app != null && r.app.thread != null) {
11290 try {
11291 r.app.thread.scheduleActivityConfigurationChanged(r);
11292 } catch (RemoteException e) {
11293 // If process died, whatever.
11294 }
11295 }
11296 r.stopFreezingScreenLocked(false);
11297
11298 return true;
11299 }
11300
11301 /**
11302 * Save the locale. You must be inside a synchronized (this) block.
11303 */
11304 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11305 if(isDiff) {
11306 SystemProperties.set("user.language", l.getLanguage());
11307 SystemProperties.set("user.region", l.getCountry());
11308 }
11309
11310 if(isPersist) {
11311 SystemProperties.set("persist.sys.language", l.getLanguage());
11312 SystemProperties.set("persist.sys.country", l.getCountry());
11313 SystemProperties.set("persist.sys.localevar", l.getVariant());
11314 }
11315 }
11316
11317 // =========================================================
11318 // LIFETIME MANAGEMENT
11319 // =========================================================
11320
11321 private final int computeOomAdjLocked(
11322 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11323 if (mAdjSeq == app.adjSeq) {
11324 // This adjustment has already been computed.
11325 return app.curAdj;
11326 }
11327
11328 if (app.thread == null) {
11329 app.adjSeq = mAdjSeq;
11330 return (app.curAdj=EMPTY_APP_ADJ);
11331 }
11332
11333 app.isForeground = false;
11334
The Android Open Source Project4df24232009-03-05 14:34:35 -080011335 // Determine the importance of the process, starting with most
11336 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011337 int adj;
11338 int N;
11339 if (app == TOP_APP || app.instrumentationClass != null
11340 || app.persistentActivities > 0) {
11341 // The last app on the list is the foreground app.
11342 adj = FOREGROUND_APP_ADJ;
11343 app.isForeground = true;
11344 } else if (app.curReceiver != null ||
11345 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11346 // An app that is currently receiving a broadcast also
11347 // counts as being in the foreground.
11348 adj = FOREGROUND_APP_ADJ;
11349 } else if (app.executingServices.size() > 0) {
11350 // An app that is currently executing a service callback also
11351 // counts as being in the foreground.
11352 adj = FOREGROUND_APP_ADJ;
11353 } else if (app.foregroundServices || app.forcingToForeground != null) {
11354 // The user is aware of this app, so make it visible.
11355 adj = VISIBLE_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -080011356 } else if (app == mHomeProcess) {
11357 // This process is hosting what we currently consider to be the
11358 // home app, so we don't want to let it go into the background.
11359 adj = HOME_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 } else if ((N=app.activities.size()) != 0) {
11361 // This app is in the background with paused activities.
11362 adj = hiddenAdj;
11363 for (int j=0; j<N; j++) {
11364 if (((HistoryRecord)app.activities.get(j)).visible) {
11365 // This app has a visible activity!
11366 adj = VISIBLE_APP_ADJ;
11367 break;
11368 }
11369 }
11370 } else {
11371 // A very not-needed process.
11372 adj = EMPTY_APP_ADJ;
11373 }
11374
The Android Open Source Project4df24232009-03-05 14:34:35 -080011375 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011376 // there are applications dependent on our services or providers, but
11377 // this gives us a baseline and makes sure we don't get into an
11378 // infinite recursion.
11379 app.adjSeq = mAdjSeq;
11380 app.curRawAdj = adj;
11381 app.curAdj = adj <= app.maxAdj ? adj : app.maxAdj;
11382
11383 if (app.services.size() != 0 && adj > FOREGROUND_APP_ADJ) {
11384 // If this process has active services running in it, we would
11385 // like to avoid killing it unless it would prevent the current
11386 // application from running.
11387 if (adj > hiddenAdj) {
11388 adj = hiddenAdj;
11389 }
11390 final long now = SystemClock.uptimeMillis();
11391 // This process is more important if the top activity is
11392 // bound to the service.
11393 Iterator jt = app.services.iterator();
11394 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11395 ServiceRecord s = (ServiceRecord)jt.next();
11396 if (s.startRequested) {
11397 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11398 // This service has seen some activity within
11399 // recent memory, so we will keep its process ahead
11400 // of the background processes.
11401 if (adj > SECONDARY_SERVER_ADJ) {
11402 adj = SECONDARY_SERVER_ADJ;
11403 }
11404 } else {
11405 // This service has been inactive for too long, just
11406 // put it with the rest of the background processes.
11407 if (adj > hiddenAdj) {
11408 adj = hiddenAdj;
11409 }
11410 }
11411 }
11412 if (s.connections.size() > 0 && adj > FOREGROUND_APP_ADJ) {
11413 Iterator<ConnectionRecord> kt
11414 = s.connections.values().iterator();
11415 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11416 // XXX should compute this based on the max of
11417 // all connected clients.
11418 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011419 if (cr.binding.client == app) {
11420 // Binding to ourself is not interesting.
11421 continue;
11422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011423 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11424 ProcessRecord client = cr.binding.client;
11425 int myHiddenAdj = hiddenAdj;
11426 if (myHiddenAdj > client.hiddenAdj) {
11427 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
11428 myHiddenAdj = client.hiddenAdj;
11429 } else {
11430 myHiddenAdj = VISIBLE_APP_ADJ;
11431 }
11432 }
11433 int clientAdj = computeOomAdjLocked(
11434 client, myHiddenAdj, TOP_APP);
11435 if (adj > clientAdj) {
11436 adj = clientAdj > VISIBLE_APP_ADJ
11437 ? clientAdj : VISIBLE_APP_ADJ;
11438 }
11439 }
11440 HistoryRecord a = cr.activity;
11441 //if (a != null) {
11442 // Log.i(TAG, "Connection to " + a ": state=" + a.state);
11443 //}
11444 if (a != null && adj > FOREGROUND_APP_ADJ &&
11445 (a.state == ActivityState.RESUMED
11446 || a.state == ActivityState.PAUSING)) {
11447 adj = FOREGROUND_APP_ADJ;
11448 }
11449 }
11450 }
11451 }
11452 }
11453
11454 if (app.pubProviders.size() != 0 && adj > FOREGROUND_APP_ADJ) {
11455 // If this process has published any content providers, then
11456 // its adjustment makes it at least as important as any of the
11457 // processes using those providers, and no less important than
11458 // CONTENT_PROVIDER_ADJ, which is just shy of EMPTY.
11459 if (adj > CONTENT_PROVIDER_ADJ) {
11460 adj = CONTENT_PROVIDER_ADJ;
11461 }
11462 Iterator jt = app.pubProviders.values().iterator();
11463 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11464 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
11465 if (cpr.clients.size() != 0) {
11466 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11467 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11468 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011469 if (client == app) {
11470 // Being our own client is not interesting.
11471 continue;
11472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011473 int myHiddenAdj = hiddenAdj;
11474 if (myHiddenAdj > client.hiddenAdj) {
11475 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11476 myHiddenAdj = client.hiddenAdj;
11477 } else {
11478 myHiddenAdj = FOREGROUND_APP_ADJ;
11479 }
11480 }
11481 int clientAdj = computeOomAdjLocked(
11482 client, myHiddenAdj, TOP_APP);
11483 if (adj > clientAdj) {
11484 adj = clientAdj > FOREGROUND_APP_ADJ
11485 ? clientAdj : FOREGROUND_APP_ADJ;
11486 }
11487 }
11488 }
11489 // If the provider has external (non-framework) process
11490 // dependencies, ensure that its adjustment is at least
11491 // FOREGROUND_APP_ADJ.
11492 if (cpr.externals != 0) {
11493 if (adj > FOREGROUND_APP_ADJ) {
11494 adj = FOREGROUND_APP_ADJ;
11495 }
11496 }
11497 }
11498 }
11499
11500 app.curRawAdj = adj;
11501
11502 //Log.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
11503 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11504 if (adj > app.maxAdj) {
11505 adj = app.maxAdj;
11506 }
11507
11508 app.curAdj = adj;
11509
11510 return adj;
11511 }
11512
11513 /**
11514 * Ask a given process to GC right now.
11515 */
11516 final void performAppGcLocked(ProcessRecord app) {
11517 try {
11518 app.lastRequestedGc = SystemClock.uptimeMillis();
11519 if (app.thread != null) {
11520 app.thread.processInBackground();
11521 }
11522 } catch (Exception e) {
11523 // whatever.
11524 }
11525 }
11526
11527 /**
11528 * Returns true if things are idle enough to perform GCs.
11529 */
11530 private final boolean canGcNow() {
11531 return mParallelBroadcasts.size() == 0
11532 && mOrderedBroadcasts.size() == 0
11533 && (mSleeping || (mResumedActivity != null &&
11534 mResumedActivity.idle));
11535 }
11536
11537 /**
11538 * Perform GCs on all processes that are waiting for it, but only
11539 * if things are idle.
11540 */
11541 final void performAppGcsLocked() {
11542 final int N = mProcessesToGc.size();
11543 if (N <= 0) {
11544 return;
11545 }
11546 if (canGcNow()) {
11547 while (mProcessesToGc.size() > 0) {
11548 ProcessRecord proc = mProcessesToGc.remove(0);
11549 if (proc.curRawAdj > VISIBLE_APP_ADJ) {
11550 // To avoid spamming the system, we will GC processes one
11551 // at a time, waiting a few seconds between each.
11552 performAppGcLocked(proc);
11553 scheduleAppGcsLocked();
11554 return;
11555 }
11556 }
11557 }
11558 }
11559
11560 /**
11561 * If all looks good, perform GCs on all processes waiting for them.
11562 */
11563 final void performAppGcsIfAppropriateLocked() {
11564 if (canGcNow()) {
11565 performAppGcsLocked();
11566 return;
11567 }
11568 // Still not idle, wait some more.
11569 scheduleAppGcsLocked();
11570 }
11571
11572 /**
11573 * Schedule the execution of all pending app GCs.
11574 */
11575 final void scheduleAppGcsLocked() {
11576 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
11577 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11578 mHandler.sendMessageDelayed(msg, GC_TIMEOUT);
11579 }
11580
11581 /**
11582 * Set up to ask a process to GC itself. This will either do it
11583 * immediately, or put it on the list of processes to gc the next
11584 * time things are idle.
11585 */
11586 final void scheduleAppGcLocked(ProcessRecord app) {
11587 long now = SystemClock.uptimeMillis();
11588 if ((app.lastRequestedGc+5000) > now) {
11589 return;
11590 }
11591 if (!mProcessesToGc.contains(app)) {
11592 mProcessesToGc.add(app);
11593 scheduleAppGcsLocked();
11594 }
11595 }
11596
11597 private final boolean updateOomAdjLocked(
11598 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11599 app.hiddenAdj = hiddenAdj;
11600
11601 if (app.thread == null) {
11602 return true;
11603 }
11604
11605 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP);
11606
11607 //Log.i(TAG, "Computed adj " + adj + " for app " + app.processName);
11608 //Thread priority adjustment is disabled out to see
11609 //how the kernel scheduler performs.
11610 if (false) {
11611 if (app.pid != 0 && app.isForeground != app.setIsForeground) {
11612 app.setIsForeground = app.isForeground;
11613 if (app.pid != MY_PID) {
11614 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(TAG, "Setting priority of " + app
11615 + " to " + (app.isForeground
11616 ? Process.THREAD_PRIORITY_FOREGROUND
11617 : Process.THREAD_PRIORITY_DEFAULT));
11618 try {
11619 Process.setThreadPriority(app.pid, app.isForeground
11620 ? Process.THREAD_PRIORITY_FOREGROUND
11621 : Process.THREAD_PRIORITY_DEFAULT);
11622 } catch (RuntimeException e) {
11623 Log.w(TAG, "Exception trying to set priority of application thread "
11624 + app.pid, e);
11625 }
11626 }
11627 }
11628 }
11629 if (app.pid != 0 && app.pid != MY_PID) {
11630 if (app.curRawAdj != app.setRawAdj) {
11631 if (app.curRawAdj > FOREGROUND_APP_ADJ
11632 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11633 // If this app is transitioning from foreground to
11634 // non-foreground, have it do a gc.
11635 scheduleAppGcLocked(app);
11636 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11637 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11638 // Likewise do a gc when an app is moving in to the
11639 // background (such as a service stopping).
11640 scheduleAppGcLocked(app);
11641 }
11642 app.setRawAdj = app.curRawAdj;
11643 }
11644 if (adj != app.setAdj) {
11645 if (Process.setOomAdj(app.pid, adj)) {
11646 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(
11647 TAG, "Set app " + app.processName +
11648 " oom adj to " + adj);
11649 app.setAdj = adj;
11650 } else {
11651 return false;
11652 }
11653 }
11654 }
11655
11656 return true;
11657 }
11658
11659 private final HistoryRecord resumedAppLocked() {
11660 HistoryRecord resumedActivity = mResumedActivity;
11661 if (resumedActivity == null || resumedActivity.app == null) {
11662 resumedActivity = mPausingActivity;
11663 if (resumedActivity == null || resumedActivity.app == null) {
11664 resumedActivity = topRunningActivityLocked(null);
11665 }
11666 }
11667 return resumedActivity;
11668 }
11669
11670 private final boolean updateOomAdjLocked(ProcessRecord app) {
11671 final HistoryRecord TOP_ACT = resumedAppLocked();
11672 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11673 int curAdj = app.curAdj;
11674 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11675 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11676
11677 mAdjSeq++;
11678
11679 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11680 if (res) {
11681 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11682 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11683 if (nowHidden != wasHidden) {
11684 // Changed to/from hidden state, so apps after it in the LRU
11685 // list may also be changed.
11686 updateOomAdjLocked();
11687 }
11688 }
11689 return res;
11690 }
11691
11692 private final boolean updateOomAdjLocked() {
11693 boolean didOomAdj = true;
11694 final HistoryRecord TOP_ACT = resumedAppLocked();
11695 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11696
11697 if (false) {
11698 RuntimeException e = new RuntimeException();
11699 e.fillInStackTrace();
11700 Log.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
11701 }
11702
11703 mAdjSeq++;
11704
11705 // First try updating the OOM adjustment for each of the
11706 // application processes based on their current state.
11707 int i = mLRUProcesses.size();
11708 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11709 while (i > 0) {
11710 i--;
11711 ProcessRecord app = mLRUProcesses.get(i);
11712 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
11713 if (curHiddenAdj < HIDDEN_APP_MAX_ADJ
11714 && app.curAdj == curHiddenAdj) {
11715 curHiddenAdj++;
11716 }
11717 } else {
11718 didOomAdj = false;
11719 }
11720 }
11721
11722 // todo: for now pretend like OOM ADJ didn't work, because things
11723 // aren't behaving as expected on Linux -- it's not killing processes.
11724 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11725 }
11726
11727 private final void trimApplications() {
11728 synchronized (this) {
11729 int i;
11730
11731 // First remove any unused application processes whose package
11732 // has been removed.
11733 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11734 final ProcessRecord app = mRemovedProcesses.get(i);
11735 if (app.activities.size() == 0
11736 && app.curReceiver == null && app.services.size() == 0) {
11737 Log.i(
11738 TAG, "Exiting empty application process "
11739 + app.processName + " ("
11740 + (app.thread != null ? app.thread.asBinder() : null)
11741 + ")\n");
11742 if (app.pid > 0 && app.pid != MY_PID) {
11743 Process.killProcess(app.pid);
11744 } else {
11745 try {
11746 app.thread.scheduleExit();
11747 } catch (Exception e) {
11748 // Ignore exceptions.
11749 }
11750 }
11751 cleanUpApplicationRecordLocked(app, false, -1);
11752 mRemovedProcesses.remove(i);
11753
11754 if (app.persistent) {
11755 if (app.persistent) {
11756 addAppLocked(app.info);
11757 }
11758 }
11759 }
11760 }
11761
11762 // Now try updating the OOM adjustment for each of the
11763 // application processes based on their current state.
11764 // If the setOomAdj() API is not supported, then go with our
11765 // back-up plan...
11766 if (!updateOomAdjLocked()) {
11767
11768 // Count how many processes are running services.
11769 int numServiceProcs = 0;
11770 for (i=mLRUProcesses.size()-1; i>=0; i--) {
11771 final ProcessRecord app = mLRUProcesses.get(i);
11772
11773 if (app.persistent || app.services.size() != 0
11774 || app.curReceiver != null
11775 || app.persistentActivities > 0) {
11776 // Don't count processes holding services against our
11777 // maximum process count.
11778 if (localLOGV) Log.v(
11779 TAG, "Not trimming app " + app + " with services: "
11780 + app.services);
11781 numServiceProcs++;
11782 }
11783 }
11784
11785 int curMaxProcs = mProcessLimit;
11786 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11787 if (mAlwaysFinishActivities) {
11788 curMaxProcs = 1;
11789 }
11790 curMaxProcs += numServiceProcs;
11791
11792 // Quit as many processes as we can to get down to the desired
11793 // process count. First remove any processes that no longer
11794 // have activites running in them.
11795 for ( i=0;
11796 i<mLRUProcesses.size()
11797 && mLRUProcesses.size() > curMaxProcs;
11798 i++) {
11799 final ProcessRecord app = mLRUProcesses.get(i);
11800 // Quit an application only if it is not currently
11801 // running any activities.
11802 if (!app.persistent && app.activities.size() == 0
11803 && app.curReceiver == null && app.services.size() == 0) {
11804 Log.i(
11805 TAG, "Exiting empty application process "
11806 + app.processName + " ("
11807 + (app.thread != null ? app.thread.asBinder() : null)
11808 + ")\n");
11809 if (app.pid > 0 && app.pid != MY_PID) {
11810 Process.killProcess(app.pid);
11811 } else {
11812 try {
11813 app.thread.scheduleExit();
11814 } catch (Exception e) {
11815 // Ignore exceptions.
11816 }
11817 }
11818 // todo: For now we assume the application is not buggy
11819 // or evil, and will quit as a result of our request.
11820 // Eventually we need to drive this off of the death
11821 // notification, and kill the process if it takes too long.
11822 cleanUpApplicationRecordLocked(app, false, i);
11823 i--;
11824 }
11825 }
11826
11827 // If we still have too many processes, now from the least
11828 // recently used process we start finishing activities.
11829 if (Config.LOGV) Log.v(
11830 TAG, "*** NOW HAVE " + mLRUProcesses.size() +
11831 " of " + curMaxProcs + " processes");
11832 for ( i=0;
11833 i<mLRUProcesses.size()
11834 && mLRUProcesses.size() > curMaxProcs;
11835 i++) {
11836 final ProcessRecord app = mLRUProcesses.get(i);
11837 // Quit the application only if we have a state saved for
11838 // all of its activities.
11839 boolean canQuit = !app.persistent && app.curReceiver == null
11840 && app.services.size() == 0
11841 && app.persistentActivities == 0;
11842 int NUMA = app.activities.size();
11843 int j;
11844 if (Config.LOGV) Log.v(
11845 TAG, "Looking to quit " + app.processName);
11846 for (j=0; j<NUMA && canQuit; j++) {
11847 HistoryRecord r = (HistoryRecord)app.activities.get(j);
11848 if (Config.LOGV) Log.v(
11849 TAG, " " + r.intent.getComponent().flattenToShortString()
11850 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11851 canQuit = (r.haveState || !r.stateNotNeeded)
11852 && !r.visible && r.stopped;
11853 }
11854 if (canQuit) {
11855 // Finish all of the activities, and then the app itself.
11856 for (j=0; j<NUMA; j++) {
11857 HistoryRecord r = (HistoryRecord)app.activities.get(j);
11858 if (!r.finishing) {
11859 destroyActivityLocked(r, false);
11860 }
11861 r.resultTo = null;
11862 }
11863 Log.i(TAG, "Exiting application process "
11864 + app.processName + " ("
11865 + (app.thread != null ? app.thread.asBinder() : null)
11866 + ")\n");
11867 if (app.pid > 0 && app.pid != MY_PID) {
11868 Process.killProcess(app.pid);
11869 } else {
11870 try {
11871 app.thread.scheduleExit();
11872 } catch (Exception e) {
11873 // Ignore exceptions.
11874 }
11875 }
11876 // todo: For now we assume the application is not buggy
11877 // or evil, and will quit as a result of our request.
11878 // Eventually we need to drive this off of the death
11879 // notification, and kill the process if it takes too long.
11880 cleanUpApplicationRecordLocked(app, false, i);
11881 i--;
11882 //dump();
11883 }
11884 }
11885
11886 }
11887
11888 int curMaxActivities = MAX_ACTIVITIES;
11889 if (mAlwaysFinishActivities) {
11890 curMaxActivities = 1;
11891 }
11892
11893 // Finally, if there are too many activities now running, try to
11894 // finish as many as we can to get back down to the limit.
11895 for ( i=0;
11896 i<mLRUActivities.size()
11897 && mLRUActivities.size() > curMaxActivities;
11898 i++) {
11899 final HistoryRecord r
11900 = (HistoryRecord)mLRUActivities.get(i);
11901
11902 // We can finish this one if we have its icicle saved and
11903 // it is not persistent.
11904 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11905 && r.stopped && !r.persistent && !r.finishing) {
11906 final int origSize = mLRUActivities.size();
11907 destroyActivityLocked(r, true);
11908
11909 // This will remove it from the LRU list, so keep
11910 // our index at the same value. Note that this check to
11911 // see if the size changes is just paranoia -- if
11912 // something unexpected happens, we don't want to end up
11913 // in an infinite loop.
11914 if (origSize > mLRUActivities.size()) {
11915 i--;
11916 }
11917 }
11918 }
11919 }
11920 }
11921
11922 /** This method sends the specified signal to each of the persistent apps */
11923 public void signalPersistentProcesses(int sig) throws RemoteException {
11924 if (sig != Process.SIGNAL_USR1) {
11925 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11926 }
11927
11928 synchronized (this) {
11929 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11930 != PackageManager.PERMISSION_GRANTED) {
11931 throw new SecurityException("Requires permission "
11932 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11933 }
11934
11935 for (int i = mLRUProcesses.size() - 1 ; i >= 0 ; i--) {
11936 ProcessRecord r = mLRUProcesses.get(i);
11937 if (r.thread != null && r.persistent) {
11938 Process.sendSignal(r.pid, sig);
11939 }
11940 }
11941 }
11942 }
11943
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011944 public boolean profileControl(String process, boolean start,
11945 String path) throws RemoteException {
11946
11947 synchronized (this) {
11948 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11949 // its own permission.
11950 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11951 != PackageManager.PERMISSION_GRANTED) {
11952 throw new SecurityException("Requires permission "
11953 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
11954 }
11955
11956 ProcessRecord proc = null;
11957 try {
11958 int pid = Integer.parseInt(process);
11959 synchronized (mPidsSelfLocked) {
11960 proc = mPidsSelfLocked.get(pid);
11961 }
11962 } catch (NumberFormatException e) {
11963 }
11964
11965 if (proc == null) {
11966 HashMap<String, SparseArray<ProcessRecord>> all
11967 = mProcessNames.getMap();
11968 SparseArray<ProcessRecord> procs = all.get(process);
11969 if (procs != null && procs.size() > 0) {
11970 proc = procs.valueAt(0);
11971 }
11972 }
11973
11974 if (proc == null || proc.thread == null) {
11975 throw new IllegalArgumentException("Unknown process: " + process);
11976 }
11977
11978 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11979 if (isSecure) {
11980 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11981 throw new SecurityException("Process not debuggable: " + proc);
11982 }
11983 }
11984
11985 try {
11986 proc.thread.profilerControl(start, path);
11987 return true;
11988 } catch (RemoteException e) {
11989 throw new IllegalStateException("Process disappeared");
11990 }
11991 }
11992 }
11993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011994 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11995 public void monitor() {
11996 synchronized (this) { }
11997 }
11998}