blob: 9d720d1a4896de265c6a3c9edb260b8fac6c6764 [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;
124 static final boolean VALIDATE_TOKENS = false;
125 static final boolean SHOW_ACTIVITY_START_TIME = true;
126
127 // Control over CPU and battery monitoring.
128 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
129 static final boolean MONITOR_CPU_USAGE = true;
130 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
131 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
132 static final boolean MONITOR_THREAD_CPU_USAGE = false;
133
134 // Event log tags
135 static final int LOG_CONFIGURATION_CHANGED = 2719;
136 static final int LOG_CPU = 2721;
137 static final int LOG_AM_FINISH_ACTIVITY = 30001;
138 static final int LOG_TASK_TO_FRONT = 30002;
139 static final int LOG_AM_NEW_INTENT = 30003;
140 static final int LOG_AM_CREATE_TASK = 30004;
141 static final int LOG_AM_CREATE_ACTIVITY = 30005;
142 static final int LOG_AM_RESTART_ACTIVITY = 30006;
143 static final int LOG_AM_RESUME_ACTIVITY = 30007;
144 static final int LOG_ANR = 30008;
145 static final int LOG_ACTIVITY_LAUNCH_TIME = 30009;
146 static final int LOG_AM_PROCESS_BOUND = 30010;
147 static final int LOG_AM_PROCESS_DIED = 30011;
148 static final int LOG_AM_FAILED_TO_PAUSE_ACTIVITY = 30012;
149 static final int LOG_AM_PAUSE_ACTIVITY = 30013;
150 static final int LOG_AM_PROCESS_START = 30014;
151 static final int LOG_AM_PROCESS_BAD = 30015;
152 static final int LOG_AM_PROCESS_GOOD = 30016;
153 static final int LOG_AM_LOW_MEMORY = 30017;
154 static final int LOG_AM_DESTROY_ACTIVITY = 30018;
155 static final int LOG_AM_RELAUNCH_RESUME_ACTIVITY = 30019;
156 static final int LOG_AM_RELAUNCH_ACTIVITY = 30020;
157 static final int LOG_AM_KILL_FOR_MEMORY = 30023;
158 static final int LOG_AM_BROADCAST_DISCARD_FILTER = 30024;
159 static final int LOG_AM_BROADCAST_DISCARD_APP = 30025;
160 static final int LOG_AM_CREATE_SERVICE = 30030;
161 static final int LOG_AM_DESTROY_SERVICE = 30031;
162 static final int LOG_AM_PROCESS_CRASHED_TOO_MUCH = 30032;
163 static final int LOG_AM_DROP_PROCESS = 30033;
164 static final int LOG_AM_SERVICE_CRASHED_TOO_MUCH = 30034;
165 static final int LOG_AM_SCHEDULE_SERVICE_RESTART = 30035;
166 static final int LOG_AM_PROVIDER_LOST_PROCESS = 30036;
167
168 static final int LOG_BOOT_PROGRESS_AMS_READY = 3040;
169 static final int LOG_BOOT_PROGRESS_ENABLE_SCREEN = 3050;
170
171 private static final String SYSTEM_SECURE = "ro.secure";
172
173 // This is the maximum number of application processes we would like
174 // to have running. Due to the asynchronous nature of things, we can
175 // temporarily go beyond this limit.
176 static final int MAX_PROCESSES = 2;
177
178 // Set to false to leave processes running indefinitely, relying on
179 // the kernel killing them as resources are required.
180 static final boolean ENFORCE_PROCESS_LIMIT = false;
181
182 // This is the maximum number of activities that we would like to have
183 // running at a given time.
184 static final int MAX_ACTIVITIES = 20;
185
186 // Maximum number of recent tasks that we can remember.
187 static final int MAX_RECENT_TASKS = 20;
188
189 // How long until we reset a task when the user returns to it. Currently
190 // 30 minutes.
191 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
192
193 // Set to true to disable the icon that is shown while a new activity
194 // is being started.
195 static final boolean SHOW_APP_STARTING_ICON = true;
196
197 // How long we wait until giving up on the last activity to pause. This
198 // is short because it directly impacts the responsiveness of starting the
199 // next activity.
200 static final int PAUSE_TIMEOUT = 500;
201
202 /**
203 * How long we can hold the launch wake lock before giving up.
204 */
205 static final int LAUNCH_TIMEOUT = 10*1000;
206
207 // How long we wait for a launched process to attach to the activity manager
208 // before we decide it's never going to come up for real.
209 static final int PROC_START_TIMEOUT = 10*1000;
210
211 // How long we wait until giving up on the last activity telling us it
212 // is idle.
213 static final int IDLE_TIMEOUT = 10*1000;
214
215 // How long to wait after going idle before forcing apps to GC.
216 static final int GC_TIMEOUT = 5*1000;
217
218 // How long we wait until giving up on an activity telling us it has
219 // finished destroying itself.
220 static final int DESTROY_TIMEOUT = 10*1000;
221
222 // How long we allow a receiver to run before giving up on it.
223 static final int BROADCAST_TIMEOUT = 10*1000;
224
225 // How long we wait for a service to finish executing.
226 static final int SERVICE_TIMEOUT = 20*1000;
227
228 // How long a service needs to be running until restarting its process
229 // is no longer considered to be a relaunch of the service.
230 static final int SERVICE_RESTART_DURATION = 5*1000;
231
232 // Maximum amount of time for there to be no activity on a service before
233 // we consider it non-essential and allow its process to go on the
234 // LRU background list.
235 static final int MAX_SERVICE_INACTIVITY = 10*60*1000;
236
237 // How long we wait until we timeout on key dispatching.
238 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
239
240 // The minimum time we allow between crashes, for us to consider this
241 // application to be bad and stop and its services and reject broadcasts.
242 static final int MIN_CRASH_INTERVAL = 60*1000;
243
244 // How long we wait until we timeout on key dispatching during instrumentation.
245 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
246
247 // OOM adjustments for processes in various states:
248
249 // This is a process without anything currently running in it. Definitely
250 // the first to go! Value set in system/rootdir/init.rc on startup.
251 // This value is initalized in the constructor, careful when refering to
252 // this static variable externally.
253 static int EMPTY_APP_ADJ;
254
255 // This is a process with a content provider that does not have any clients
256 // attached to it. If it did have any clients, its adjustment would be the
257 // one for the highest-priority of those processes.
258 static int CONTENT_PROVIDER_ADJ;
259
260 // This is a process only hosting activities that are not visible,
261 // so it can be killed without any disruption. Value set in
262 // system/rootdir/init.rc on startup.
263 final int HIDDEN_APP_MAX_ADJ;
264 static int HIDDEN_APP_MIN_ADJ;
265
The Android Open Source Project4df24232009-03-05 14:34:35 -0800266 // This is a process holding the home application -- we want to try
267 // avoiding killing it, even if it would normally be in the background,
268 // because the user interacts with it so much.
269 final int HOME_APP_ADJ;
270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 // This is a process holding a secondary server -- killing it will not
272 // have much of an impact as far as the user is concerned. Value set in
273 // system/rootdir/init.rc on startup.
274 final int SECONDARY_SERVER_ADJ;
275
276 // This is a process only hosting activities that are visible to the
277 // user, so we'd prefer they don't disappear. Value set in
278 // system/rootdir/init.rc on startup.
279 final int VISIBLE_APP_ADJ;
280
281 // This is the process running the current foreground app. We'd really
282 // rather not kill it! Value set in system/rootdir/init.rc on startup.
283 final int FOREGROUND_APP_ADJ;
284
285 // This is a process running a core server, such as telephony. Definitely
286 // don't want to kill it, but doing so is not completely fatal.
287 static final int CORE_SERVER_ADJ = -12;
288
289 // The system process runs at the default adjustment.
290 static final int SYSTEM_ADJ = -16;
291
292 // Memory pages are 4K.
293 static final int PAGE_SIZE = 4*1024;
294
295 // Corresponding memory levels for above adjustments.
296 final int EMPTY_APP_MEM;
297 final int HIDDEN_APP_MEM;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800298 final int HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 final int SECONDARY_SERVER_MEM;
300 final int VISIBLE_APP_MEM;
301 final int FOREGROUND_APP_MEM;
302
303 final int MY_PID;
304
305 static final String[] EMPTY_STRING_ARRAY = new String[0];
306
307 enum ActivityState {
308 INITIALIZING,
309 RESUMED,
310 PAUSING,
311 PAUSED,
312 STOPPING,
313 STOPPED,
314 FINISHING,
315 DESTROYING,
316 DESTROYED
317 }
318
319 /**
320 * The back history of all previous (and possibly still
321 * running) activities. It contains HistoryRecord objects.
322 */
323 final ArrayList mHistory = new ArrayList();
324
325 /**
326 * List of all active broadcasts that are to be executed immediately
327 * (without waiting for another broadcast to finish). Currently this only
328 * contains broadcasts to registered receivers, to avoid spinning up
329 * a bunch of processes to execute IntentReceiver components.
330 */
331 final ArrayList<BroadcastRecord> mParallelBroadcasts
332 = new ArrayList<BroadcastRecord>();
333
334 /**
335 * List of all active broadcasts that are to be executed one at a time.
336 * The object at the top of the list is the currently activity broadcasts;
337 * those after it are waiting for the top to finish..
338 */
339 final ArrayList<BroadcastRecord> mOrderedBroadcasts
340 = new ArrayList<BroadcastRecord>();
341
342 /**
343 * Set when we current have a BROADCAST_INTENT_MSG in flight.
344 */
345 boolean mBroadcastsScheduled = false;
346
347 /**
348 * Set to indicate whether to issue an onUserLeaving callback when a
349 * newly launched activity is being brought in front of us.
350 */
351 boolean mUserLeaving = false;
352
353 /**
354 * When we are in the process of pausing an activity, before starting the
355 * next one, this variable holds the activity that is currently being paused.
356 */
357 HistoryRecord mPausingActivity = null;
358
359 /**
360 * Current activity that is resumed, or null if there is none.
361 */
362 HistoryRecord mResumedActivity = null;
363
364 /**
365 * Activity we have told the window manager to have key focus.
366 */
367 HistoryRecord mFocusedActivity = null;
368
369 /**
370 * This is the last activity that we put into the paused state. This is
371 * used to determine if we need to do an activity transition while sleeping,
372 * when we normally hold the top activity paused.
373 */
374 HistoryRecord mLastPausedActivity = null;
375
376 /**
377 * List of activities that are waiting for a new activity
378 * to become visible before completing whatever operation they are
379 * supposed to do.
380 */
381 final ArrayList mWaitingVisibleActivities = new ArrayList();
382
383 /**
384 * List of activities that are ready to be stopped, but waiting
385 * for the next activity to settle down before doing so. It contains
386 * HistoryRecord objects.
387 */
388 final ArrayList<HistoryRecord> mStoppingActivities
389 = new ArrayList<HistoryRecord>();
390
391 /**
392 * List of intents that were used to start the most recent tasks.
393 */
394 final ArrayList<TaskRecord> mRecentTasks
395 = new ArrayList<TaskRecord>();
396
397 /**
398 * List of activities that are ready to be finished, but waiting
399 * for the previous activity to settle down before doing so. It contains
400 * HistoryRecord objects.
401 */
402 final ArrayList mFinishingActivities = new ArrayList();
403
404 /**
405 * All of the applications we currently have running organized by name.
406 * The keys are strings of the application package name (as
407 * returned by the package manager), and the keys are ApplicationRecord
408 * objects.
409 */
410 final ProcessMap<ProcessRecord> mProcessNames
411 = new ProcessMap<ProcessRecord>();
412
413 /**
414 * The last time that various processes have crashed.
415 */
416 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
417
418 /**
419 * Set of applications that we consider to be bad, and will reject
420 * incoming broadcasts from (which the user has no control over).
421 * Processes are added to this set when they have crashed twice within
422 * a minimum amount of time; they are removed from it when they are
423 * later restarted (hopefully due to some user action). The value is the
424 * time it was added to the list.
425 */
426 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
427
428 /**
429 * All of the processes we currently have running organized by pid.
430 * The keys are the pid running the application.
431 *
432 * <p>NOTE: This object is protected by its own lock, NOT the global
433 * activity manager lock!
434 */
435 final SparseArray<ProcessRecord> mPidsSelfLocked
436 = new SparseArray<ProcessRecord>();
437
438 /**
439 * All of the processes that have been forced to be foreground. The key
440 * is the pid of the caller who requested it (we hold a death
441 * link on it).
442 */
443 abstract class ForegroundToken implements IBinder.DeathRecipient {
444 int pid;
445 IBinder token;
446 }
447 final SparseArray<ForegroundToken> mForegroundProcesses
448 = new SparseArray<ForegroundToken>();
449
450 /**
451 * List of records for processes that someone had tried to start before the
452 * system was ready. We don't start them at that point, but ensure they
453 * are started by the time booting is complete.
454 */
455 final ArrayList<ProcessRecord> mProcessesOnHold
456 = new ArrayList<ProcessRecord>();
457
458 /**
459 * List of records for processes that we have started and are waiting
460 * for them to call back. This is really only needed when running in
461 * single processes mode, in which case we do not have a unique pid for
462 * each process.
463 */
464 final ArrayList<ProcessRecord> mStartingProcesses
465 = new ArrayList<ProcessRecord>();
466
467 /**
468 * List of persistent applications that are in the process
469 * of being started.
470 */
471 final ArrayList<ProcessRecord> mPersistentStartingProcesses
472 = new ArrayList<ProcessRecord>();
473
474 /**
475 * Processes that are being forcibly torn down.
476 */
477 final ArrayList<ProcessRecord> mRemovedProcesses
478 = new ArrayList<ProcessRecord>();
479
480 /**
481 * List of running applications, sorted by recent usage.
482 * The first entry in the list is the least recently used.
483 * It contains ApplicationRecord objects. This list does NOT include
484 * any persistent application records (since we never want to exit them).
485 */
486 final ArrayList<ProcessRecord> mLRUProcesses
487 = new ArrayList<ProcessRecord>();
488
489 /**
490 * List of processes that should gc as soon as things are idle.
491 */
492 final ArrayList<ProcessRecord> mProcessesToGc
493 = new ArrayList<ProcessRecord>();
494
495 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800496 * This is the process holding what we currently consider to be
497 * the "home" activity.
498 */
499 private ProcessRecord mHomeProcess;
500
501 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 * List of running activities, sorted by recent usage.
503 * The first entry in the list is the least recently used.
504 * It contains HistoryRecord objects.
505 */
506 private final ArrayList mLRUActivities = new ArrayList();
507
508 /**
509 * Set of PendingResultRecord objects that are currently active.
510 */
511 final HashSet mPendingResultRecords = new HashSet();
512
513 /**
514 * Set of IntentSenderRecord objects that are currently active.
515 */
516 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
517 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
518
519 /**
520 * Intent broadcast that we have tried to start, but are
521 * waiting for its application's process to be created. We only
522 * need one (instead of a list) because we always process broadcasts
523 * one at a time, so no others can be started while waiting for this
524 * one.
525 */
526 BroadcastRecord mPendingBroadcast = null;
527
528 /**
529 * Keeps track of all IIntentReceivers that have been registered for
530 * broadcasts. Hash keys are the receiver IBinder, hash value is
531 * a ReceiverList.
532 */
533 final HashMap mRegisteredReceivers = new HashMap();
534
535 /**
536 * Resolver for broadcast intents to registered receivers.
537 * Holds BroadcastFilter (subclass of IntentFilter).
538 */
539 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
540 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
541 @Override
542 protected boolean allowFilterResult(
543 BroadcastFilter filter, List<BroadcastFilter> dest) {
544 IBinder target = filter.receiverList.receiver.asBinder();
545 for (int i=dest.size()-1; i>=0; i--) {
546 if (dest.get(i).receiverList.receiver.asBinder() == target) {
547 return false;
548 }
549 }
550 return true;
551 }
552 };
553
554 /**
555 * State of all active sticky broadcasts. Keys are the action of the
556 * sticky Intent, values are an ArrayList of all broadcasted intents with
557 * that action (which should usually be one).
558 */
559 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
560 new HashMap<String, ArrayList<Intent>>();
561
562 /**
563 * All currently running services.
564 */
565 final HashMap<ComponentName, ServiceRecord> mServices =
566 new HashMap<ComponentName, ServiceRecord>();
567
568 /**
569 * All currently running services indexed by the Intent used to start them.
570 */
571 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
572 new HashMap<Intent.FilterComparison, ServiceRecord>();
573
574 /**
575 * All currently bound service connections. Keys are the IBinder of
576 * the client's IServiceConnection.
577 */
578 final HashMap<IBinder, ConnectionRecord> mServiceConnections
579 = new HashMap<IBinder, ConnectionRecord>();
580
581 /**
582 * List of services that we have been asked to start,
583 * but haven't yet been able to. It is used to hold start requests
584 * while waiting for their corresponding application thread to get
585 * going.
586 */
587 final ArrayList<ServiceRecord> mPendingServices
588 = new ArrayList<ServiceRecord>();
589
590 /**
591 * List of services that are scheduled to restart following a crash.
592 */
593 final ArrayList<ServiceRecord> mRestartingServices
594 = new ArrayList<ServiceRecord>();
595
596 /**
597 * List of services that are in the process of being stopped.
598 */
599 final ArrayList<ServiceRecord> mStoppingServices
600 = new ArrayList<ServiceRecord>();
601
602 /**
603 * List of PendingThumbnailsRecord objects of clients who are still
604 * waiting to receive all of the thumbnails for a task.
605 */
606 final ArrayList mPendingThumbnails = new ArrayList();
607
608 /**
609 * List of HistoryRecord objects that have been finished and must
610 * still report back to a pending thumbnail receiver.
611 */
612 final ArrayList mCancelledThumbnails = new ArrayList();
613
614 /**
615 * All of the currently running global content providers. Keys are a
616 * string containing the provider name and values are a
617 * ContentProviderRecord object containing the data about it. Note
618 * that a single provider may be published under multiple names, so
619 * there may be multiple entries here for a single one in mProvidersByClass.
620 */
621 final HashMap mProvidersByName = new HashMap();
622
623 /**
624 * All of the currently running global content providers. Keys are a
625 * string containing the provider's implementation class and values are a
626 * ContentProviderRecord object containing the data about it.
627 */
628 final HashMap mProvidersByClass = new HashMap();
629
630 /**
631 * List of content providers who have clients waiting for them. The
632 * application is currently being launched and the provider will be
633 * removed from this list once it is published.
634 */
635 final ArrayList mLaunchingProviders = new ArrayList();
636
637 /**
638 * Global set of specific Uri permissions that have been granted.
639 */
640 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
641 = new SparseArray<HashMap<Uri, UriPermission>>();
642
643 /**
644 * Thread-local storage used to carry caller permissions over through
645 * indirect content-provider access.
646 * @see #ActivityManagerService.openContentUri()
647 */
648 private class Identity {
649 public int pid;
650 public int uid;
651
652 Identity(int _pid, int _uid) {
653 pid = _pid;
654 uid = _uid;
655 }
656 }
657 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
658
659 /**
660 * All information we have collected about the runtime performance of
661 * any user id that can impact battery performance.
662 */
663 final BatteryStatsService mBatteryStatsService;
664
665 /**
666 * information about component usage
667 */
668 final UsageStatsService mUsageStatsService;
669
670 /**
671 * Current configuration information. HistoryRecord objects are given
672 * a reference to this object to indicate which configuration they are
673 * currently running in, so this object must be kept immutable.
674 */
675 Configuration mConfiguration = new Configuration();
676
677 /**
678 * List of initialization arguments to pass to all processes when binding applications to them.
679 * For example, references to the commonly used services.
680 */
681 HashMap<String, IBinder> mAppBindArgs;
682
683 /**
684 * Used to control how we initialize the service.
685 */
686 boolean mStartRunning = false;
687 ComponentName mTopComponent;
688 String mTopAction;
689 String mTopData;
690 boolean mSystemReady = false;
691 boolean mBooting = false;
692
693 Context mContext;
694
695 int mFactoryTest;
696
697 /**
698 * Set while we are wanting to sleep, to prevent any
699 * activities from being started/resumed.
700 */
701 boolean mSleeping = false;
702
703 /**
704 * Set when the system is going to sleep, until we have
705 * successfully paused the current activity and released our wake lock.
706 * At that point the system is allowed to actually sleep.
707 */
708 PowerManager.WakeLock mGoingToSleep;
709
710 /**
711 * We don't want to allow the device to go to sleep while in the process
712 * of launching an activity. This is primarily to allow alarm intent
713 * receivers to launch an activity and get that to run before the device
714 * goes back to sleep.
715 */
716 PowerManager.WakeLock mLaunchingActivity;
717
718 /**
719 * Task identifier that activities are currently being started
720 * in. Incremented each time a new task is created.
721 * todo: Replace this with a TokenSpace class that generates non-repeating
722 * integers that won't wrap.
723 */
724 int mCurTask = 1;
725
726 /**
727 * Current sequence id for oom_adj computation traversal.
728 */
729 int mAdjSeq = 0;
730
731 /**
732 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
733 * is set, indicating the user wants processes started in such a way
734 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
735 * running in each process (thus no pre-initialized process, etc).
736 */
737 boolean mSimpleProcessManagement = false;
738
739 /**
740 * System monitoring: number of processes that died since the last
741 * N procs were started.
742 */
743 int[] mProcDeaths = new int[20];
744
745 String mDebugApp = null;
746 boolean mWaitForDebugger = false;
747 boolean mDebugTransient = false;
748 String mOrigDebugApp = null;
749 boolean mOrigWaitForDebugger = false;
750 boolean mAlwaysFinishActivities = false;
751 IActivityWatcher mWatcher = null;
752
753 /**
754 * Callback of last caller to {@link #requestPss}.
755 */
756 Runnable mRequestPssCallback;
757
758 /**
759 * Remaining processes for which we are waiting results from the last
760 * call to {@link #requestPss}.
761 */
762 final ArrayList<ProcessRecord> mRequestPssList
763 = new ArrayList<ProcessRecord>();
764
765 /**
766 * Runtime statistics collection thread. This object's lock is used to
767 * protect all related state.
768 */
769 final Thread mProcessStatsThread;
770
771 /**
772 * Used to collect process stats when showing not responding dialog.
773 * Protected by mProcessStatsThread.
774 */
775 final ProcessStats mProcessStats = new ProcessStats(
776 MONITOR_THREAD_CPU_USAGE);
777 long mLastCpuTime = 0;
778 long mLastWriteTime = 0;
779
780 /**
781 * Set to true after the system has finished booting.
782 */
783 boolean mBooted = false;
784
785 int mProcessLimit = 0;
786
787 WindowManagerService mWindowManager;
788
789 static ActivityManagerService mSelf;
790 static ActivityThread mSystemThread;
791
792 private final class AppDeathRecipient implements IBinder.DeathRecipient {
793 final ProcessRecord mApp;
794 final int mPid;
795 final IApplicationThread mAppThread;
796
797 AppDeathRecipient(ProcessRecord app, int pid,
798 IApplicationThread thread) {
799 if (localLOGV) Log.v(
800 TAG, "New death recipient " + this
801 + " for thread " + thread.asBinder());
802 mApp = app;
803 mPid = pid;
804 mAppThread = thread;
805 }
806
807 public void binderDied() {
808 if (localLOGV) Log.v(
809 TAG, "Death received in " + this
810 + " for thread " + mAppThread.asBinder());
811 removeRequestedPss(mApp);
812 synchronized(ActivityManagerService.this) {
813 appDiedLocked(mApp, mPid, mAppThread);
814 }
815 }
816 }
817
818 static final int SHOW_ERROR_MSG = 1;
819 static final int SHOW_NOT_RESPONDING_MSG = 2;
820 static final int SHOW_FACTORY_ERROR_MSG = 3;
821 static final int UPDATE_CONFIGURATION_MSG = 4;
822 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
823 static final int WAIT_FOR_DEBUGGER_MSG = 6;
824 static final int BROADCAST_INTENT_MSG = 7;
825 static final int BROADCAST_TIMEOUT_MSG = 8;
826 static final int PAUSE_TIMEOUT_MSG = 9;
827 static final int IDLE_TIMEOUT_MSG = 10;
828 static final int IDLE_NOW_MSG = 11;
829 static final int SERVICE_TIMEOUT_MSG = 12;
830 static final int UPDATE_TIME_ZONE = 13;
831 static final int SHOW_UID_ERROR_MSG = 14;
832 static final int IM_FEELING_LUCKY_MSG = 15;
833 static final int LAUNCH_TIMEOUT_MSG = 16;
834 static final int DESTROY_TIMEOUT_MSG = 17;
835 static final int SERVICE_ERROR_MSG = 18;
836 static final int RESUME_TOP_ACTIVITY_MSG = 19;
837 static final int PROC_START_TIMEOUT_MSG = 20;
838
839 AlertDialog mUidAlert;
840
841 final Handler mHandler = new Handler() {
842 //public Handler() {
843 // if (localLOGV) Log.v(TAG, "Handler started!");
844 //}
845
846 public void handleMessage(Message msg) {
847 switch (msg.what) {
848 case SHOW_ERROR_MSG: {
849 HashMap data = (HashMap) msg.obj;
850 byte[] crashData = (byte[])data.get("crashData");
851 if (crashData != null) {
852 // This needs to be *un*synchronized to avoid deadlock.
853 ContentResolver resolver = mContext.getContentResolver();
854 Checkin.reportCrash(resolver, crashData);
855 }
856 synchronized (ActivityManagerService.this) {
857 ProcessRecord proc = (ProcessRecord)data.get("app");
858 if (proc != null && proc.crashDialog != null) {
859 Log.e(TAG, "App already has crash dialog: " + proc);
860 return;
861 }
862 AppErrorResult res = (AppErrorResult) data.get("result");
863 if (!mSleeping) {
864 Dialog d = new AppErrorDialog(
865 mContext, res, proc,
866 (Integer)data.get("flags"),
867 (String)data.get("shortMsg"),
868 (String)data.get("longMsg"));
869 d.show();
870 proc.crashDialog = d;
871 } else {
872 // The device is asleep, so just pretend that the user
873 // saw a crash dialog and hit "force quit".
874 res.set(0);
875 }
876 }
877 } break;
878 case SHOW_NOT_RESPONDING_MSG: {
879 synchronized (ActivityManagerService.this) {
880 HashMap data = (HashMap) msg.obj;
881 ProcessRecord proc = (ProcessRecord)data.get("app");
882 if (proc != null && proc.anrDialog != null) {
883 Log.e(TAG, "App already has anr dialog: " + proc);
884 return;
885 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800886
887 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
888 null, null, 0, null, null, null,
889 false, false, MY_PID, Process.SYSTEM_UID);
890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
892 mContext, proc, (HistoryRecord)data.get("activity"));
893 d.show();
894 proc.anrDialog = d;
895 }
896 } break;
897 case SHOW_FACTORY_ERROR_MSG: {
898 Dialog d = new FactoryErrorDialog(
899 mContext, msg.getData().getCharSequence("msg"));
900 d.show();
901 enableScreenAfterBoot();
902 } break;
903 case UPDATE_CONFIGURATION_MSG: {
904 final ContentResolver resolver = mContext.getContentResolver();
905 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
906 } break;
907 case GC_BACKGROUND_PROCESSES_MSG: {
908 synchronized (ActivityManagerService.this) {
909 performAppGcsIfAppropriateLocked();
910 }
911 } break;
912 case WAIT_FOR_DEBUGGER_MSG: {
913 synchronized (ActivityManagerService.this) {
914 ProcessRecord app = (ProcessRecord)msg.obj;
915 if (msg.arg1 != 0) {
916 if (!app.waitedForDebugger) {
917 Dialog d = new AppWaitingForDebuggerDialog(
918 ActivityManagerService.this,
919 mContext, app);
920 app.waitDialog = d;
921 app.waitedForDebugger = true;
922 d.show();
923 }
924 } else {
925 if (app.waitDialog != null) {
926 app.waitDialog.dismiss();
927 app.waitDialog = null;
928 }
929 }
930 }
931 } break;
932 case BROADCAST_INTENT_MSG: {
933 if (DEBUG_BROADCAST) Log.v(
934 TAG, "Received BROADCAST_INTENT_MSG");
935 processNextBroadcast(true);
936 } break;
937 case BROADCAST_TIMEOUT_MSG: {
938 broadcastTimeout();
939 } break;
940 case PAUSE_TIMEOUT_MSG: {
941 IBinder token = (IBinder)msg.obj;
942 // We don't at this point know if the activity is fullscreen,
943 // so we need to be conservative and assume it isn't.
944 Log.w(TAG, "Activity pause timeout for " + token);
945 activityPaused(token, null, true);
946 } break;
947 case IDLE_TIMEOUT_MSG: {
948 IBinder token = (IBinder)msg.obj;
949 // We don't at this point know if the activity is fullscreen,
950 // so we need to be conservative and assume it isn't.
951 Log.w(TAG, "Activity idle timeout for " + token);
952 activityIdleInternal(token, true);
953 } break;
954 case DESTROY_TIMEOUT_MSG: {
955 IBinder token = (IBinder)msg.obj;
956 // We don't at this point know if the activity is fullscreen,
957 // so we need to be conservative and assume it isn't.
958 Log.w(TAG, "Activity destroy timeout for " + token);
959 activityDestroyed(token);
960 } break;
961 case IDLE_NOW_MSG: {
962 IBinder token = (IBinder)msg.obj;
963 activityIdle(token);
964 } break;
965 case SERVICE_TIMEOUT_MSG: {
966 serviceTimeout((ProcessRecord)msg.obj);
967 } break;
968 case UPDATE_TIME_ZONE: {
969 synchronized (ActivityManagerService.this) {
970 for (int i = mLRUProcesses.size() - 1 ; i >= 0 ; i--) {
971 ProcessRecord r = mLRUProcesses.get(i);
972 if (r.thread != null) {
973 try {
974 r.thread.updateTimeZone();
975 } catch (RemoteException ex) {
976 Log.w(TAG, "Failed to update time zone for: " + r.info.processName);
977 }
978 }
979 }
980 }
981 break;
982 }
983 case SHOW_UID_ERROR_MSG: {
984 // XXX This is a temporary dialog, no need to localize.
985 AlertDialog d = new BaseErrorDialog(mContext);
986 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
987 d.setCancelable(false);
988 d.setTitle("System UIDs Inconsistent");
989 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
990 d.setButton("I'm Feeling Lucky",
991 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
992 mUidAlert = d;
993 d.show();
994 } break;
995 case IM_FEELING_LUCKY_MSG: {
996 if (mUidAlert != null) {
997 mUidAlert.dismiss();
998 mUidAlert = null;
999 }
1000 } break;
1001 case LAUNCH_TIMEOUT_MSG: {
1002 synchronized (ActivityManagerService.this) {
1003 if (mLaunchingActivity.isHeld()) {
1004 Log.w(TAG, "Launch timeout has expired, giving up wake lock!");
1005 mLaunchingActivity.release();
1006 }
1007 }
1008 } break;
1009 case SERVICE_ERROR_MSG: {
1010 ServiceRecord srv = (ServiceRecord)msg.obj;
1011 // This needs to be *un*synchronized to avoid deadlock.
1012 Checkin.logEvent(mContext.getContentResolver(),
1013 Checkin.Events.Tag.SYSTEM_SERVICE_LOOPING,
1014 srv.name.toShortString());
1015 } break;
1016 case RESUME_TOP_ACTIVITY_MSG: {
1017 synchronized (ActivityManagerService.this) {
1018 resumeTopActivityLocked(null);
1019 }
1020 }
1021 case PROC_START_TIMEOUT_MSG: {
1022 ProcessRecord app = (ProcessRecord)msg.obj;
1023 synchronized (ActivityManagerService.this) {
1024 processStartTimedOutLocked(app);
1025 }
1026 }
1027 }
1028 }
1029 };
1030
1031 public static void setSystemProcess() {
1032 try {
1033 ActivityManagerService m = mSelf;
1034
1035 ServiceManager.addService("activity", m);
1036 ServiceManager.addService("meminfo", new MemBinder(m));
1037 if (MONITOR_CPU_USAGE) {
1038 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1039 }
1040 ServiceManager.addService("activity.broadcasts", new BroadcastsBinder(m));
1041 ServiceManager.addService("activity.services", new ServicesBinder(m));
1042 ServiceManager.addService("activity.senders", new SendersBinder(m));
1043 ServiceManager.addService("activity.providers", new ProvidersBinder(m));
1044 ServiceManager.addService("permission", new PermissionController(m));
1045
1046 ApplicationInfo info =
1047 mSelf.mContext.getPackageManager().getApplicationInfo(
1048 "android", PackageManager.GET_SHARED_LIBRARY_FILES);
1049 synchronized (mSelf) {
1050 ProcessRecord app = mSelf.newProcessRecordLocked(
1051 mSystemThread.getApplicationThread(), info,
1052 info.processName);
1053 app.persistent = true;
1054 app.pid = Process.myPid();
1055 app.maxAdj = SYSTEM_ADJ;
1056 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1057 synchronized (mSelf.mPidsSelfLocked) {
1058 mSelf.mPidsSelfLocked.put(app.pid, app);
1059 }
1060 mSelf.updateLRUListLocked(app, true);
1061 }
1062 } catch (PackageManager.NameNotFoundException e) {
1063 throw new RuntimeException(
1064 "Unable to find android system package", e);
1065 }
1066 }
1067
1068 public void setWindowManager(WindowManagerService wm) {
1069 mWindowManager = wm;
1070 }
1071
1072 public static final Context main(int factoryTest) {
1073 AThread thr = new AThread();
1074 thr.start();
1075
1076 synchronized (thr) {
1077 while (thr.mService == null) {
1078 try {
1079 thr.wait();
1080 } catch (InterruptedException e) {
1081 }
1082 }
1083 }
1084
1085 ActivityManagerService m = thr.mService;
1086 mSelf = m;
1087 ActivityThread at = ActivityThread.systemMain();
1088 mSystemThread = at;
1089 Context context = at.getSystemContext();
1090 m.mContext = context;
1091 m.mFactoryTest = factoryTest;
1092 PowerManager pm =
1093 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1094 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1095 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1096 m.mLaunchingActivity.setReferenceCounted(false);
1097
1098 m.mBatteryStatsService.publish(context);
1099 m.mUsageStatsService.publish(context);
1100
1101 synchronized (thr) {
1102 thr.mReady = true;
1103 thr.notifyAll();
1104 }
1105
1106 m.startRunning(null, null, null, null);
1107
1108 return context;
1109 }
1110
1111 public static ActivityManagerService self() {
1112 return mSelf;
1113 }
1114
1115 static class AThread extends Thread {
1116 ActivityManagerService mService;
1117 boolean mReady = false;
1118
1119 public AThread() {
1120 super("ActivityManager");
1121 }
1122
1123 public void run() {
1124 Looper.prepare();
1125
1126 android.os.Process.setThreadPriority(
1127 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1128
1129 ActivityManagerService m = new ActivityManagerService();
1130
1131 synchronized (this) {
1132 mService = m;
1133 notifyAll();
1134 }
1135
1136 synchronized (this) {
1137 while (!mReady) {
1138 try {
1139 wait();
1140 } catch (InterruptedException e) {
1141 }
1142 }
1143 }
1144
1145 Looper.loop();
1146 }
1147 }
1148
1149 static class BroadcastsBinder extends Binder {
1150 ActivityManagerService mActivityManagerService;
1151 BroadcastsBinder(ActivityManagerService activityManagerService) {
1152 mActivityManagerService = activityManagerService;
1153 }
1154
1155 @Override
1156 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1157 mActivityManagerService.dumpBroadcasts(pw);
1158 }
1159 }
1160
1161 static class ServicesBinder extends Binder {
1162 ActivityManagerService mActivityManagerService;
1163 ServicesBinder(ActivityManagerService activityManagerService) {
1164 mActivityManagerService = activityManagerService;
1165 }
1166
1167 @Override
1168 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1169 mActivityManagerService.dumpServices(pw);
1170 }
1171 }
1172
1173 static class SendersBinder extends Binder {
1174 ActivityManagerService mActivityManagerService;
1175 SendersBinder(ActivityManagerService activityManagerService) {
1176 mActivityManagerService = activityManagerService;
1177 }
1178
1179 @Override
1180 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1181 mActivityManagerService.dumpSenders(pw);
1182 }
1183 }
1184
1185 static class ProvidersBinder extends Binder {
1186 ActivityManagerService mActivityManagerService;
1187 ProvidersBinder(ActivityManagerService activityManagerService) {
1188 mActivityManagerService = activityManagerService;
1189 }
1190
1191 @Override
1192 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1193 mActivityManagerService.dumpProviders(pw);
1194 }
1195 }
1196
1197 static class MemBinder extends Binder {
1198 ActivityManagerService mActivityManagerService;
1199 MemBinder(ActivityManagerService activityManagerService) {
1200 mActivityManagerService = activityManagerService;
1201 }
1202
1203 @Override
1204 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1205 ActivityManagerService service = mActivityManagerService;
1206 ArrayList<ProcessRecord> procs;
1207 synchronized (mActivityManagerService) {
1208 if (args != null && args.length > 0
1209 && args[0].charAt(0) != '-') {
1210 procs = new ArrayList<ProcessRecord>();
1211 int pid = -1;
1212 try {
1213 pid = Integer.parseInt(args[0]);
1214 } catch (NumberFormatException e) {
1215
1216 }
1217 for (int i=0; i<service.mLRUProcesses.size(); i++) {
1218 ProcessRecord proc = service.mLRUProcesses.get(i);
1219 if (proc.pid == pid) {
1220 procs.add(proc);
1221 } else if (proc.processName.equals(args[0])) {
1222 procs.add(proc);
1223 }
1224 }
1225 if (procs.size() <= 0) {
1226 pw.println("No process found for: " + args[0]);
1227 return;
1228 }
1229 } else {
1230 procs = service.mLRUProcesses;
1231 }
1232 }
1233 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1234 }
1235 }
1236
1237 static class CpuBinder extends Binder {
1238 ActivityManagerService mActivityManagerService;
1239 CpuBinder(ActivityManagerService activityManagerService) {
1240 mActivityManagerService = activityManagerService;
1241 }
1242
1243 @Override
1244 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1245 synchronized (mActivityManagerService.mProcessStatsThread) {
1246 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1247 }
1248 }
1249 }
1250
1251 private ActivityManagerService() {
1252 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1253 if (v != null && Integer.getInteger(v) != 0) {
1254 mSimpleProcessManagement = true;
1255 }
1256 v = System.getenv("ANDROID_DEBUG_APP");
1257 if (v != null) {
1258 mSimpleProcessManagement = true;
1259 }
1260
1261 MY_PID = Process.myPid();
1262
1263 File dataDir = Environment.getDataDirectory();
1264 File systemDir = new File(dataDir, "system");
1265 systemDir.mkdirs();
1266 mBatteryStatsService = new BatteryStatsService(new File(
1267 systemDir, "batterystats.bin").toString());
1268 mBatteryStatsService.getActiveStatistics().readLocked();
1269 mBatteryStatsService.getActiveStatistics().writeLocked();
1270
1271 mUsageStatsService = new UsageStatsService( new File(
1272 systemDir, "usagestats.bin").toString());
1273
1274 mConfiguration.makeDefault();
1275 mProcessStats.init();
1276
1277 // Add ourself to the Watchdog monitors.
1278 Watchdog.getInstance().addMonitor(this);
1279
1280 // These values are set in system/rootdir/init.rc on startup.
1281 FOREGROUND_APP_ADJ =
1282 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
1283 VISIBLE_APP_ADJ =
1284 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
1285 SECONDARY_SERVER_ADJ =
1286 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
The Android Open Source Project4df24232009-03-05 14:34:35 -08001287 HOME_APP_ADJ =
1288 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 HIDDEN_APP_MIN_ADJ =
1290 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
1291 CONTENT_PROVIDER_ADJ =
1292 Integer.valueOf(SystemProperties.get("ro.CONTENT_PROVIDER_ADJ"));
1293 HIDDEN_APP_MAX_ADJ = CONTENT_PROVIDER_ADJ-1;
1294 EMPTY_APP_ADJ =
1295 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
1296 FOREGROUND_APP_MEM =
1297 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
1298 VISIBLE_APP_MEM =
1299 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
1300 SECONDARY_SERVER_MEM =
1301 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
The Android Open Source Project4df24232009-03-05 14:34:35 -08001302 HOME_APP_MEM =
1303 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304 HIDDEN_APP_MEM =
1305 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
1306 EMPTY_APP_MEM =
1307 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
1308
1309 mProcessStatsThread = new Thread("ProcessStats") {
1310 public void run() {
1311 while (true) {
1312 try {
1313 try {
1314 synchronized(this) {
1315 final long now = SystemClock.uptimeMillis();
1316 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1317 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
1318 //Log.i(TAG, "Cpu delay=" + nextCpuDelay
1319 // + ", write delay=" + nextWriteDelay);
1320 if (nextWriteDelay < nextCpuDelay) {
1321 nextCpuDelay = nextWriteDelay;
1322 }
1323 if (nextCpuDelay > 0) {
1324 this.wait(nextCpuDelay);
1325 }
1326 }
1327 } catch (InterruptedException e) {
1328 }
1329
1330 updateCpuStatsNow();
1331 } catch (Exception e) {
1332 Log.e(TAG, "Unexpected exception collecting process stats", e);
1333 }
1334 }
1335 }
1336 };
1337 mProcessStatsThread.start();
1338 }
1339
1340 @Override
1341 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1342 throws RemoteException {
1343 try {
1344 return super.onTransact(code, data, reply, flags);
1345 } catch (RuntimeException e) {
1346 // The activity manager only throws security exceptions, so let's
1347 // log all others.
1348 if (!(e instanceof SecurityException)) {
1349 Log.e(TAG, "Activity Manager Crash", e);
1350 }
1351 throw e;
1352 }
1353 }
1354
1355 void updateCpuStats() {
1356 synchronized (mProcessStatsThread) {
1357 final long now = SystemClock.uptimeMillis();
1358 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1359 mProcessStatsThread.notify();
1360 }
1361 }
1362 }
1363
1364 void updateCpuStatsNow() {
1365 synchronized (mProcessStatsThread) {
1366 final long now = SystemClock.uptimeMillis();
1367 boolean haveNewCpuStats = false;
1368
1369 if (MONITOR_CPU_USAGE &&
1370 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1371 mLastCpuTime = now;
1372 haveNewCpuStats = true;
1373 mProcessStats.update();
1374 //Log.i(TAG, mProcessStats.printCurrentState());
1375 //Log.i(TAG, "Total CPU usage: "
1376 // + mProcessStats.getTotalCpuPercent() + "%");
1377
1378 // Log the cpu usage if the property is set.
1379 if ("true".equals(SystemProperties.get("events.cpu"))) {
1380 int user = mProcessStats.getLastUserTime();
1381 int system = mProcessStats.getLastSystemTime();
1382 int iowait = mProcessStats.getLastIoWaitTime();
1383 int irq = mProcessStats.getLastIrqTime();
1384 int softIrq = mProcessStats.getLastSoftIrqTime();
1385 int idle = mProcessStats.getLastIdleTime();
1386
1387 int total = user + system + iowait + irq + softIrq + idle;
1388 if (total == 0) total = 1;
1389
1390 EventLog.writeEvent(LOG_CPU,
1391 ((user+system+iowait+irq+softIrq) * 100) / total,
1392 (user * 100) / total,
1393 (system * 100) / total,
1394 (iowait * 100) / total,
1395 (irq * 100) / total,
1396 (softIrq * 100) / total);
1397 }
1398 }
1399
1400 synchronized(mBatteryStatsService.getActiveStatistics()) {
1401 synchronized(mPidsSelfLocked) {
1402 if (haveNewCpuStats) {
1403 if (mBatteryStatsService.isOnBattery()) {
1404 final int N = mProcessStats.countWorkingStats();
1405 for (int i=0; i<N; i++) {
1406 ProcessStats.Stats st
1407 = mProcessStats.getWorkingStats(i);
1408 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1409 if (pr != null) {
1410 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1411 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
1412 }
1413 }
1414 }
1415 }
1416 }
1417
1418 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1419 mLastWriteTime = now;
1420 mBatteryStatsService.getActiveStatistics().writeLocked();
1421 }
1422 }
1423 }
1424 }
1425
1426 /**
1427 * Initialize the application bind args. These are passed to each
1428 * process when the bindApplication() IPC is sent to the process. They're
1429 * lazily setup to make sure the services are running when they're asked for.
1430 */
1431 private HashMap<String, IBinder> getCommonServicesLocked() {
1432 if (mAppBindArgs == null) {
1433 mAppBindArgs = new HashMap<String, IBinder>();
1434
1435 // Setup the application init args
1436 mAppBindArgs.put("package", ServiceManager.getService("package"));
1437 mAppBindArgs.put("window", ServiceManager.getService("window"));
1438 mAppBindArgs.put(Context.ALARM_SERVICE,
1439 ServiceManager.getService(Context.ALARM_SERVICE));
1440 }
1441 return mAppBindArgs;
1442 }
1443
1444 private final void setFocusedActivityLocked(HistoryRecord r) {
1445 if (mFocusedActivity != r) {
1446 mFocusedActivity = r;
1447 mWindowManager.setFocusedApp(r, true);
1448 }
1449 }
1450
1451 private final void updateLRUListLocked(ProcessRecord app,
1452 boolean oomAdj) {
1453 // put it on the LRU to keep track of when it should be exited.
1454 int lrui = mLRUProcesses.indexOf(app);
1455 if (lrui >= 0) mLRUProcesses.remove(lrui);
1456 mLRUProcesses.add(app);
1457 //Log.i(TAG, "Putting proc to front: " + app.processName);
1458 if (oomAdj) {
1459 updateOomAdjLocked();
1460 }
1461 }
1462
1463 private final boolean updateLRUListLocked(HistoryRecord r) {
1464 final boolean hadit = mLRUActivities.remove(r);
1465 mLRUActivities.add(r);
1466 return hadit;
1467 }
1468
1469 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1470 int i = mHistory.size()-1;
1471 while (i >= 0) {
1472 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1473 if (!r.finishing && r != notTop) {
1474 return r;
1475 }
1476 i--;
1477 }
1478 return null;
1479 }
1480
1481 /**
1482 * This is a simplified version of topRunningActivityLocked that provides a number of
1483 * optional skip-over modes. It is intended for use with the ActivityWatcher hook only.
1484 *
1485 * @param token If non-null, any history records matching this token will be skipped.
1486 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1487 *
1488 * @return Returns the HistoryRecord of the next activity on the stack.
1489 */
1490 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1491 int i = mHistory.size()-1;
1492 while (i >= 0) {
1493 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1494 // Note: the taskId check depends on real taskId fields being non-zero
1495 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1496 return r;
1497 }
1498 i--;
1499 }
1500 return null;
1501 }
1502
1503 private final ProcessRecord getProcessRecordLocked(
1504 String processName, int uid) {
1505 if (uid == Process.SYSTEM_UID) {
1506 // The system gets to run in any process. If there are multiple
1507 // processes with the same uid, just pick the first (this
1508 // should never happen).
1509 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1510 processName);
1511 return procs != null ? procs.valueAt(0) : null;
1512 }
1513 ProcessRecord proc = mProcessNames.get(processName, uid);
1514 return proc;
1515 }
1516
1517 private boolean isNextTransitionForward() {
1518 int transit = mWindowManager.getPendingAppTransition();
1519 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1520 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1521 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1522 }
1523
1524 private final boolean realStartActivityLocked(HistoryRecord r,
1525 ProcessRecord app, boolean andResume, boolean checkConfig)
1526 throws RemoteException {
1527
1528 r.startFreezingScreenLocked(app, 0);
1529 mWindowManager.setAppVisibility(r, true);
1530
1531 // Have the window manager re-evaluate the orientation of
1532 // the screen based on the new activity order. Note that
1533 // as a result of this, it can call back into the activity
1534 // manager with a new orientation. We don't care about that,
1535 // because the activity is not currently running so we are
1536 // just restarting it anyway.
1537 if (checkConfig) {
1538 Configuration config = mWindowManager.updateOrientationFromAppTokens(
1539 r.mayFreezeScreenLocked(app) ? r : null);
1540 updateConfigurationLocked(config, r);
1541 }
1542
1543 r.app = app;
1544
1545 if (localLOGV) Log.v(TAG, "Launching: " + r);
1546
1547 int idx = app.activities.indexOf(r);
1548 if (idx < 0) {
1549 app.activities.add(r);
1550 }
1551 updateLRUListLocked(app, true);
1552
1553 try {
1554 if (app.thread == null) {
1555 throw new RemoteException();
1556 }
1557 List<ResultInfo> results = null;
1558 List<Intent> newIntents = null;
1559 if (andResume) {
1560 results = r.results;
1561 newIntents = r.newIntents;
1562 }
1563 if (DEBUG_SWITCH) Log.v(TAG, "Launching: " + r
1564 + " icicle=" + r.icicle
1565 + " with results=" + results + " newIntents=" + newIntents
1566 + " andResume=" + andResume);
1567 if (andResume) {
1568 EventLog.writeEvent(LOG_AM_RESTART_ACTIVITY,
1569 System.identityHashCode(r),
1570 r.task.taskId, r.shortComponentName);
1571 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001572 if (r.isHomeActivity) {
1573 mHomeProcess = app;
1574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
1576 r.info, r.icicle, results, newIntents, !andResume,
1577 isNextTransitionForward());
1578 // Update usage stats for launched activity
1579 updateUsageStats(r, true);
1580 } catch (RemoteException e) {
1581 if (r.launchFailed) {
1582 // This is the second time we failed -- finish activity
1583 // and give up.
1584 Log.e(TAG, "Second failure launching "
1585 + r.intent.getComponent().flattenToShortString()
1586 + ", giving up", e);
1587 appDiedLocked(app, app.pid, app.thread);
1588 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1589 "2nd-crash");
1590 return false;
1591 }
1592
1593 // This is the first time we failed -- restart process and
1594 // retry.
1595 app.activities.remove(r);
1596 throw e;
1597 }
1598
1599 r.launchFailed = false;
1600 if (updateLRUListLocked(r)) {
1601 Log.w(TAG, "Activity " + r
1602 + " being launched, but already in LRU list");
1603 }
1604
1605 if (andResume) {
1606 // As part of the process of launching, ActivityThread also performs
1607 // a resume.
1608 r.state = ActivityState.RESUMED;
1609 r.icicle = null;
1610 r.haveState = false;
1611 r.stopped = false;
1612 mResumedActivity = r;
1613 r.task.touchActiveTime();
1614 completeResumeLocked(r);
1615 pauseIfSleepingLocked();
1616 } else {
1617 // This activity is not starting in the resumed state... which
1618 // should look like we asked it to pause+stop (but remain visible),
1619 // and it has done so and reported back the current icicle and
1620 // other state.
1621 r.state = ActivityState.STOPPED;
1622 r.stopped = true;
1623 }
1624
1625 return true;
1626 }
1627
1628 private final void startSpecificActivityLocked(HistoryRecord r,
1629 boolean andResume, boolean checkConfig) {
1630 // Is this activity's application already running?
1631 ProcessRecord app = getProcessRecordLocked(r.processName,
1632 r.info.applicationInfo.uid);
1633
1634 if (r.startTime == 0) {
1635 r.startTime = SystemClock.uptimeMillis();
1636 }
1637
1638 if (app != null && app.thread != null) {
1639 try {
1640 realStartActivityLocked(r, app, andResume, checkConfig);
1641 return;
1642 } catch (RemoteException e) {
1643 Log.w(TAG, "Exception when starting activity "
1644 + r.intent.getComponent().flattenToShortString(), e);
1645 }
1646
1647 // If a dead object exception was thrown -- fall through to
1648 // restart the application.
1649 }
1650
1651 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
1652 "activity", r.intent.getComponent());
1653 }
1654
1655 private final ProcessRecord startProcessLocked(String processName,
1656 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
1657 String hostingType, ComponentName hostingName) {
1658 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1659 // We don't have to do anything more if:
1660 // (1) There is an existing application record; and
1661 // (2) The caller doesn't think it is dead, OR there is no thread
1662 // object attached to it so we know it couldn't have crashed; and
1663 // (3) There is a pid assigned to it, so it is either starting or
1664 // already running.
1665 if (DEBUG_PROCESSES) Log.v(TAG, "startProcess: name=" + processName
1666 + " app=" + app + " knownToBeDead=" + knownToBeDead
1667 + " thread=" + (app != null ? app.thread : null)
1668 + " pid=" + (app != null ? app.pid : -1));
1669 if (app != null &&
1670 (!knownToBeDead || app.thread == null) && app.pid > 0) {
1671 return app;
1672 }
1673
1674 String hostingNameStr = hostingName != null
1675 ? hostingName.flattenToShortString() : null;
1676
1677 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1678 // If we are in the background, then check to see if this process
1679 // is bad. If so, we will just silently fail.
1680 if (mBadProcesses.get(info.processName, info.uid) != null) {
1681 return null;
1682 }
1683 } else {
1684 // When the user is explicitly starting a process, then clear its
1685 // crash count so that we won't make it bad until they see at
1686 // least one crash dialog again, and make the process good again
1687 // if it had been bad.
1688 mProcessCrashTimes.remove(info.processName, info.uid);
1689 if (mBadProcesses.get(info.processName, info.uid) != null) {
1690 EventLog.writeEvent(LOG_AM_PROCESS_GOOD, info.uid,
1691 info.processName);
1692 mBadProcesses.remove(info.processName, info.uid);
1693 if (app != null) {
1694 app.bad = false;
1695 }
1696 }
1697 }
1698
1699 if (app == null) {
1700 app = newProcessRecordLocked(null, info, processName);
1701 mProcessNames.put(processName, info.uid, app);
1702 } else {
1703 // If this is a new package in the process, add the package to the list
1704 app.addPackage(info.packageName);
1705 }
1706
1707 // If the system is not ready yet, then hold off on starting this
1708 // process until it is.
1709 if (!mSystemReady
1710 && (info.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
1711 if (!mProcessesOnHold.contains(app)) {
1712 mProcessesOnHold.add(app);
1713 }
1714 return app;
1715 }
1716
1717 startProcessLocked(app, hostingType, hostingNameStr);
1718 return (app.pid != 0) ? app : null;
1719 }
1720
1721 private final void startProcessLocked(ProcessRecord app,
1722 String hostingType, String hostingNameStr) {
1723 if (app.pid > 0 && app.pid != MY_PID) {
1724 synchronized (mPidsSelfLocked) {
1725 mPidsSelfLocked.remove(app.pid);
1726 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1727 }
1728 app.pid = 0;
1729 }
1730
1731 mProcessesOnHold.remove(app);
1732
1733 updateCpuStats();
1734
1735 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1736 mProcDeaths[0] = 0;
1737
1738 try {
1739 int uid = app.info.uid;
1740 int[] gids = null;
1741 try {
1742 gids = mContext.getPackageManager().getPackageGids(
1743 app.info.packageName);
1744 } catch (PackageManager.NameNotFoundException e) {
1745 Log.w(TAG, "Unable to retrieve gids", e);
1746 }
1747 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1748 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1749 && mTopComponent != null
1750 && app.processName.equals(mTopComponent.getPackageName())) {
1751 uid = 0;
1752 }
1753 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1754 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1755 uid = 0;
1756 }
1757 }
1758 int debugFlags = 0;
1759 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1760 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1761 }
1762 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1763 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1764 }
1765 if ("1".equals(SystemProperties.get("debug.assert"))) {
1766 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1767 }
1768 int pid = Process.start("android.app.ActivityThread",
1769 mSimpleProcessManagement ? app.processName : null, uid, uid,
1770 gids, debugFlags, null);
1771 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1772 synchronized (bs) {
1773 if (bs.isOnBattery()) {
1774 app.batteryStats.incStartsLocked();
1775 }
1776 }
1777
1778 EventLog.writeEvent(LOG_AM_PROCESS_START, pid, uid,
1779 app.processName, hostingType,
1780 hostingNameStr != null ? hostingNameStr : "");
1781
1782 if (app.persistent) {
1783 Watchdog.getInstance().processStarted(app, app.processName, pid);
1784 }
1785
1786 StringBuilder buf = new StringBuilder(128);
1787 buf.append("Start proc ");
1788 buf.append(app.processName);
1789 buf.append(" for ");
1790 buf.append(hostingType);
1791 if (hostingNameStr != null) {
1792 buf.append(" ");
1793 buf.append(hostingNameStr);
1794 }
1795 buf.append(": pid=");
1796 buf.append(pid);
1797 buf.append(" uid=");
1798 buf.append(uid);
1799 buf.append(" gids={");
1800 if (gids != null) {
1801 for (int gi=0; gi<gids.length; gi++) {
1802 if (gi != 0) buf.append(", ");
1803 buf.append(gids[gi]);
1804
1805 }
1806 }
1807 buf.append("}");
1808 Log.i(TAG, buf.toString());
1809 if (pid == 0 || pid == MY_PID) {
1810 // Processes are being emulated with threads.
1811 app.pid = MY_PID;
1812 app.removed = false;
1813 mStartingProcesses.add(app);
1814 } else if (pid > 0) {
1815 app.pid = pid;
1816 app.removed = false;
1817 synchronized (mPidsSelfLocked) {
1818 this.mPidsSelfLocked.put(pid, app);
1819 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1820 msg.obj = app;
1821 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1822 }
1823 } else {
1824 app.pid = 0;
1825 RuntimeException e = new RuntimeException(
1826 "Failure starting process " + app.processName
1827 + ": returned pid=" + pid);
1828 Log.e(TAG, e.getMessage(), e);
1829 }
1830 } catch (RuntimeException e) {
1831 // XXX do better error recovery.
1832 app.pid = 0;
1833 Log.e(TAG, "Failure starting process " + app.processName, e);
1834 }
1835 }
1836
1837 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
1838 if (mPausingActivity != null) {
1839 RuntimeException e = new RuntimeException();
1840 Log.e(TAG, "Trying to pause when pause is already pending for "
1841 + mPausingActivity, e);
1842 }
1843 HistoryRecord prev = mResumedActivity;
1844 if (prev == null) {
1845 RuntimeException e = new RuntimeException();
1846 Log.e(TAG, "Trying to pause when nothing is resumed", e);
1847 resumeTopActivityLocked(null);
1848 return;
1849 }
1850 if (DEBUG_PAUSE) Log.v(TAG, "Start pausing: " + prev);
1851 mResumedActivity = null;
1852 mPausingActivity = prev;
1853 mLastPausedActivity = prev;
1854 prev.state = ActivityState.PAUSING;
1855 prev.task.touchActiveTime();
1856
1857 updateCpuStats();
1858
1859 if (prev.app != null && prev.app.thread != null) {
1860 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending pause: " + prev);
1861 try {
1862 EventLog.writeEvent(LOG_AM_PAUSE_ACTIVITY,
1863 System.identityHashCode(prev),
1864 prev.shortComponentName);
1865 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
1866 prev.configChangeFlags);
1867 updateUsageStats(prev, false);
1868 } catch (Exception e) {
1869 // Ignore exception, if process died other code will cleanup.
1870 Log.w(TAG, "Exception thrown during pause", e);
1871 mPausingActivity = null;
1872 mLastPausedActivity = null;
1873 }
1874 } else {
1875 mPausingActivity = null;
1876 mLastPausedActivity = null;
1877 }
1878
1879 // If we are not going to sleep, we want to ensure the device is
1880 // awake until the next activity is started.
1881 if (!mSleeping) {
1882 mLaunchingActivity.acquire();
1883 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1884 // To be safe, don't allow the wake lock to be held for too long.
1885 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1886 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
1887 }
1888 }
1889
1890
1891 if (mPausingActivity != null) {
1892 // Have the window manager pause its key dispatching until the new
1893 // activity has started. If we're pausing the activity just because
1894 // the screen is being turned off and the UI is sleeping, don't interrupt
1895 // key dispatch; the same activity will pick it up again on wakeup.
1896 if (!uiSleeping) {
1897 prev.pauseKeyDispatchingLocked();
1898 } else {
1899 if (DEBUG_PAUSE) Log.v(TAG, "Key dispatch not paused for screen off");
1900 }
1901
1902 // Schedule a pause timeout in case the app doesn't respond.
1903 // We don't give it much time because this directly impacts the
1904 // responsiveness seen by the user.
1905 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
1906 msg.obj = prev;
1907 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
1908 if (DEBUG_PAUSE) Log.v(TAG, "Waiting for pause to complete...");
1909 } else {
1910 // This activity failed to schedule the
1911 // pause, so just treat it as being paused now.
1912 if (DEBUG_PAUSE) Log.v(TAG, "Activity not running, resuming next.");
1913 resumeTopActivityLocked(null);
1914 }
1915 }
1916
1917 private final void completePauseLocked() {
1918 HistoryRecord prev = mPausingActivity;
1919 if (DEBUG_PAUSE) Log.v(TAG, "Complete pause: " + prev);
1920
1921 if (prev != null) {
1922 if (prev.finishing) {
1923 if (DEBUG_PAUSE) Log.v(TAG, "Executing finish of activity: " + prev);
1924 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
1925 } else if (prev.app != null) {
1926 if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending stop: " + prev);
1927 if (prev.waitingVisible) {
1928 prev.waitingVisible = false;
1929 mWaitingVisibleActivities.remove(prev);
1930 if (DEBUG_SWITCH || DEBUG_PAUSE) Log.v(
1931 TAG, "Complete pause, no longer waiting: " + prev);
1932 }
1933 if (prev.configDestroy) {
1934 // The previous is being paused because the configuration
1935 // is changing, which means it is actually stopping...
1936 // To juggle the fact that we are also starting a new
1937 // instance right now, we need to first completely stop
1938 // the current instance before starting the new one.
1939 if (DEBUG_PAUSE) Log.v(TAG, "Destroying after pause: " + prev);
1940 destroyActivityLocked(prev, true);
1941 } else {
1942 mStoppingActivities.add(prev);
1943 if (mStoppingActivities.size() > 3) {
1944 // If we already have a few activities waiting to stop,
1945 // then give up on things going idle and start clearing
1946 // them out.
1947 if (DEBUG_PAUSE) Log.v(TAG, "To many pending stops, forcing idle");
1948 Message msg = Message.obtain();
1949 msg.what = ActivityManagerService.IDLE_NOW_MSG;
1950 mHandler.sendMessage(msg);
1951 }
1952 }
1953 } else {
1954 if (DEBUG_PAUSE) Log.v(TAG, "App died during pause, not stopping: " + prev);
1955 prev = null;
1956 }
1957 mPausingActivity = null;
1958 }
1959
1960 if (!mSleeping) {
1961 resumeTopActivityLocked(prev);
1962 } else {
1963 if (mGoingToSleep.isHeld()) {
1964 mGoingToSleep.release();
1965 }
1966 }
1967
1968 if (prev != null) {
1969 prev.resumeKeyDispatchingLocked();
1970 }
1971 }
1972
1973 /**
1974 * Once we know that we have asked an application to put an activity in
1975 * the resumed state (either by launching it or explicitly telling it),
1976 * this function updates the rest of our state to match that fact.
1977 */
1978 private final void completeResumeLocked(HistoryRecord next) {
1979 next.idle = false;
1980 next.results = null;
1981 next.newIntents = null;
1982
1983 // schedule an idle timeout in case the app doesn't do it for us.
1984 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1985 msg.obj = next;
1986 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
1987
1988 if (false) {
1989 // The activity was never told to pause, so just keep
1990 // things going as-is. To maintain our own state,
1991 // we need to emulate it coming back and saying it is
1992 // idle.
1993 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
1994 msg.obj = next;
1995 mHandler.sendMessage(msg);
1996 }
1997
1998 next.thumbnail = null;
1999 setFocusedActivityLocked(next);
2000 next.resumeKeyDispatchingLocked();
2001 ensureActivitiesVisibleLocked(null, 0);
2002 mWindowManager.executeAppTransition();
2003 }
2004
2005 /**
2006 * Make sure that all activities that need to be visible (that is, they
2007 * currently can be seen by the user) actually are.
2008 */
2009 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2010 HistoryRecord starting, String onlyThisProcess, int configChanges) {
2011 if (DEBUG_VISBILITY) Log.v(
2012 TAG, "ensureActivitiesVisible behind " + top
2013 + " configChanges=0x" + Integer.toHexString(configChanges));
2014
2015 // If the top activity is not fullscreen, then we need to
2016 // make sure any activities under it are now visible.
2017 final int count = mHistory.size();
2018 int i = count-1;
2019 while (mHistory.get(i) != top) {
2020 i--;
2021 }
2022 HistoryRecord r;
2023 boolean behindFullscreen = false;
2024 for (; i>=0; i--) {
2025 r = (HistoryRecord)mHistory.get(i);
2026 if (DEBUG_VISBILITY) Log.v(
2027 TAG, "Make visible? " + r + " finishing=" + r.finishing
2028 + " state=" + r.state);
2029 if (r.finishing) {
2030 continue;
2031 }
2032
2033 final boolean doThisProcess = onlyThisProcess == null
2034 || onlyThisProcess.equals(r.processName);
2035
2036 // First: if this is not the current activity being started, make
2037 // sure it matches the current configuration.
2038 if (r != starting && doThisProcess) {
2039 ensureActivityConfigurationLocked(r, 0);
2040 }
2041
2042 if (r.app == null || r.app.thread == null) {
2043 if (onlyThisProcess == null
2044 || onlyThisProcess.equals(r.processName)) {
2045 // This activity needs to be visible, but isn't even
2046 // running... get it started, but don't resume it
2047 // at this point.
2048 if (DEBUG_VISBILITY) Log.v(
2049 TAG, "Start and freeze screen for " + r);
2050 if (r != starting) {
2051 r.startFreezingScreenLocked(r.app, configChanges);
2052 }
2053 if (!r.visible) {
2054 if (DEBUG_VISBILITY) Log.v(
2055 TAG, "Starting and making visible: " + r);
2056 mWindowManager.setAppVisibility(r, true);
2057 }
2058 if (r != starting) {
2059 startSpecificActivityLocked(r, false, false);
2060 }
2061 }
2062
2063 } else if (r.visible) {
2064 // If this activity is already visible, then there is nothing
2065 // else to do here.
2066 if (DEBUG_VISBILITY) Log.v(
2067 TAG, "Skipping: already visible at " + r);
2068 r.stopFreezingScreenLocked(false);
2069
2070 } else if (onlyThisProcess == null) {
2071 // This activity is not currently visible, but is running.
2072 // Tell it to become visible.
2073 r.visible = true;
2074 if (r.state != ActivityState.RESUMED && r != starting) {
2075 // If this activity is paused, tell it
2076 // to now show its window.
2077 if (DEBUG_VISBILITY) Log.v(
2078 TAG, "Making visible and scheduling visibility: " + r);
2079 try {
2080 mWindowManager.setAppVisibility(r, true);
2081 r.app.thread.scheduleWindowVisibility(r, true);
2082 r.stopFreezingScreenLocked(false);
2083 } catch (Exception e) {
2084 // Just skip on any failure; we'll make it
2085 // visible when it next restarts.
2086 Log.w(TAG, "Exception thrown making visibile: "
2087 + r.intent.getComponent(), e);
2088 }
2089 }
2090 }
2091
2092 // Aggregate current change flags.
2093 configChanges |= r.configChangeFlags;
2094
2095 if (r.fullscreen) {
2096 // At this point, nothing else needs to be shown
2097 if (DEBUG_VISBILITY) Log.v(
2098 TAG, "Stopping: fullscreen at " + r);
2099 behindFullscreen = true;
2100 i--;
2101 break;
2102 }
2103 }
2104
2105 // Now for any activities that aren't visible to the user, make
2106 // sure they no longer are keeping the screen frozen.
2107 while (i >= 0) {
2108 r = (HistoryRecord)mHistory.get(i);
2109 if (DEBUG_VISBILITY) Log.v(
2110 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2111 + " state=" + r.state
2112 + " behindFullscreen=" + behindFullscreen);
2113 if (!r.finishing) {
2114 if (behindFullscreen) {
2115 if (r.visible) {
2116 if (DEBUG_VISBILITY) Log.v(
2117 TAG, "Making invisible: " + r);
2118 r.visible = false;
2119 try {
2120 mWindowManager.setAppVisibility(r, false);
2121 if ((r.state == ActivityState.STOPPING
2122 || r.state == ActivityState.STOPPED)
2123 && r.app != null && r.app.thread != null) {
2124 if (DEBUG_VISBILITY) Log.v(
2125 TAG, "Scheduling invisibility: " + r);
2126 r.app.thread.scheduleWindowVisibility(r, false);
2127 }
2128 } catch (Exception e) {
2129 // Just skip on any failure; we'll make it
2130 // visible when it next restarts.
2131 Log.w(TAG, "Exception thrown making hidden: "
2132 + r.intent.getComponent(), e);
2133 }
2134 } else {
2135 if (DEBUG_VISBILITY) Log.v(
2136 TAG, "Already invisible: " + r);
2137 }
2138 } else if (r.fullscreen) {
2139 if (DEBUG_VISBILITY) Log.v(
2140 TAG, "Now behindFullscreen: " + r);
2141 behindFullscreen = true;
2142 }
2143 }
2144 i--;
2145 }
2146 }
2147
2148 /**
2149 * Version of ensureActivitiesVisible that can easily be called anywhere.
2150 */
2151 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2152 int configChanges) {
2153 HistoryRecord r = topRunningActivityLocked(null);
2154 if (r != null) {
2155 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2156 }
2157 }
2158
2159 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2160 if (resumed) {
2161 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2162 } else {
2163 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2164 }
2165 }
2166
2167 /**
2168 * Ensure that the top activity in the stack is resumed.
2169 *
2170 * @param prev The previously resumed activity, for when in the process
2171 * of pausing; can be null to call from elsewhere.
2172 *
2173 * @return Returns true if something is being resumed, or false if
2174 * nothing happened.
2175 */
2176 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2177 // Find the first activity that is not finishing.
2178 HistoryRecord next = topRunningActivityLocked(null);
2179
2180 // Remember how we'll process this pause/resume situation, and ensure
2181 // that the state is reset however we wind up proceeding.
2182 final boolean userLeaving = mUserLeaving;
2183 mUserLeaving = false;
2184
2185 if (next == null) {
2186 // There are no more activities! Let's just start up the
2187 // Launcher...
2188 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2189 && mTopAction == null) {
2190 // We are running in factory test mode, but unable to find
2191 // the factory test app, so just sit around displaying the
2192 // error message and don't try to start anything.
2193 return false;
2194 }
2195 Intent intent = new Intent(
2196 mTopAction,
2197 mTopData != null ? Uri.parse(mTopData) : null);
2198 intent.setComponent(mTopComponent);
2199 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2200 intent.addCategory(Intent.CATEGORY_HOME);
2201 }
2202 ActivityInfo aInfo =
2203 intent.resolveActivityInfo(mContext.getPackageManager(),
2204 PackageManager.GET_SHARED_LIBRARY_FILES);
2205 if (aInfo != null) {
2206 intent.setComponent(new ComponentName(
2207 aInfo.applicationInfo.packageName, aInfo.name));
2208 // Don't do this if the home app is currently being
2209 // instrumented.
2210 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2211 aInfo.applicationInfo.uid);
2212 if (app == null || app.instrumentationClass == null) {
2213 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2214 startActivityLocked(null, intent, null, null, 0, aInfo,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002215 null, null, 0, 0, 0, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216 }
2217 }
2218 return true;
2219 }
2220
2221 // If the top activity is the resumed one, nothing to do.
2222 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2223 // Make sure we have executed any pending transitions, since there
2224 // should be nothing left to do at this point.
2225 mWindowManager.executeAppTransition();
2226 return false;
2227 }
2228
2229 // If we are sleeping, and there is no resumed activity, and the top
2230 // activity is paused, well that is the state we want.
2231 if (mSleeping && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
2232 // Make sure we have executed any pending transitions, since there
2233 // should be nothing left to do at this point.
2234 mWindowManager.executeAppTransition();
2235 return false;
2236 }
2237
2238 // The activity may be waiting for stop, but that is no longer
2239 // appropriate for it.
2240 mStoppingActivities.remove(next);
2241 mWaitingVisibleActivities.remove(next);
2242
2243 if (DEBUG_SWITCH) Log.v(TAG, "Resuming " + next);
2244
2245 // If we are currently pausing an activity, then don't do anything
2246 // until that is done.
2247 if (mPausingActivity != null) {
2248 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: pausing=" + mPausingActivity);
2249 return false;
2250 }
2251
2252 // We need to start pausing the current activity so the top one
2253 // can be resumed...
2254 if (mResumedActivity != null) {
2255 if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: need to start pausing");
2256 startPausingLocked(userLeaving, false);
2257 return true;
2258 }
2259
2260 if (prev != null && prev != next) {
2261 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2262 prev.waitingVisible = true;
2263 mWaitingVisibleActivities.add(prev);
2264 if (DEBUG_SWITCH) Log.v(
2265 TAG, "Resuming top, waiting visible to hide: " + prev);
2266 } else {
2267 // The next activity is already visible, so hide the previous
2268 // activity's windows right now so we can show the new one ASAP.
2269 // We only do this if the previous is finishing, which should mean
2270 // it is on top of the one being resumed so hiding it quickly
2271 // is good. Otherwise, we want to do the normal route of allowing
2272 // the resumed activity to be shown so we can decide if the
2273 // previous should actually be hidden depending on whether the
2274 // new one is found to be full-screen or not.
2275 if (prev.finishing) {
2276 mWindowManager.setAppVisibility(prev, false);
2277 if (DEBUG_SWITCH) Log.v(TAG, "Not waiting for visible to hide: "
2278 + prev + ", waitingVisible="
2279 + (prev != null ? prev.waitingVisible : null)
2280 + ", nowVisible=" + next.nowVisible);
2281 } else {
2282 if (DEBUG_SWITCH) Log.v(TAG, "Previous already visible but still waiting to hide: "
2283 + prev + ", waitingVisible="
2284 + (prev != null ? prev.waitingVisible : null)
2285 + ", nowVisible=" + next.nowVisible);
2286 }
2287 }
2288 }
2289
2290 // We are starting up the next activity, so tell the window manager
2291 // that the previous one will be hidden soon. This way it can know
2292 // to ignore it when computing the desired screen orientation.
2293 if (prev != null) {
2294 if (prev.finishing) {
2295 if (DEBUG_TRANSITION) Log.v(TAG,
2296 "Prepare close transition: prev=" + prev);
2297 mWindowManager.prepareAppTransition(prev.task == next.task
2298 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2299 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2300 mWindowManager.setAppWillBeHidden(prev);
2301 mWindowManager.setAppVisibility(prev, false);
2302 } else {
2303 if (DEBUG_TRANSITION) Log.v(TAG,
2304 "Prepare open transition: prev=" + prev);
2305 mWindowManager.prepareAppTransition(prev.task == next.task
2306 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2307 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2308 }
2309 if (false) {
2310 mWindowManager.setAppWillBeHidden(prev);
2311 mWindowManager.setAppVisibility(prev, false);
2312 }
2313 } else if (mHistory.size() > 1) {
2314 if (DEBUG_TRANSITION) Log.v(TAG,
2315 "Prepare open transition: no previous");
2316 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2317 }
2318
2319 if (next.app != null && next.app.thread != null) {
2320 if (DEBUG_SWITCH) Log.v(TAG, "Resume running: " + next);
2321
2322 // This activity is now becoming visible.
2323 mWindowManager.setAppVisibility(next, true);
2324
2325 HistoryRecord lastResumedActivity = mResumedActivity;
2326 ActivityState lastState = next.state;
2327
2328 updateCpuStats();
2329
2330 next.state = ActivityState.RESUMED;
2331 mResumedActivity = next;
2332 next.task.touchActiveTime();
2333 updateLRUListLocked(next.app, true);
2334 updateLRUListLocked(next);
2335
2336 // Have the window manager re-evaluate the orientation of
2337 // the screen based on the new activity order.
2338 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2339 next.mayFreezeScreenLocked(next.app) ? next : null);
2340 if (config != null) {
2341 next.frozenBeforeDestroy = true;
2342 }
2343 if (!updateConfigurationLocked(config, next)) {
2344 // The configuration update wasn't able to keep the existing
2345 // instance of the activity, and instead started a new one.
2346 // We should be all done, but let's just make sure our activity
2347 // is still at the top and schedule another run if something
2348 // weird happened.
2349 HistoryRecord nextNext = topRunningActivityLocked(null);
2350 if (DEBUG_SWITCH) Log.i(TAG,
2351 "Activity config changed during resume: " + next
2352 + ", new next: " + nextNext);
2353 if (nextNext != next) {
2354 // Do over!
2355 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2356 }
2357 mWindowManager.executeAppTransition();
2358 return true;
2359 }
2360
2361 try {
2362 // Deliver all pending results.
2363 ArrayList a = next.results;
2364 if (a != null) {
2365 final int N = a.size();
2366 if (!next.finishing && N > 0) {
2367 if (localLOGV) Log.v(
2368 TAG, "Delivering results to " + next
2369 + ": " + a);
2370 next.app.thread.scheduleSendResult(next, a);
2371 }
2372 }
2373
2374 if (next.newIntents != null) {
2375 next.app.thread.scheduleNewIntent(next.newIntents, next);
2376 }
2377
2378 EventLog.writeEvent(LOG_AM_RESUME_ACTIVITY,
2379 System.identityHashCode(next),
2380 next.task.taskId, next.shortComponentName);
2381 updateUsageStats(next, true);
2382
2383 next.app.thread.scheduleResumeActivity(next,
2384 isNextTransitionForward());
2385 pauseIfSleepingLocked();
2386
2387 } catch (Exception e) {
2388 // Whoops, need to restart this activity!
2389 next.state = lastState;
2390 mResumedActivity = lastResumedActivity;
2391 if (Config.LOGD) Log.d(TAG,
2392 "Restarting because process died: " + next);
2393 if (!next.hasBeenLaunched) {
2394 next.hasBeenLaunched = true;
2395 } else {
2396 if (SHOW_APP_STARTING_ICON) {
2397 mWindowManager.setAppStartingWindow(
2398 next, next.packageName, next.theme,
2399 next.nonLocalizedLabel,
2400 next.labelRes, next.icon, null, true);
2401 }
2402 }
2403 startSpecificActivityLocked(next, true, false);
2404 return true;
2405 }
2406
2407 // From this point on, if something goes wrong there is no way
2408 // to recover the activity.
2409 try {
2410 next.visible = true;
2411 completeResumeLocked(next);
2412 } catch (Exception e) {
2413 // If any exception gets thrown, toss away this
2414 // activity and try the next one.
2415 Log.w(TAG, "Exception thrown during resume of " + next, e);
2416 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2417 "resume-exception");
2418 return true;
2419 }
2420
2421 // Didn't need to use the icicle, and it is now out of date.
2422 next.icicle = null;
2423 next.haveState = false;
2424 next.stopped = false;
2425
2426 } else {
2427 // Whoops, need to restart this activity!
2428 if (!next.hasBeenLaunched) {
2429 next.hasBeenLaunched = true;
2430 } else {
2431 if (SHOW_APP_STARTING_ICON) {
2432 mWindowManager.setAppStartingWindow(
2433 next, next.packageName, next.theme,
2434 next.nonLocalizedLabel,
2435 next.labelRes, next.icon, null, true);
2436 }
2437 if (DEBUG_SWITCH) Log.v(TAG, "Restarting: " + next);
2438 }
2439 startSpecificActivityLocked(next, true, true);
2440 }
2441
2442 return true;
2443 }
2444
2445 private final void startActivityLocked(HistoryRecord r, boolean newTask) {
2446 final int NH = mHistory.size();
2447
2448 int addPos = -1;
2449
2450 if (!newTask) {
2451 // If starting in an existing task, find where that is...
2452 HistoryRecord next = null;
2453 boolean startIt = true;
2454 for (int i = NH-1; i >= 0; i--) {
2455 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2456 if (p.finishing) {
2457 continue;
2458 }
2459 if (p.task == r.task) {
2460 // Here it is! Now, if this is not yet visible to the
2461 // user, then just add it without starting; it will
2462 // get started when the user navigates back to it.
2463 addPos = i+1;
2464 if (!startIt) {
2465 mHistory.add(addPos, r);
2466 r.inHistory = true;
2467 r.task.numActivities++;
2468 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2469 r.info.screenOrientation, r.fullscreen);
2470 if (VALIDATE_TOKENS) {
2471 mWindowManager.validateAppTokens(mHistory);
2472 }
2473 return;
2474 }
2475 break;
2476 }
2477 if (p.fullscreen) {
2478 startIt = false;
2479 }
2480 next = p;
2481 }
2482 }
2483
2484 // Place a new activity at top of stack, so it is next to interact
2485 // with the user.
2486 if (addPos < 0) {
2487 addPos = mHistory.size();
2488 }
2489
2490 // If we are not placing the new activity frontmost, we do not want
2491 // to deliver the onUserLeaving callback to the actual frontmost
2492 // activity
2493 if (addPos < NH) {
2494 mUserLeaving = false;
2495 if (DEBUG_USER_LEAVING) Log.v(TAG, "startActivity() behind front, mUserLeaving=false");
2496 }
2497
2498 // Slot the activity into the history stack and proceed
2499 mHistory.add(addPos, r);
2500 r.inHistory = true;
2501 r.frontOfTask = newTask;
2502 r.task.numActivities++;
2503 if (NH > 0) {
2504 // We want to show the starting preview window if we are
2505 // switching to a new task, or the next activity's process is
2506 // not currently running.
2507 boolean showStartingIcon = newTask;
2508 ProcessRecord proc = r.app;
2509 if (proc == null) {
2510 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2511 }
2512 if (proc == null || proc.thread == null) {
2513 showStartingIcon = true;
2514 }
2515 if (DEBUG_TRANSITION) Log.v(TAG,
2516 "Prepare open transition: starting " + r);
2517 mWindowManager.prepareAppTransition(newTask
2518 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2519 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2520 mWindowManager.addAppToken(
2521 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2522 boolean doShow = true;
2523 if (newTask) {
2524 // Even though this activity is starting fresh, we still need
2525 // to reset it to make sure we apply affinities to move any
2526 // existing activities from other tasks in to it.
2527 // If the caller has requested that the target task be
2528 // reset, then do so.
2529 if ((r.intent.getFlags()
2530 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2531 resetTaskIfNeededLocked(r, r);
2532 doShow = topRunningActivityLocked(null) == r;
2533 }
2534 }
2535 if (SHOW_APP_STARTING_ICON && doShow) {
2536 // Figure out if we are transitioning from another activity that is
2537 // "has the same starting icon" as the next one. This allows the
2538 // window manager to keep the previous window it had previously
2539 // created, if it still had one.
2540 HistoryRecord prev = mResumedActivity;
2541 if (prev != null) {
2542 // We don't want to reuse the previous starting preview if:
2543 // (1) The current activity is in a different task.
2544 if (prev.task != r.task) prev = null;
2545 // (2) The current activity is already displayed.
2546 else if (prev.nowVisible) prev = null;
2547 }
2548 mWindowManager.setAppStartingWindow(
2549 r, r.packageName, r.theme, r.nonLocalizedLabel,
2550 r.labelRes, r.icon, prev, showStartingIcon);
2551 }
2552 } else {
2553 // If this is the first activity, don't do any fancy animations,
2554 // because there is nothing for it to animate on top of.
2555 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2556 r.info.screenOrientation, r.fullscreen);
2557 }
2558 if (VALIDATE_TOKENS) {
2559 mWindowManager.validateAppTokens(mHistory);
2560 }
2561
2562 resumeTopActivityLocked(null);
2563 }
2564
2565 /**
2566 * Perform clear operation as requested by
2567 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: assuming the top task on the
2568 * stack is the one that the new activity is being launched in, look for
2569 * an instance of that activity in the stack and, if found, finish all
2570 * activities on top of it and return the instance.
2571 *
2572 * @param newR Description of the new activity being started.
2573 * @return Returns the old activity that should be continue to be used,
2574 * or null if none was found.
2575 */
2576 private final HistoryRecord performClearTopTaskLocked(int taskId,
2577 HistoryRecord newR, boolean doClear) {
2578 int i = mHistory.size();
2579 while (i > 0) {
2580 i--;
2581 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2582 if (r.finishing) {
2583 continue;
2584 }
2585 if (r.task.taskId != taskId) {
2586 return null;
2587 }
2588 if (r.realActivity.equals(newR.realActivity)) {
2589 // Here it is! Now finish everything in front...
2590 HistoryRecord ret = r;
2591 if (doClear) {
2592 while (i < (mHistory.size()-1)) {
2593 i++;
2594 r = (HistoryRecord)mHistory.get(i);
2595 if (r.finishing) {
2596 continue;
2597 }
2598 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2599 null, "clear")) {
2600 i--;
2601 }
2602 }
2603 }
2604
2605 // Finally, if this is a normal launch mode (that is, not
2606 // expecting onNewIntent()), then we will finish the current
2607 // instance of the activity so a new fresh one can be started.
2608 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE) {
2609 if (!ret.finishing) {
2610 int index = indexOfTokenLocked(ret, false);
2611 if (index >= 0) {
2612 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2613 null, "clear");
2614 }
2615 return null;
2616 }
2617 }
2618
2619 return ret;
2620 }
2621 }
2622
2623 return null;
2624 }
2625
2626 /**
2627 * Find the activity in the history stack within the given task. Returns
2628 * the index within the history at which it's found, or < 0 if not found.
2629 */
2630 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
2631 int i = mHistory.size();
2632 while (i > 0) {
2633 i--;
2634 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
2635 if (candidate.task.taskId != task) {
2636 break;
2637 }
2638 if (candidate.realActivity.equals(r.realActivity)) {
2639 return i;
2640 }
2641 }
2642
2643 return -1;
2644 }
2645
2646 /**
2647 * Reorder the history stack so that the activity at the given index is
2648 * brought to the front.
2649 */
2650 private final HistoryRecord moveActivityToFrontLocked(int where) {
2651 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
2652 int top = mHistory.size();
2653 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
2654 mHistory.add(top, newTop);
2655 oldTop.frontOfTask = false;
2656 newTop.frontOfTask = true;
2657 return newTop;
2658 }
2659
2660 /**
2661 * Deliver a new Intent to an existing activity, so that its onNewIntent()
2662 * method will be called at the proper time.
2663 */
2664 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
2665 boolean sent = false;
2666 if (r.state == ActivityState.RESUMED
2667 && r.app != null && r.app.thread != null) {
2668 try {
2669 ArrayList<Intent> ar = new ArrayList<Intent>();
2670 ar.add(new Intent(intent));
2671 r.app.thread.scheduleNewIntent(ar, r);
2672 sent = true;
2673 } catch (Exception e) {
2674 Log.w(TAG, "Exception thrown sending new intent to " + r, e);
2675 }
2676 }
2677 if (!sent) {
2678 r.addNewIntentLocked(new Intent(intent));
2679 }
2680 }
2681
2682 private final void logStartActivity(int tag, HistoryRecord r,
2683 TaskRecord task) {
2684 EventLog.writeEvent(tag,
2685 System.identityHashCode(r), task.taskId,
2686 r.shortComponentName, r.intent.getAction(),
2687 r.intent.getType(), r.intent.getDataString(),
2688 r.intent.getFlags());
2689 }
2690
2691 private final int startActivityLocked(IApplicationThread caller,
2692 Intent intent, String resolvedType,
2693 Uri[] grantedUriPermissions,
2694 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
2695 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002696 int callingPid, int callingUid, boolean onlyIfNeeded,
2697 boolean componentSpecified) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002698 Log.i(TAG, "Starting activity: " + intent);
2699
2700 HistoryRecord sourceRecord = null;
2701 HistoryRecord resultRecord = null;
2702 if (resultTo != null) {
2703 int index = indexOfTokenLocked(resultTo, false);
2704 if (localLOGV) Log.v(
2705 TAG, "Sending result to " + resultTo + " (index " + index + ")");
2706 if (index >= 0) {
2707 sourceRecord = (HistoryRecord)mHistory.get(index);
2708 if (requestCode >= 0 && !sourceRecord.finishing) {
2709 resultRecord = sourceRecord;
2710 }
2711 }
2712 }
2713
2714 int launchFlags = intent.getFlags();
2715
2716 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
2717 && sourceRecord != null) {
2718 // Transfer the result target from the source activity to the new
2719 // one being started, including any failures.
2720 if (requestCode >= 0) {
2721 return START_FORWARD_AND_REQUEST_CONFLICT;
2722 }
2723 resultRecord = sourceRecord.resultTo;
2724 resultWho = sourceRecord.resultWho;
2725 requestCode = sourceRecord.requestCode;
2726 sourceRecord.resultTo = null;
2727 if (resultRecord != null) {
2728 resultRecord.removeResultsLocked(
2729 sourceRecord, resultWho, requestCode);
2730 }
2731 }
2732
2733 int err = START_SUCCESS;
2734
2735 if (intent.getComponent() == null) {
2736 // We couldn't find a class that can handle the given Intent.
2737 // That's the end of that!
2738 err = START_INTENT_NOT_RESOLVED;
2739 }
2740
2741 if (err == START_SUCCESS && aInfo == null) {
2742 // We couldn't find the specific class specified in the Intent.
2743 // Also the end of the line.
2744 err = START_CLASS_NOT_FOUND;
2745 }
2746
2747 ProcessRecord callerApp = null;
2748 if (err == START_SUCCESS && caller != null) {
2749 callerApp = getRecordForAppLocked(caller);
2750 if (callerApp != null) {
2751 callingPid = callerApp.pid;
2752 callingUid = callerApp.info.uid;
2753 } else {
2754 Log.w(TAG, "Unable to find app for caller " + caller
2755 + " (pid=" + callingPid + ") when starting: "
2756 + intent.toString());
2757 err = START_PERMISSION_DENIED;
2758 }
2759 }
2760
2761 if (err != START_SUCCESS) {
2762 if (resultRecord != null) {
2763 sendActivityResultLocked(-1,
2764 resultRecord, resultWho, requestCode,
2765 Activity.RESULT_CANCELED, null);
2766 }
2767 return err;
2768 }
2769
2770 final int perm = checkComponentPermission(aInfo.permission, callingPid,
2771 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
2772 if (perm != PackageManager.PERMISSION_GRANTED) {
2773 if (resultRecord != null) {
2774 sendActivityResultLocked(-1,
2775 resultRecord, resultWho, requestCode,
2776 Activity.RESULT_CANCELED, null);
2777 }
2778 String msg = "Permission Denial: starting " + intent.toString()
2779 + " from " + callerApp + " (pid=" + callingPid
2780 + ", uid=" + callingUid + ")"
2781 + " requires " + aInfo.permission;
2782 Log.w(TAG, msg);
2783 throw new SecurityException(msg);
2784 }
2785
2786 if (mWatcher != null) {
2787 boolean abort = false;
2788 try {
2789 // The Intent we give to the watcher has the extra data
2790 // stripped off, since it can contain private information.
2791 Intent watchIntent = intent.cloneFilter();
2792 abort = !mWatcher.activityStarting(watchIntent,
2793 aInfo.applicationInfo.packageName);
2794 } catch (RemoteException e) {
2795 mWatcher = null;
2796 }
2797
2798 if (abort) {
2799 if (resultRecord != null) {
2800 sendActivityResultLocked(-1,
2801 resultRecord, resultWho, requestCode,
2802 Activity.RESULT_CANCELED, null);
2803 }
2804 // We pretend to the caller that it was really started, but
2805 // they will just get a cancel result.
2806 return START_SUCCESS;
2807 }
2808 }
2809
2810 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
2811 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002812 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813 r.startTime = SystemClock.uptimeMillis();
2814
2815 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
2816 != 0 ? r : null;
2817
2818 // We'll invoke onUserLeaving before onPause only if the launching
2819 // activity did not explicitly state that this is an automated launch.
2820 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
2821 if (DEBUG_USER_LEAVING) Log.v(TAG,
2822 "startActivity() => mUserLeaving=" + mUserLeaving);
2823
2824 // If the onlyIfNeeded flag is set, then we can do this if the activity
2825 // being launched is the same as the one making the call... or, as
2826 // a special case, if we do not know the caller then we count the
2827 // current top activity as the caller.
2828 if (onlyIfNeeded) {
2829 HistoryRecord checkedCaller = sourceRecord;
2830 if (checkedCaller == null) {
2831 checkedCaller = topRunningActivityLocked(notTop);
2832 }
2833 if (!checkedCaller.realActivity.equals(r.realActivity)) {
2834 // Caller is not the same as launcher, so always needed.
2835 onlyIfNeeded = false;
2836 }
2837 }
2838
2839 if (grantedUriPermissions != null && callingUid > 0) {
2840 for (int i=0; i<grantedUriPermissions.length; i++) {
2841 grantUriPermissionLocked(callingUid, r.packageName,
2842 grantedUriPermissions[i], grantedMode, r);
2843 }
2844 }
2845
2846 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
2847 intent, r);
2848
2849 if (sourceRecord == null) {
2850 // This activity is not being started from another... in this
2851 // case we -always- start a new task.
2852 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
2853 Log.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
2854 + intent);
2855 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2856 }
2857 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2858 // The original activity who is starting us is running as a single
2859 // instance... this new activity it is starting must go on its
2860 // own task.
2861 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2862 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
2863 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
2864 // The activity being started is a single instance... it always
2865 // gets launched into its own task.
2866 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2867 }
2868
2869 if (resultRecord != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
2870 // For whatever reason this activity is being launched into a new
2871 // task... yet the caller has requested a result back. Well, that
2872 // is pretty messed up, so instead immediately send back a cancel
2873 // and let the new task continue launched as normal without a
2874 // dependency on its originator.
2875 Log.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
2876 sendActivityResultLocked(-1,
2877 resultRecord, resultWho, requestCode,
2878 Activity.RESULT_CANCELED, null);
2879 r.resultTo = null;
2880 resultRecord = null;
2881 }
2882
2883 boolean addingToTask = false;
2884 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
2885 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
2886 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
2887 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2888 // If bring to front is requested, and no result is requested, and
2889 // we can find a task that was started with this same
2890 // component, then instead of launching bring that one to the front.
2891 if (resultRecord == null) {
2892 // See if there is a task to bring to the front. If this is
2893 // a SINGLE_INSTANCE activity, there can be one and only one
2894 // instance of it in the history, and it is always in its own
2895 // unique task, so we do a special search.
2896 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
2897 ? findTaskLocked(intent, r.info)
2898 : findActivityLocked(intent, r.info);
2899 if (taskTop != null) {
2900 if (taskTop.task.intent == null) {
2901 // This task was started because of movement of
2902 // the activity based on affinity... now that we
2903 // are actually launching it, we can assign the
2904 // base intent.
2905 taskTop.task.setIntent(intent, r.info);
2906 }
2907 // If the target task is not in the front, then we need
2908 // to bring it to the front... except... well, with
2909 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
2910 // to have the same behavior as if a new instance was
2911 // being started, which means not bringing it to the front
2912 // if the caller is not itself in the front.
2913 HistoryRecord curTop = topRunningActivityLocked(notTop);
2914 if (curTop.task != taskTop.task) {
2915 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
2916 boolean callerAtFront = sourceRecord == null
2917 || curTop.task == sourceRecord.task;
2918 if (callerAtFront) {
2919 // We really do want to push this one into the
2920 // user's face, right now.
2921 moveTaskToFrontLocked(taskTop.task);
2922 }
2923 }
2924 // If the caller has requested that the target task be
2925 // reset, then do so.
2926 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2927 taskTop = resetTaskIfNeededLocked(taskTop, r);
2928 }
2929 if (onlyIfNeeded) {
2930 // We don't need to start a new activity, and
2931 // the client said not to do anything if that
2932 // is the case, so this is it! And for paranoia, make
2933 // sure we have correctly resumed the top activity.
2934 resumeTopActivityLocked(null);
2935 return START_RETURN_INTENT_TO_CALLER;
2936 }
2937 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
2938 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
2939 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2940 // In this situation we want to remove all activities
2941 // from the task up to the one being started. In most
2942 // cases this means we are resetting the task to its
2943 // initial state.
2944 HistoryRecord top = performClearTopTaskLocked(
2945 taskTop.task.taskId, r, true);
2946 if (top != null) {
2947 if (top.frontOfTask) {
2948 // Activity aliases may mean we use different
2949 // intents for the top activity, so make sure
2950 // the task now has the identity of the new
2951 // intent.
2952 top.task.setIntent(r.intent, r.info);
2953 }
2954 logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
2955 deliverNewIntentLocked(top, r.intent);
2956 } else {
2957 // A special case: we need to
2958 // start the activity because it is not currently
2959 // running, and the caller has asked to clear the
2960 // current task to have this activity at the top.
2961 addingToTask = true;
2962 // Now pretend like this activity is being started
2963 // by the top of its task, so it is put in the
2964 // right place.
2965 sourceRecord = taskTop;
2966 }
2967 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
2968 // In this case the top activity on the task is the
2969 // same as the one being launched, so we take that
2970 // as a request to bring the task to the foreground.
2971 // If the top activity in the task is the root
2972 // activity, deliver this new intent to it if it
2973 // desires.
2974 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
2975 && taskTop.realActivity.equals(r.realActivity)) {
2976 logStartActivity(LOG_AM_NEW_INTENT, r, taskTop.task);
2977 if (taskTop.frontOfTask) {
2978 taskTop.task.setIntent(r.intent, r.info);
2979 }
2980 deliverNewIntentLocked(taskTop, r.intent);
2981 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
2982 // In this case we are launching the root activity
2983 // of the task, but with a different intent. We
2984 // should start a new instance on top.
2985 addingToTask = true;
2986 sourceRecord = taskTop;
2987 }
2988 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
2989 // In this case an activity is being launched in to an
2990 // existing task, without resetting that task. This
2991 // is typically the situation of launching an activity
2992 // from a notification or shortcut. We want to place
2993 // the new activity on top of the current task.
2994 addingToTask = true;
2995 sourceRecord = taskTop;
2996 } else if (!taskTop.task.rootWasReset) {
2997 // In this case we are launching in to an existing task
2998 // that has not yet been started from its front door.
2999 // The current task has been brought to the front.
3000 // Ideally, we'd probably like to place this new task
3001 // at the bottom of its stack, but that's a little hard
3002 // to do with the current organization of the code so
3003 // for now we'll just drop it.
3004 taskTop.task.setIntent(r.intent, r.info);
3005 }
3006 if (!addingToTask) {
3007 // We didn't do anything... but it was needed (a.k.a., client
3008 // don't use that intent!) And for paranoia, make
3009 // sure we have correctly resumed the top activity.
3010 resumeTopActivityLocked(null);
3011 return START_TASK_TO_FRONT;
3012 }
3013 }
3014 }
3015 }
3016
3017 //String uri = r.intent.toURI();
3018 //Intent intent2 = new Intent(uri);
3019 //Log.i(TAG, "Given intent: " + r.intent);
3020 //Log.i(TAG, "URI is: " + uri);
3021 //Log.i(TAG, "To intent: " + intent2);
3022
3023 if (r.packageName != null) {
3024 // If the activity being launched is the same as the one currently
3025 // at the top, then we need to check if it should only be launched
3026 // once.
3027 HistoryRecord top = topRunningActivityLocked(notTop);
3028 if (top != null && resultRecord == null) {
3029 if (top.realActivity.equals(r.realActivity)) {
3030 if (top.app != null && top.app.thread != null) {
3031 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3032 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3033 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3034 logStartActivity(LOG_AM_NEW_INTENT, top, top.task);
3035 // For paranoia, make sure we have correctly
3036 // resumed the top activity.
3037 resumeTopActivityLocked(null);
3038 if (onlyIfNeeded) {
3039 // We don't need to start a new activity, and
3040 // the client said not to do anything if that
3041 // is the case, so this is it!
3042 return START_RETURN_INTENT_TO_CALLER;
3043 }
3044 deliverNewIntentLocked(top, r.intent);
3045 return START_DELIVERED_TO_TOP;
3046 }
3047 }
3048 }
3049 }
3050
3051 } else {
3052 if (resultRecord != null) {
3053 sendActivityResultLocked(-1,
3054 resultRecord, resultWho, requestCode,
3055 Activity.RESULT_CANCELED, null);
3056 }
3057 return START_CLASS_NOT_FOUND;
3058 }
3059
3060 boolean newTask = false;
3061
3062 // Should this be considered a new task?
3063 if (resultRecord == null && !addingToTask
3064 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3065 // todo: should do better management of integers.
3066 mCurTask++;
3067 if (mCurTask <= 0) {
3068 mCurTask = 1;
3069 }
3070 r.task = new TaskRecord(mCurTask, r.info, intent,
3071 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3072 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3073 + " in new task " + r.task);
3074 newTask = true;
3075 addRecentTask(r.task);
3076
3077 } else if (sourceRecord != null) {
3078 if (!addingToTask &&
3079 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3080 // In this case, we are adding the activity to an existing
3081 // task, but the caller has asked to clear that task if the
3082 // activity is already running.
3083 HistoryRecord top = performClearTopTaskLocked(
3084 sourceRecord.task.taskId, r, true);
3085 if (top != null) {
3086 logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
3087 deliverNewIntentLocked(top, r.intent);
3088 // For paranoia, make sure we have correctly
3089 // resumed the top activity.
3090 resumeTopActivityLocked(null);
3091 return START_DELIVERED_TO_TOP;
3092 }
3093 } else if (!addingToTask &&
3094 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3095 // In this case, we are launching an activity in our own task
3096 // that may already be running somewhere in the history, and
3097 // we want to shuffle it to the front of the stack if so.
3098 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3099 if (where >= 0) {
3100 HistoryRecord top = moveActivityToFrontLocked(where);
3101 logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
3102 deliverNewIntentLocked(top, r.intent);
3103 resumeTopActivityLocked(null);
3104 return START_DELIVERED_TO_TOP;
3105 }
3106 }
3107 // An existing activity is starting this new activity, so we want
3108 // to keep the new one in the same task as the one that is starting
3109 // it.
3110 r.task = sourceRecord.task;
3111 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3112 + " in existing task " + r.task);
3113
3114 } else {
3115 // This not being started from an existing activity, and not part
3116 // of a new task... just put it in the top task, though these days
3117 // this case should never happen.
3118 final int N = mHistory.size();
3119 HistoryRecord prev =
3120 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3121 r.task = prev != null
3122 ? prev.task
3123 : new TaskRecord(mCurTask, r.info, intent,
3124 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
3125 if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
3126 + " in new guessed " + r.task);
3127 }
3128 if (newTask) {
3129 EventLog.writeEvent(LOG_AM_CREATE_TASK, r.task.taskId);
3130 }
3131 logStartActivity(LOG_AM_CREATE_ACTIVITY, r, r.task);
3132 startActivityLocked(r, newTask);
3133 return START_SUCCESS;
3134 }
3135
3136 public final int startActivity(IApplicationThread caller,
3137 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3138 int grantedMode, IBinder resultTo,
3139 String resultWho, int requestCode, boolean onlyIfNeeded,
3140 boolean debug) {
3141 // Refuse possible leaked file descriptors
3142 if (intent != null && intent.hasFileDescriptors()) {
3143 throw new IllegalArgumentException("File descriptors passed in Intent");
3144 }
3145
The Android Open Source Project4df24232009-03-05 14:34:35 -08003146 final boolean componentSpecified = intent.getComponent() != null;
3147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003148 // Don't modify the client's object!
3149 intent = new Intent(intent);
3150
3151 // Collect information about the target of the Intent.
3152 // Must do this before locking, because resolving the intent
3153 // may require launching a process to run its content provider.
3154 ActivityInfo aInfo;
3155 try {
3156 ResolveInfo rInfo =
3157 ActivityThread.getPackageManager().resolveIntent(
3158 intent, resolvedType,
3159 PackageManager.MATCH_DEFAULT_ONLY
3160 | PackageManager.GET_SHARED_LIBRARY_FILES);
3161 aInfo = rInfo != null ? rInfo.activityInfo : null;
3162 } catch (RemoteException e) {
3163 aInfo = null;
3164 }
3165
3166 if (aInfo != null) {
3167 // Store the found target back into the intent, because now that
3168 // we have it we never want to do this again. For example, if the
3169 // user navigates back to this point in the history, we should
3170 // always restart the exact same activity.
3171 intent.setComponent(new ComponentName(
3172 aInfo.applicationInfo.packageName, aInfo.name));
3173
3174 // Don't debug things in the system process
3175 if (debug) {
3176 if (!aInfo.processName.equals("system")) {
3177 setDebugApp(aInfo.processName, true, false);
3178 }
3179 }
3180 }
3181
3182 synchronized(this) {
3183 final long origId = Binder.clearCallingIdentity();
3184 int res = startActivityLocked(caller, intent, resolvedType,
3185 grantedUriPermissions, grantedMode, aInfo,
3186 resultTo, resultWho, requestCode, -1, -1,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003187 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003188 Binder.restoreCallingIdentity(origId);
3189 return res;
3190 }
3191 }
3192
3193 public boolean startNextMatchingActivity(IBinder callingActivity,
3194 Intent intent) {
3195 // Refuse possible leaked file descriptors
3196 if (intent != null && intent.hasFileDescriptors() == true) {
3197 throw new IllegalArgumentException("File descriptors passed in Intent");
3198 }
3199
3200 synchronized (this) {
3201 int index = indexOfTokenLocked(callingActivity, false);
3202 if (index < 0) {
3203 return false;
3204 }
3205 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3206 if (r.app == null || r.app.thread == null) {
3207 // The caller is not running... d'oh!
3208 return false;
3209 }
3210 intent = new Intent(intent);
3211 // The caller is not allowed to change the data.
3212 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3213 // And we are resetting to find the next component...
3214 intent.setComponent(null);
3215
3216 ActivityInfo aInfo = null;
3217 try {
3218 List<ResolveInfo> resolves =
3219 ActivityThread.getPackageManager().queryIntentActivities(
3220 intent, r.resolvedType,
3221 PackageManager.MATCH_DEFAULT_ONLY
3222 | PackageManager.GET_SHARED_LIBRARY_FILES);
3223
3224 // Look for the original activity in the list...
3225 final int N = resolves != null ? resolves.size() : 0;
3226 for (int i=0; i<N; i++) {
3227 ResolveInfo rInfo = resolves.get(i);
3228 if (rInfo.activityInfo.packageName.equals(r.packageName)
3229 && rInfo.activityInfo.name.equals(r.info.name)) {
3230 // We found the current one... the next matching is
3231 // after it.
3232 i++;
3233 if (i<N) {
3234 aInfo = resolves.get(i).activityInfo;
3235 }
3236 break;
3237 }
3238 }
3239 } catch (RemoteException e) {
3240 }
3241
3242 if (aInfo == null) {
3243 // Nobody who is next!
3244 return false;
3245 }
3246
3247 intent.setComponent(new ComponentName(
3248 aInfo.applicationInfo.packageName, aInfo.name));
3249 intent.setFlags(intent.getFlags()&~(
3250 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3251 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3252 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3253 Intent.FLAG_ACTIVITY_NEW_TASK));
3254
3255 // Okay now we need to start the new activity, replacing the
3256 // currently running activity. This is a little tricky because
3257 // we want to start the new one as if the current one is finished,
3258 // but not finish the current one first so that there is no flicker.
3259 // And thus...
3260 final boolean wasFinishing = r.finishing;
3261 r.finishing = true;
3262
3263 // Propagate reply information over to the new activity.
3264 final HistoryRecord resultTo = r.resultTo;
3265 final String resultWho = r.resultWho;
3266 final int requestCode = r.requestCode;
3267 r.resultTo = null;
3268 if (resultTo != null) {
3269 resultTo.removeResultsLocked(r, resultWho, requestCode);
3270 }
3271
3272 final long origId = Binder.clearCallingIdentity();
3273 // XXX we are not dealing with propagating grantedUriPermissions...
3274 // those are not yet exposed to user code, so there is no need.
3275 int res = startActivityLocked(r.app.thread, intent,
3276 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003277 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278 Binder.restoreCallingIdentity(origId);
3279
3280 r.finishing = wasFinishing;
3281 if (res != START_SUCCESS) {
3282 return false;
3283 }
3284 return true;
3285 }
3286 }
3287
3288 final int startActivityInPackage(int uid,
3289 Intent intent, String resolvedType, IBinder resultTo,
3290 String resultWho, int requestCode, boolean onlyIfNeeded) {
The Android Open Source Project4df24232009-03-05 14:34:35 -08003291 final boolean componentSpecified = intent.getComponent() != null;
3292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003293 // Don't modify the client's object!
3294 intent = new Intent(intent);
3295
3296 // Collect information about the target of the Intent.
3297 // Must do this before locking, because resolving the intent
3298 // may require launching a process to run its content provider.
3299 ActivityInfo aInfo;
3300 try {
3301 ResolveInfo rInfo =
3302 ActivityThread.getPackageManager().resolveIntent(
3303 intent, resolvedType,
3304 PackageManager.MATCH_DEFAULT_ONLY
3305 | PackageManager.GET_SHARED_LIBRARY_FILES);
3306 aInfo = rInfo != null ? rInfo.activityInfo : null;
3307 } catch (RemoteException e) {
3308 aInfo = null;
3309 }
3310
3311 if (aInfo != null) {
3312 // Store the found target back into the intent, because now that
3313 // we have it we never want to do this again. For example, if the
3314 // user navigates back to this point in the history, we should
3315 // always restart the exact same activity.
3316 intent.setComponent(new ComponentName(
3317 aInfo.applicationInfo.packageName, aInfo.name));
3318 }
3319
3320 synchronized(this) {
3321 return startActivityLocked(null, intent, resolvedType,
3322 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003323 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 }
3325 }
3326
3327 private final void addRecentTask(TaskRecord task) {
3328 // Remove any existing entries that are the same kind of task.
3329 int N = mRecentTasks.size();
3330 for (int i=0; i<N; i++) {
3331 TaskRecord tr = mRecentTasks.get(i);
3332 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3333 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3334 mRecentTasks.remove(i);
3335 i--;
3336 N--;
3337 if (task.intent == null) {
3338 // If the new recent task we are adding is not fully
3339 // specified, then replace it with the existing recent task.
3340 task = tr;
3341 }
3342 }
3343 }
3344 if (N >= MAX_RECENT_TASKS) {
3345 mRecentTasks.remove(N-1);
3346 }
3347 mRecentTasks.add(0, task);
3348 }
3349
3350 public void setRequestedOrientation(IBinder token,
3351 int requestedOrientation) {
3352 synchronized (this) {
3353 int index = indexOfTokenLocked(token, false);
3354 if (index < 0) {
3355 return;
3356 }
3357 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3358 final long origId = Binder.clearCallingIdentity();
3359 mWindowManager.setAppOrientation(r, requestedOrientation);
3360 Configuration config = mWindowManager.updateOrientationFromAppTokens(
3361 r.mayFreezeScreenLocked(r.app) ? r : null);
3362 if (config != null) {
3363 r.frozenBeforeDestroy = true;
3364 if (!updateConfigurationLocked(config, r)) {
3365 resumeTopActivityLocked(null);
3366 }
3367 }
3368 Binder.restoreCallingIdentity(origId);
3369 }
3370 }
3371
3372 public int getRequestedOrientation(IBinder token) {
3373 synchronized (this) {
3374 int index = indexOfTokenLocked(token, false);
3375 if (index < 0) {
3376 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3377 }
3378 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3379 return mWindowManager.getAppOrientation(r);
3380 }
3381 }
3382
3383 private final void stopActivityLocked(HistoryRecord r) {
3384 if (DEBUG_SWITCH) Log.d(TAG, "Stopping: " + r);
3385 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3386 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3387 if (!r.finishing) {
3388 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3389 "no-history");
3390 }
3391 } else if (r.app != null && r.app.thread != null) {
3392 if (mFocusedActivity == r) {
3393 setFocusedActivityLocked(topRunningActivityLocked(null));
3394 }
3395 r.resumeKeyDispatchingLocked();
3396 try {
3397 r.stopped = false;
3398 r.state = ActivityState.STOPPING;
3399 if (DEBUG_VISBILITY) Log.v(
3400 TAG, "Stopping visible=" + r.visible + " for " + r);
3401 if (!r.visible) {
3402 mWindowManager.setAppVisibility(r, false);
3403 }
3404 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3405 } catch (Exception e) {
3406 // Maybe just ignore exceptions here... if the process
3407 // has crashed, our death notification will clean things
3408 // up.
3409 Log.w(TAG, "Exception thrown during pause", e);
3410 // Just in case, assume it to be stopped.
3411 r.stopped = true;
3412 r.state = ActivityState.STOPPED;
3413 if (r.configDestroy) {
3414 destroyActivityLocked(r, true);
3415 }
3416 }
3417 }
3418 }
3419
3420 /**
3421 * @return Returns true if the activity is being finished, false if for
3422 * some reason it is being left as-is.
3423 */
3424 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3425 Intent resultData, String reason) {
3426 if (localLOGV) Log.v(
3427 TAG, "Finishing activity: token=" + token
3428 + ", result=" + resultCode + ", data=" + resultData);
3429
3430 int index = indexOfTokenLocked(token, false);
3431 if (index < 0) {
3432 return false;
3433 }
3434 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3435
3436 // Is this the last activity left?
3437 boolean lastActivity = true;
3438 for (int i=mHistory.size()-1; i>=0; i--) {
3439 HistoryRecord p = (HistoryRecord)mHistory.get(i);
3440 if (!p.finishing && p != r) {
3441 lastActivity = false;
3442 break;
3443 }
3444 }
3445
3446 // If this is the last activity, but it is the home activity, then
3447 // just don't finish it.
3448 if (lastActivity) {
3449 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
3450 return false;
3451 }
3452 }
3453
3454 finishActivityLocked(r, index, resultCode, resultData, reason);
3455 return true;
3456 }
3457
3458 /**
3459 * @return Returns true if this activity has been removed from the history
3460 * list, or false if it is still in the list and will be removed later.
3461 */
3462 private final boolean finishActivityLocked(HistoryRecord r, int index,
3463 int resultCode, Intent resultData, String reason) {
3464 if (r.finishing) {
3465 Log.w(TAG, "Duplicate finish request for " + r);
3466 return false;
3467 }
3468
3469 r.finishing = true;
3470 EventLog.writeEvent(LOG_AM_FINISH_ACTIVITY,
3471 System.identityHashCode(r),
3472 r.task.taskId, r.shortComponentName, reason);
3473 r.task.numActivities--;
3474 if (r.frontOfTask && index < (mHistory.size()-1)) {
3475 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
3476 if (next.task == r.task) {
3477 next.frontOfTask = true;
3478 }
3479 }
3480
3481 r.pauseKeyDispatchingLocked();
3482 if (mFocusedActivity == r) {
3483 setFocusedActivityLocked(topRunningActivityLocked(null));
3484 }
3485
3486 // send the result
3487 HistoryRecord resultTo = r.resultTo;
3488 if (resultTo != null) {
3489 if (localLOGV) Log.v(TAG, "Adding result to " + resultTo);
3490 if (r.info.applicationInfo.uid > 0) {
3491 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3492 r.packageName, resultData, r);
3493 }
3494 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3495 resultData);
3496 r.resultTo = null;
3497 }
3498
3499 // Make sure this HistoryRecord is not holding on to other resources,
3500 // because clients have remote IPC references to this object so we
3501 // can't assume that will go away and want to avoid circular IPC refs.
3502 r.results = null;
3503 r.pendingResults = null;
3504 r.newIntents = null;
3505 r.icicle = null;
3506
3507 if (mPendingThumbnails.size() > 0) {
3508 // There are clients waiting to receive thumbnails so, in case
3509 // this is an activity that someone is waiting for, add it
3510 // to the pending list so we can correctly update the clients.
3511 mCancelledThumbnails.add(r);
3512 }
3513
3514 if (mResumedActivity == r) {
3515 boolean endTask = index <= 0
3516 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
3517 if (DEBUG_TRANSITION) Log.v(TAG,
3518 "Prepare close transition: finishing " + r);
3519 mWindowManager.prepareAppTransition(endTask
3520 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
3521 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
3522
3523 // Tell window manager to prepare for this one to be removed.
3524 mWindowManager.setAppVisibility(r, false);
3525
3526 if (mPausingActivity == null) {
3527 if (DEBUG_PAUSE) Log.v(TAG, "Finish needs to pause: " + r);
3528 if (DEBUG_USER_LEAVING) Log.v(TAG, "finish() => pause with userLeaving=false");
3529 startPausingLocked(false, false);
3530 }
3531
3532 } else if (r.state != ActivityState.PAUSING) {
3533 // If the activity is PAUSING, we will complete the finish once
3534 // it is done pausing; else we can just directly finish it here.
3535 if (DEBUG_PAUSE) Log.v(TAG, "Finish not pausing: " + r);
3536 return finishCurrentActivityLocked(r, index,
3537 FINISH_AFTER_PAUSE) == null;
3538 } else {
3539 if (DEBUG_PAUSE) Log.v(TAG, "Finish waiting for pause of: " + r);
3540 }
3541
3542 return false;
3543 }
3544
3545 private static final int FINISH_IMMEDIATELY = 0;
3546 private static final int FINISH_AFTER_PAUSE = 1;
3547 private static final int FINISH_AFTER_VISIBLE = 2;
3548
3549 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
3550 int mode) {
3551 final int index = indexOfTokenLocked(r, false);
3552 if (index < 0) {
3553 return null;
3554 }
3555
3556 return finishCurrentActivityLocked(r, index, mode);
3557 }
3558
3559 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
3560 int index, int mode) {
3561 // First things first: if this activity is currently visible,
3562 // and the resumed activity is not yet visible, then hold off on
3563 // finishing until the resumed one becomes visible.
3564 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
3565 if (!mStoppingActivities.contains(r)) {
3566 mStoppingActivities.add(r);
3567 if (mStoppingActivities.size() > 3) {
3568 // If we already have a few activities waiting to stop,
3569 // then give up on things going idle and start clearing
3570 // them out.
3571 Message msg = Message.obtain();
3572 msg.what = ActivityManagerService.IDLE_NOW_MSG;
3573 mHandler.sendMessage(msg);
3574 }
3575 }
3576 r.state = ActivityState.STOPPING;
3577 updateOomAdjLocked();
3578 return r;
3579 }
3580
3581 // make sure the record is cleaned out of other places.
3582 mStoppingActivities.remove(r);
3583 mWaitingVisibleActivities.remove(r);
3584 if (mResumedActivity == r) {
3585 mResumedActivity = null;
3586 }
3587 final ActivityState prevState = r.state;
3588 r.state = ActivityState.FINISHING;
3589
3590 if (mode == FINISH_IMMEDIATELY
3591 || prevState == ActivityState.STOPPED
3592 || prevState == ActivityState.INITIALIZING) {
3593 // If this activity is already stopped, we can just finish
3594 // it right now.
3595 return destroyActivityLocked(r, true) ? null : r;
3596 } else {
3597 // Need to go through the full pause cycle to get this
3598 // activity into the stopped state and then finish it.
3599 if (localLOGV) Log.v(TAG, "Enqueueing pending finish: " + r);
3600 mFinishingActivities.add(r);
3601 resumeTopActivityLocked(null);
3602 }
3603 return r;
3604 }
3605
3606 /**
3607 * This is the internal entry point for handling Activity.finish().
3608 *
3609 * @param token The Binder token referencing the Activity we want to finish.
3610 * @param resultCode Result code, if any, from this Activity.
3611 * @param resultData Result data (Intent), if any, from this Activity.
3612 *
3613 * @result Returns true if the activity successfully finished, or false if it is still running.
3614 */
3615 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
3616 // Refuse possible leaked file descriptors
3617 if (resultData != null && resultData.hasFileDescriptors() == true) {
3618 throw new IllegalArgumentException("File descriptors passed in Intent");
3619 }
3620
3621 synchronized(this) {
3622 if (mWatcher != null) {
3623 // Find the first activity that is not finishing.
3624 HistoryRecord next = topRunningActivityLocked(token, 0);
3625 if (next != null) {
3626 // ask watcher if this is allowed
3627 boolean resumeOK = true;
3628 try {
3629 resumeOK = mWatcher.activityResuming(next.packageName);
3630 } catch (RemoteException e) {
3631 mWatcher = null;
3632 }
3633
3634 if (!resumeOK) {
3635 return false;
3636 }
3637 }
3638 }
3639 final long origId = Binder.clearCallingIdentity();
3640 boolean res = requestFinishActivityLocked(token, resultCode,
3641 resultData, "app-request");
3642 Binder.restoreCallingIdentity(origId);
3643 return res;
3644 }
3645 }
3646
3647 void sendActivityResultLocked(int callingUid, HistoryRecord r,
3648 String resultWho, int requestCode, int resultCode, Intent data) {
3649
3650 if (callingUid > 0) {
3651 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3652 data, r);
3653 }
3654
3655 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
3656 try {
3657 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3658 list.add(new ResultInfo(resultWho, requestCode,
3659 resultCode, data));
3660 r.app.thread.scheduleSendResult(r, list);
3661 return;
3662 } catch (Exception e) {
3663 Log.w(TAG, "Exception thrown sending result to " + r, e);
3664 }
3665 }
3666
3667 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
3668 }
3669
3670 public final void finishSubActivity(IBinder token, String resultWho,
3671 int requestCode) {
3672 synchronized(this) {
3673 int index = indexOfTokenLocked(token, false);
3674 if (index < 0) {
3675 return;
3676 }
3677 HistoryRecord self = (HistoryRecord)mHistory.get(index);
3678
3679 final long origId = Binder.clearCallingIdentity();
3680
3681 int i;
3682 for (i=mHistory.size()-1; i>=0; i--) {
3683 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3684 if (r.resultTo == self && r.requestCode == requestCode) {
3685 if ((r.resultWho == null && resultWho == null) ||
3686 (r.resultWho != null && r.resultWho.equals(resultWho))) {
3687 finishActivityLocked(r, i,
3688 Activity.RESULT_CANCELED, null, "request-sub");
3689 }
3690 }
3691 }
3692
3693 Binder.restoreCallingIdentity(origId);
3694 }
3695 }
3696
3697 /**
3698 * Perform clean-up of service connections in an activity record.
3699 */
3700 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
3701 // Throw away any services that have been bound by this activity.
3702 if (r.connections != null) {
3703 Iterator<ConnectionRecord> it = r.connections.iterator();
3704 while (it.hasNext()) {
3705 ConnectionRecord c = it.next();
3706 removeConnectionLocked(c, null, r);
3707 }
3708 r.connections = null;
3709 }
3710 }
3711
3712 /**
3713 * Perform the common clean-up of an activity record. This is called both
3714 * as part of destroyActivityLocked() (when destroying the client-side
3715 * representation) and cleaning things up as a result of its hosting
3716 * processing going away, in which case there is no remaining client-side
3717 * state to destroy so only the cleanup here is needed.
3718 */
3719 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
3720 if (mResumedActivity == r) {
3721 mResumedActivity = null;
3722 }
3723 if (mFocusedActivity == r) {
3724 mFocusedActivity = null;
3725 }
3726
3727 r.configDestroy = false;
3728 r.frozenBeforeDestroy = false;
3729
3730 // Make sure this record is no longer in the pending finishes list.
3731 // This could happen, for example, if we are trimming activities
3732 // down to the max limit while they are still waiting to finish.
3733 mFinishingActivities.remove(r);
3734 mWaitingVisibleActivities.remove(r);
3735
3736 // Remove any pending results.
3737 if (r.finishing && r.pendingResults != null) {
3738 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
3739 PendingIntentRecord rec = apr.get();
3740 if (rec != null) {
3741 cancelIntentSenderLocked(rec, false);
3742 }
3743 }
3744 r.pendingResults = null;
3745 }
3746
3747 if (cleanServices) {
3748 cleanUpActivityServicesLocked(r);
3749 }
3750
3751 if (mPendingThumbnails.size() > 0) {
3752 // There are clients waiting to receive thumbnails so, in case
3753 // this is an activity that someone is waiting for, add it
3754 // to the pending list so we can correctly update the clients.
3755 mCancelledThumbnails.add(r);
3756 }
3757
3758 // Get rid of any pending idle timeouts.
3759 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
3760 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
3761 }
3762
3763 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
3764 if (r.state != ActivityState.DESTROYED) {
3765 mHistory.remove(r);
3766 r.inHistory = false;
3767 r.state = ActivityState.DESTROYED;
3768 mWindowManager.removeAppToken(r);
3769 if (VALIDATE_TOKENS) {
3770 mWindowManager.validateAppTokens(mHistory);
3771 }
3772 cleanUpActivityServicesLocked(r);
3773 removeActivityUriPermissionsLocked(r);
3774 }
3775 }
3776
3777 /**
3778 * Destroy the current CLIENT SIDE instance of an activity. This may be
3779 * called both when actually finishing an activity, or when performing
3780 * a configuration switch where we destroy the current client-side object
3781 * but then create a new client-side object for this same HistoryRecord.
3782 */
3783 private final boolean destroyActivityLocked(HistoryRecord r,
3784 boolean removeFromApp) {
3785 if (DEBUG_SWITCH) Log.v(
3786 TAG, "Removing activity: token=" + r
3787 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
3788 EventLog.writeEvent(LOG_AM_DESTROY_ACTIVITY,
3789 System.identityHashCode(r),
3790 r.task.taskId, r.shortComponentName);
3791
3792 boolean removedFromHistory = false;
3793
3794 cleanUpActivityLocked(r, false);
3795
3796 if (r.app != null) {
3797 if (removeFromApp) {
3798 int idx = r.app.activities.indexOf(r);
3799 if (idx >= 0) {
3800 r.app.activities.remove(idx);
3801 }
3802 if (r.persistent) {
3803 decPersistentCountLocked(r.app);
3804 }
3805 }
3806
3807 boolean skipDestroy = false;
3808
3809 try {
3810 if (DEBUG_SWITCH) Log.i(TAG, "Destroying: " + r);
3811 r.app.thread.scheduleDestroyActivity(r, r.finishing,
3812 r.configChangeFlags);
3813 } catch (Exception e) {
3814 // We can just ignore exceptions here... if the process
3815 // has crashed, our death notification will clean things
3816 // up.
3817 //Log.w(TAG, "Exception thrown during finish", e);
3818 if (r.finishing) {
3819 removeActivityFromHistoryLocked(r);
3820 removedFromHistory = true;
3821 skipDestroy = true;
3822 }
3823 }
3824
3825 r.app = null;
3826 r.nowVisible = false;
3827
3828 if (r.finishing && !skipDestroy) {
3829 r.state = ActivityState.DESTROYING;
3830 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
3831 msg.obj = r;
3832 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
3833 } else {
3834 r.state = ActivityState.DESTROYED;
3835 }
3836 } else {
3837 // remove this record from the history.
3838 if (r.finishing) {
3839 removeActivityFromHistoryLocked(r);
3840 removedFromHistory = true;
3841 } else {
3842 r.state = ActivityState.DESTROYED;
3843 }
3844 }
3845
3846 r.configChangeFlags = 0;
3847
3848 if (!mLRUActivities.remove(r)) {
3849 Log.w(TAG, "Activity " + r + " being finished, but not in LRU list");
3850 }
3851
3852 return removedFromHistory;
3853 }
3854
3855 private static void removeHistoryRecordsForAppLocked(ArrayList list,
3856 ProcessRecord app)
3857 {
3858 int i = list.size();
3859 if (localLOGV) Log.v(
3860 TAG, "Removing app " + app + " from list " + list
3861 + " with " + i + " entries");
3862 while (i > 0) {
3863 i--;
3864 HistoryRecord r = (HistoryRecord)list.get(i);
3865 if (localLOGV) Log.v(
3866 TAG, "Record #" + i + " " + r + ": app=" + r.app);
3867 if (r.app == app) {
3868 if (localLOGV) Log.v(TAG, "Removing this entry!");
3869 list.remove(i);
3870 }
3871 }
3872 }
3873
3874 /**
3875 * Main function for removing an existing process from the activity manager
3876 * as a result of that process going away. Clears out all connections
3877 * to the process.
3878 */
3879 private final void handleAppDiedLocked(ProcessRecord app,
3880 boolean restarting) {
3881 cleanUpApplicationRecordLocked(app, restarting, -1);
3882 if (!restarting) {
3883 mLRUProcesses.remove(app);
3884 }
3885
3886 // Just in case...
3887 if (mPausingActivity != null && mPausingActivity.app == app) {
3888 if (DEBUG_PAUSE) Log.v(TAG, "App died while pausing: " + mPausingActivity);
3889 mPausingActivity = null;
3890 }
3891 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
3892 mLastPausedActivity = null;
3893 }
3894
3895 // Remove this application's activities from active lists.
3896 removeHistoryRecordsForAppLocked(mLRUActivities, app);
3897 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
3898 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
3899 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
3900
3901 boolean atTop = true;
3902 boolean hasVisibleActivities = false;
3903
3904 // Clean out the history list.
3905 int i = mHistory.size();
3906 if (localLOGV) Log.v(
3907 TAG, "Removing app " + app + " from history with " + i + " entries");
3908 while (i > 0) {
3909 i--;
3910 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3911 if (localLOGV) Log.v(
3912 TAG, "Record #" + i + " " + r + ": app=" + r.app);
3913 if (r.app == app) {
3914 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
3915 if (localLOGV) Log.v(
3916 TAG, "Removing this entry! frozen=" + r.haveState
3917 + " finishing=" + r.finishing);
3918 mHistory.remove(i);
3919
3920 r.inHistory = false;
3921 mWindowManager.removeAppToken(r);
3922 if (VALIDATE_TOKENS) {
3923 mWindowManager.validateAppTokens(mHistory);
3924 }
3925 removeActivityUriPermissionsLocked(r);
3926
3927 } else {
3928 // We have the current state for this activity, so
3929 // it can be restarted later when needed.
3930 if (localLOGV) Log.v(
3931 TAG, "Keeping entry, setting app to null");
3932 if (r.visible) {
3933 hasVisibleActivities = true;
3934 }
3935 r.app = null;
3936 r.nowVisible = false;
3937 if (!r.haveState) {
3938 r.icicle = null;
3939 }
3940 }
3941
3942 cleanUpActivityLocked(r, true);
3943 r.state = ActivityState.STOPPED;
3944 }
3945 atTop = false;
3946 }
3947
3948 app.activities.clear();
3949
3950 if (app.instrumentationClass != null) {
3951 Log.w(TAG, "Crash of app " + app.processName
3952 + " running instrumentation " + app.instrumentationClass);
3953 Bundle info = new Bundle();
3954 info.putString("shortMsg", "Process crashed.");
3955 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
3956 }
3957
3958 if (!restarting) {
3959 if (!resumeTopActivityLocked(null)) {
3960 // If there was nothing to resume, and we are not already
3961 // restarting this process, but there is a visible activity that
3962 // is hosted by the process... then make sure all visible
3963 // activities are running, taking care of restarting this
3964 // process.
3965 if (hasVisibleActivities) {
3966 ensureActivitiesVisibleLocked(null, 0);
3967 }
3968 }
3969 }
3970 }
3971
3972 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
3973 IBinder threadBinder = thread.asBinder();
3974
3975 // Find the application record.
3976 int count = mLRUProcesses.size();
3977 int i;
3978 for (i=0; i<count; i++) {
3979 ProcessRecord rec = mLRUProcesses.get(i);
3980 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
3981 return i;
3982 }
3983 }
3984 return -1;
3985 }
3986
3987 private final ProcessRecord getRecordForAppLocked(
3988 IApplicationThread thread) {
3989 if (thread == null) {
3990 return null;
3991 }
3992
3993 int appIndex = getLRURecordIndexForAppLocked(thread);
3994 return appIndex >= 0 ? mLRUProcesses.get(appIndex) : null;
3995 }
3996
3997 private final void appDiedLocked(ProcessRecord app, int pid,
3998 IApplicationThread thread) {
3999
4000 mProcDeaths[0]++;
4001
4002 if (app.thread != null && app.thread.asBinder() == thread.asBinder()) {
4003 Log.i(TAG, "Process " + app.processName + " (pid " + pid
4004 + ") has died.");
4005 EventLog.writeEvent(LOG_AM_PROCESS_DIED, app.pid, app.processName);
4006 if (localLOGV) Log.v(
4007 TAG, "Dying app: " + app + ", pid: " + pid
4008 + ", thread: " + thread.asBinder());
4009 boolean doLowMem = app.instrumentationClass == null;
4010 handleAppDiedLocked(app, false);
4011
4012 if (doLowMem) {
4013 // If there are no longer any background processes running,
4014 // and the app that died was not running instrumentation,
4015 // then tell everyone we are now low on memory.
4016 boolean haveBg = false;
4017 int count = mLRUProcesses.size();
4018 int i;
4019 for (i=0; i<count; i++) {
4020 ProcessRecord rec = mLRUProcesses.get(i);
4021 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4022 haveBg = true;
4023 break;
4024 }
4025 }
4026
4027 if (!haveBg) {
4028 Log.i(TAG, "Low Memory: No more background processes.");
4029 EventLog.writeEvent(LOG_AM_LOW_MEMORY, mLRUProcesses.size());
4030 for (i=0; i<count; i++) {
4031 ProcessRecord rec = mLRUProcesses.get(i);
4032 if (rec.thread != null) {
4033 rec.lastRequestedGc = SystemClock.uptimeMillis();
4034 try {
4035 rec.thread.scheduleLowMemory();
4036 } catch (RemoteException e) {
4037 // Don't care if the process is gone.
4038 }
4039 }
4040 }
4041 }
4042 }
4043 } else if (Config.LOGD) {
4044 Log.d(TAG, "Received spurious death notification for thread "
4045 + thread.asBinder());
4046 }
4047 }
4048
4049 final String readFile(String filename) {
4050 try {
4051 FileInputStream fs = new FileInputStream(filename);
4052 byte[] inp = new byte[8192];
4053 int size = fs.read(inp);
4054 fs.close();
4055 return new String(inp, 0, 0, size);
4056 } catch (java.io.IOException e) {
4057 }
4058 return "";
4059 }
4060
4061 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4062 final String annotation) {
4063 if (app.notResponding || app.crashing) {
4064 return;
4065 }
4066
4067 // Log the ANR to the event log.
4068 EventLog.writeEvent(LOG_ANR, app.pid, app.processName, annotation);
4069
4070 // If we are on a secure build and the application is not interesting to the user (it is
4071 // not visible or in the background), just kill it instead of displaying a dialog.
4072 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
4073 if (isSecure && !app.isInterestingToUserLocked() && Process.myPid() != app.pid) {
4074 Process.killProcess(app.pid);
4075 return;
4076 }
4077
4078 // DeviceMonitor.start();
4079
4080 String processInfo = null;
4081 if (MONITOR_CPU_USAGE) {
4082 updateCpuStatsNow();
4083 synchronized (mProcessStatsThread) {
4084 processInfo = mProcessStats.printCurrentState();
4085 }
4086 }
4087
4088 StringBuilder info = new StringBuilder();
4089 info.append("ANR (application not responding) in process: ");
4090 info.append(app.processName);
4091 if (annotation != null) {
4092 info.append("\nAnnotation: ");
4093 info.append(annotation);
4094 }
4095 if (MONITOR_CPU_USAGE) {
4096 info.append("\nCPU usage:\n");
4097 info.append(processInfo);
4098 }
4099 Log.i(TAG, info.toString());
4100
4101 // The application is not responding. Dump as many thread traces as we can.
4102 boolean fileDump = prepareTraceFile(true);
4103 if (!fileDump) {
4104 // Dumping traces to the log, just dump the process that isn't responding so
4105 // we don't overflow the log
4106 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4107 } else {
4108 // Dumping traces to a file so dump all active processes we know about
4109 synchronized (this) {
4110 for (int i = mLRUProcesses.size() - 1 ; i >= 0 ; i--) {
4111 ProcessRecord r = mLRUProcesses.get(i);
4112 if (r.thread != null) {
4113 Process.sendSignal(r.pid, Process.SIGNAL_QUIT);
4114 }
4115 }
4116 }
4117 }
4118
4119 if (mWatcher != null) {
4120 try {
4121 int res = mWatcher.appNotResponding(app.processName,
4122 app.pid, info.toString());
4123 if (res != 0) {
4124 if (res < 0) {
4125 // wait until the SIGQUIT has had a chance to process before killing the
4126 // process.
4127 try {
4128 wait(2000);
4129 } catch (InterruptedException e) {
4130 }
4131
4132 Process.killProcess(app.pid);
4133 return;
4134 }
4135 }
4136 } catch (RemoteException e) {
4137 mWatcher = null;
4138 }
4139 }
4140
4141 makeAppNotRespondingLocked(app,
4142 activity != null ? activity.shortComponentName : null,
4143 annotation != null ? "ANR " + annotation : "ANR",
4144 info.toString(), null);
4145 Message msg = Message.obtain();
4146 HashMap map = new HashMap();
4147 msg.what = SHOW_NOT_RESPONDING_MSG;
4148 msg.obj = map;
4149 map.put("app", app);
4150 if (activity != null) {
4151 map.put("activity", activity);
4152 }
4153
4154 mHandler.sendMessage(msg);
4155 return;
4156 }
4157
4158 /**
4159 * If a stack trace file has been configured, prepare the filesystem
4160 * by creating the directory if it doesn't exist and optionally
4161 * removing the old trace file.
4162 *
4163 * @param removeExisting If set, the existing trace file will be removed.
4164 * @return Returns true if the trace file preparations succeeded
4165 */
4166 public static boolean prepareTraceFile(boolean removeExisting) {
4167 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4168 boolean fileReady = false;
4169 if (!TextUtils.isEmpty(tracesPath)) {
4170 File f = new File(tracesPath);
4171 if (!f.exists()) {
4172 // Ensure the enclosing directory exists
4173 File dir = f.getParentFile();
4174 if (!dir.exists()) {
4175 fileReady = dir.mkdirs();
4176 FileUtils.setPermissions(dir.getAbsolutePath(),
4177 FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO, -1, -1);
4178 } else if (dir.isDirectory()) {
4179 fileReady = true;
4180 }
4181 } else if (removeExisting) {
4182 // Remove the previous traces file, so we don't fill the disk.
4183 // The VM will recreate it
4184 Log.i(TAG, "Removing old ANR trace file from " + tracesPath);
4185 fileReady = f.delete();
4186 }
4187 }
4188
4189 return fileReady;
4190 }
4191
4192
4193 private final void decPersistentCountLocked(ProcessRecord app)
4194 {
4195 app.persistentActivities--;
4196 if (app.persistentActivities > 0) {
4197 // Still more of 'em...
4198 return;
4199 }
4200 if (app.persistent) {
4201 // Ah, but the application itself is persistent. Whatever!
4202 return;
4203 }
4204
4205 // App is no longer persistent... make sure it and the ones
4206 // following it in the LRU list have the correc oom_adj.
4207 updateOomAdjLocked();
4208 }
4209
4210 public void setPersistent(IBinder token, boolean isPersistent) {
4211 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4212 != PackageManager.PERMISSION_GRANTED) {
4213 String msg = "Permission Denial: setPersistent() from pid="
4214 + Binder.getCallingPid()
4215 + ", uid=" + Binder.getCallingUid()
4216 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
4217 Log.w(TAG, msg);
4218 throw new SecurityException(msg);
4219 }
4220
4221 synchronized(this) {
4222 int index = indexOfTokenLocked(token, true);
4223 if (index < 0) {
4224 return;
4225 }
4226 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4227 ProcessRecord app = r.app;
4228
4229 if (localLOGV) Log.v(
4230 TAG, "Setting persistence " + isPersistent + ": " + r);
4231
4232 if (isPersistent) {
4233 if (r.persistent) {
4234 // Okay okay, I heard you already!
4235 if (localLOGV) Log.v(TAG, "Already persistent!");
4236 return;
4237 }
4238 r.persistent = true;
4239 app.persistentActivities++;
4240 if (localLOGV) Log.v(TAG, "Num persistent now: " + app.persistentActivities);
4241 if (app.persistentActivities > 1) {
4242 // We aren't the first...
4243 if (localLOGV) Log.v(TAG, "Not the first!");
4244 return;
4245 }
4246 if (app.persistent) {
4247 // This would be redundant.
4248 if (localLOGV) Log.v(TAG, "App is persistent!");
4249 return;
4250 }
4251
4252 // App is now persistent... make sure it and the ones
4253 // following it now have the correct oom_adj.
4254 final long origId = Binder.clearCallingIdentity();
4255 updateOomAdjLocked();
4256 Binder.restoreCallingIdentity(origId);
4257
4258 } else {
4259 if (!r.persistent) {
4260 // Okay okay, I heard you already!
4261 return;
4262 }
4263 r.persistent = false;
4264 final long origId = Binder.clearCallingIdentity();
4265 decPersistentCountLocked(app);
4266 Binder.restoreCallingIdentity(origId);
4267
4268 }
4269 }
4270 }
4271
4272 public boolean clearApplicationUserData(final String packageName,
4273 final IPackageDataObserver observer) {
4274 int uid = Binder.getCallingUid();
4275 int pid = Binder.getCallingPid();
4276 long callingId = Binder.clearCallingIdentity();
4277 try {
4278 IPackageManager pm = ActivityThread.getPackageManager();
4279 int pkgUid = -1;
4280 synchronized(this) {
4281 try {
4282 pkgUid = pm.getPackageUid(packageName);
4283 } catch (RemoteException e) {
4284 }
4285 if (pkgUid == -1) {
4286 Log.w(TAG, "Invalid packageName:" + packageName);
4287 return false;
4288 }
4289 if (uid == pkgUid || checkComponentPermission(
4290 android.Manifest.permission.CLEAR_APP_USER_DATA,
4291 pid, uid, -1)
4292 == PackageManager.PERMISSION_GRANTED) {
4293 restartPackageLocked(packageName, pkgUid);
4294 } else {
4295 throw new SecurityException(pid+" does not have permission:"+
4296 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4297 "for process:"+packageName);
4298 }
4299 }
4300
4301 try {
4302 //clear application user data
4303 pm.clearApplicationUserData(packageName, observer);
4304 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4305 Uri.fromParts("package", packageName, null));
4306 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4307 broadcastIntentLocked(null, null, intent,
4308 null, null, 0, null, null, null,
4309 false, false, MY_PID, Process.SYSTEM_UID);
4310 } catch (RemoteException e) {
4311 }
4312 } finally {
4313 Binder.restoreCallingIdentity(callingId);
4314 }
4315 return true;
4316 }
4317
4318 public void restartPackage(final String packageName) {
4319 if (checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4320 != PackageManager.PERMISSION_GRANTED) {
4321 String msg = "Permission Denial: restartPackage() from pid="
4322 + Binder.getCallingPid()
4323 + ", uid=" + Binder.getCallingUid()
4324 + " requires " + android.Manifest.permission.RESTART_PACKAGES;
4325 Log.w(TAG, msg);
4326 throw new SecurityException(msg);
4327 }
4328
4329 long callingId = Binder.clearCallingIdentity();
4330 try {
4331 IPackageManager pm = ActivityThread.getPackageManager();
4332 int pkgUid = -1;
4333 synchronized(this) {
4334 try {
4335 pkgUid = pm.getPackageUid(packageName);
4336 } catch (RemoteException e) {
4337 }
4338 if (pkgUid == -1) {
4339 Log.w(TAG, "Invalid packageName: " + packageName);
4340 return;
4341 }
4342 restartPackageLocked(packageName, pkgUid);
4343 }
4344 } finally {
4345 Binder.restoreCallingIdentity(callingId);
4346 }
4347 }
4348
4349 private void restartPackageLocked(final String packageName, int uid) {
4350 uninstallPackageLocked(packageName, uid, false);
4351 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
4352 Uri.fromParts("package", packageName, null));
4353 intent.putExtra(Intent.EXTRA_UID, uid);
4354 broadcastIntentLocked(null, null, intent,
4355 null, null, 0, null, null, null,
4356 false, false, MY_PID, Process.SYSTEM_UID);
4357 }
4358
4359 private final void uninstallPackageLocked(String name, int uid,
4360 boolean callerWillRestart) {
4361 if (Config.LOGD) Log.d(TAG, "Uninstalling process " + name);
4362
4363 int i, N;
4364
4365 final String procNamePrefix = name + ":";
4366 if (uid < 0) {
4367 try {
4368 uid = ActivityThread.getPackageManager().getPackageUid(name);
4369 } catch (RemoteException e) {
4370 }
4371 }
4372
4373 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
4374 while (badApps.hasNext()) {
4375 SparseArray<Long> ba = badApps.next();
4376 if (ba.get(uid) != null) {
4377 badApps.remove();
4378 }
4379 }
4380
4381 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
4382
4383 // Remove all processes this package may have touched: all with the
4384 // same UID (except for the system or root user), and all whose name
4385 // matches the package name.
4386 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
4387 final int NA = apps.size();
4388 for (int ia=0; ia<NA; ia++) {
4389 ProcessRecord app = apps.valueAt(ia);
4390 if (app.removed) {
4391 procs.add(app);
4392 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
4393 || app.processName.equals(name)
4394 || app.processName.startsWith(procNamePrefix)) {
4395 app.removed = true;
4396 procs.add(app);
4397 }
4398 }
4399 }
4400
4401 N = procs.size();
4402 for (i=0; i<N; i++) {
4403 removeProcessLocked(procs.get(i), callerWillRestart);
4404 }
4405
4406 for (i=mHistory.size()-1; i>=0; i--) {
4407 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4408 if (r.packageName.equals(name)) {
4409 if (Config.LOGD) Log.d(
4410 TAG, " Force finishing activity "
4411 + r.intent.getComponent().flattenToShortString());
4412 if (r.app != null) {
4413 r.app.removed = true;
4414 }
4415 r.app = null;
4416 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
4417 }
4418 }
4419
4420 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
4421 for (ServiceRecord service : mServices.values()) {
4422 if (service.packageName.equals(name)) {
4423 if (service.app != null) {
4424 service.app.removed = true;
4425 }
4426 service.app = null;
4427 services.add(service);
4428 }
4429 }
4430
4431 N = services.size();
4432 for (i=0; i<N; i++) {
4433 bringDownServiceLocked(services.get(i), true);
4434 }
4435
4436 resumeTopActivityLocked(null);
4437 }
4438
4439 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
4440 final String name = app.processName;
4441 final int uid = app.info.uid;
4442 if (Config.LOGD) Log.d(
4443 TAG, "Force removing process " + app + " (" + name
4444 + "/" + uid + ")");
4445
4446 mProcessNames.remove(name, uid);
4447 boolean needRestart = false;
4448 if (app.pid > 0 && app.pid != MY_PID) {
4449 int pid = app.pid;
4450 synchronized (mPidsSelfLocked) {
4451 mPidsSelfLocked.remove(pid);
4452 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
4453 }
4454 handleAppDiedLocked(app, true);
4455 mLRUProcesses.remove(app);
4456 Process.killProcess(pid);
4457
4458 if (app.persistent) {
4459 if (!callerWillRestart) {
4460 addAppLocked(app.info);
4461 } else {
4462 needRestart = true;
4463 }
4464 }
4465 } else {
4466 mRemovedProcesses.add(app);
4467 }
4468
4469 return needRestart;
4470 }
4471
4472 private final void processStartTimedOutLocked(ProcessRecord app) {
4473 final int pid = app.pid;
4474 boolean gone = false;
4475 synchronized (mPidsSelfLocked) {
4476 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
4477 if (knownApp != null && knownApp.thread == null) {
4478 mPidsSelfLocked.remove(pid);
4479 gone = true;
4480 }
4481 }
4482
4483 if (gone) {
4484 Log.w(TAG, "Process " + app + " failed to attach");
4485 mProcessNames.remove(app.processName, app.info.uid);
4486 Process.killProcess(pid);
4487 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
4488 Log.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
4489 mPendingBroadcast = null;
4490 scheduleBroadcastsLocked();
4491 }
4492 } else {
4493 Log.w(TAG, "Spurious process start timeout - pid not known for " + app);
4494 }
4495 }
4496
4497 private final boolean attachApplicationLocked(IApplicationThread thread,
4498 int pid) {
4499
4500 // Find the application record that is being attached... either via
4501 // the pid if we are running in multiple processes, or just pull the
4502 // next app record if we are emulating process with anonymous threads.
4503 ProcessRecord app;
4504 if (pid != MY_PID && pid >= 0) {
4505 synchronized (mPidsSelfLocked) {
4506 app = mPidsSelfLocked.get(pid);
4507 }
4508 } else if (mStartingProcesses.size() > 0) {
4509 app = mStartingProcesses.remove(0);
4510 app.pid = pid;
4511 } else {
4512 app = null;
4513 }
4514
4515 if (app == null) {
4516 Log.w(TAG, "No pending application record for pid " + pid
4517 + " (IApplicationThread " + thread + "); dropping process");
4518 EventLog.writeEvent(LOG_AM_DROP_PROCESS, pid);
4519 if (pid > 0 && pid != MY_PID) {
4520 Process.killProcess(pid);
4521 } else {
4522 try {
4523 thread.scheduleExit();
4524 } catch (Exception e) {
4525 // Ignore exceptions.
4526 }
4527 }
4528 return false;
4529 }
4530
4531 // If this application record is still attached to a previous
4532 // process, clean it up now.
4533 if (app.thread != null) {
4534 handleAppDiedLocked(app, true);
4535 }
4536
4537 // Tell the process all about itself.
4538
4539 if (localLOGV) Log.v(
4540 TAG, "Binding process pid " + pid + " to record " + app);
4541
4542 String processName = app.processName;
4543 try {
4544 thread.asBinder().linkToDeath(new AppDeathRecipient(
4545 app, pid, thread), 0);
4546 } catch (RemoteException e) {
4547 app.resetPackageList();
4548 startProcessLocked(app, "link fail", processName);
4549 return false;
4550 }
4551
4552 EventLog.writeEvent(LOG_AM_PROCESS_BOUND, app.pid, app.processName);
4553
4554 app.thread = thread;
4555 app.curAdj = app.setAdj = -100;
4556 app.forcingToForeground = null;
4557 app.foregroundServices = false;
4558 app.debugging = false;
4559
4560 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
4561
4562 List providers = generateApplicationProvidersLocked(app);
4563
4564 if (localLOGV) Log.v(
4565 TAG, "New app record " + app
4566 + " thread=" + thread.asBinder() + " pid=" + pid);
4567 try {
4568 int testMode = IApplicationThread.DEBUG_OFF;
4569 if (mDebugApp != null && mDebugApp.equals(processName)) {
4570 testMode = mWaitForDebugger
4571 ? IApplicationThread.DEBUG_WAIT
4572 : IApplicationThread.DEBUG_ON;
4573 app.debugging = true;
4574 if (mDebugTransient) {
4575 mDebugApp = mOrigDebugApp;
4576 mWaitForDebugger = mOrigWaitForDebugger;
4577 }
4578 }
4579 thread.bindApplication(processName, app.info, providers,
4580 app.instrumentationClass, app.instrumentationProfileFile,
4581 app.instrumentationArguments, app.instrumentationWatcher, testMode,
4582 mConfiguration, getCommonServicesLocked());
4583 updateLRUListLocked(app, false);
4584 app.lastRequestedGc = SystemClock.uptimeMillis();
4585 } catch (Exception e) {
4586 // todo: Yikes! What should we do? For now we will try to
4587 // start another process, but that could easily get us in
4588 // an infinite loop of restarting processes...
4589 Log.w(TAG, "Exception thrown during bind!", e);
4590
4591 app.resetPackageList();
4592 startProcessLocked(app, "bind fail", processName);
4593 return false;
4594 }
4595
4596 // Remove this record from the list of starting applications.
4597 mPersistentStartingProcesses.remove(app);
4598 mProcessesOnHold.remove(app);
4599
4600 boolean badApp = false;
4601 boolean didSomething = false;
4602
4603 // See if the top visible activity is waiting to run in this process...
4604 HistoryRecord hr = topRunningActivityLocked(null);
4605 if (hr != null) {
4606 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
4607 && processName.equals(hr.processName)) {
4608 try {
4609 if (realStartActivityLocked(hr, app, true, true)) {
4610 didSomething = true;
4611 }
4612 } catch (Exception e) {
4613 Log.w(TAG, "Exception in new application when starting activity "
4614 + hr.intent.getComponent().flattenToShortString(), e);
4615 badApp = true;
4616 }
4617 } else {
4618 ensureActivitiesVisibleLocked(hr, null, processName, 0);
4619 }
4620 }
4621
4622 // Find any services that should be running in this process...
4623 if (!badApp && mPendingServices.size() > 0) {
4624 ServiceRecord sr = null;
4625 try {
4626 for (int i=0; i<mPendingServices.size(); i++) {
4627 sr = mPendingServices.get(i);
4628 if (app.info.uid != sr.appInfo.uid
4629 || !processName.equals(sr.processName)) {
4630 continue;
4631 }
4632
4633 mPendingServices.remove(i);
4634 i--;
4635 realStartServiceLocked(sr, app);
4636 didSomething = true;
4637 }
4638 } catch (Exception e) {
4639 Log.w(TAG, "Exception in new application when starting service "
4640 + sr.shortName, e);
4641 badApp = true;
4642 }
4643 }
4644
4645 // Check if the next broadcast receiver is in this process...
4646 BroadcastRecord br = mPendingBroadcast;
4647 if (!badApp && br != null && br.curApp == app) {
4648 try {
4649 mPendingBroadcast = null;
4650 processCurBroadcastLocked(br, app);
4651 didSomething = true;
4652 } catch (Exception e) {
4653 Log.w(TAG, "Exception in new application when starting receiver "
4654 + br.curComponent.flattenToShortString(), e);
4655 badApp = true;
4656 logBroadcastReceiverDiscard(br);
4657 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
4658 br.resultExtras, br.resultAbort, true);
4659 scheduleBroadcastsLocked();
4660 }
4661 }
4662
4663 if (badApp) {
4664 // todo: Also need to kill application to deal with all
4665 // kinds of exceptions.
4666 handleAppDiedLocked(app, false);
4667 return false;
4668 }
4669
4670 if (!didSomething) {
4671 updateOomAdjLocked();
4672 }
4673
4674 return true;
4675 }
4676
4677 public final void attachApplication(IApplicationThread thread) {
4678 synchronized (this) {
4679 int callingPid = Binder.getCallingPid();
4680 final long origId = Binder.clearCallingIdentity();
4681 attachApplicationLocked(thread, callingPid);
4682 Binder.restoreCallingIdentity(origId);
4683 }
4684 }
4685
4686 public final void activityIdle(IBinder token) {
4687 final long origId = Binder.clearCallingIdentity();
4688 activityIdleInternal(token, false);
4689 Binder.restoreCallingIdentity(origId);
4690 }
4691
4692 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
4693 boolean remove) {
4694 int N = mStoppingActivities.size();
4695 if (N <= 0) return null;
4696
4697 ArrayList<HistoryRecord> stops = null;
4698
4699 final boolean nowVisible = mResumedActivity != null
4700 && mResumedActivity.nowVisible
4701 && !mResumedActivity.waitingVisible;
4702 for (int i=0; i<N; i++) {
4703 HistoryRecord s = mStoppingActivities.get(i);
4704 if (localLOGV) Log.v(TAG, "Stopping " + s + ": nowVisible="
4705 + nowVisible + " waitingVisible=" + s.waitingVisible
4706 + " finishing=" + s.finishing);
4707 if (s.waitingVisible && nowVisible) {
4708 mWaitingVisibleActivities.remove(s);
4709 s.waitingVisible = false;
4710 if (s.finishing) {
4711 // If this activity is finishing, it is sitting on top of
4712 // everyone else but we now know it is no longer needed...
4713 // so get rid of it. Otherwise, we need to go through the
4714 // normal flow and hide it once we determine that it is
4715 // hidden by the activities in front of it.
4716 if (localLOGV) Log.v(TAG, "Before stopping, can hide: " + s);
4717 mWindowManager.setAppVisibility(s, false);
4718 }
4719 }
4720 if (!s.waitingVisible && remove) {
4721 if (localLOGV) Log.v(TAG, "Ready to stop: " + s);
4722 if (stops == null) {
4723 stops = new ArrayList<HistoryRecord>();
4724 }
4725 stops.add(s);
4726 mStoppingActivities.remove(i);
4727 N--;
4728 i--;
4729 }
4730 }
4731
4732 return stops;
4733 }
4734
4735 void enableScreenAfterBoot() {
4736 mWindowManager.enableScreenAfterBoot();
4737 }
4738
4739 final void activityIdleInternal(IBinder token, boolean fromTimeout) {
4740 if (localLOGV) Log.v(TAG, "Activity idle: " + token);
4741
4742 ArrayList<HistoryRecord> stops = null;
4743 ArrayList<HistoryRecord> finishes = null;
4744 ArrayList<HistoryRecord> thumbnails = null;
4745 int NS = 0;
4746 int NF = 0;
4747 int NT = 0;
4748 IApplicationThread sendThumbnail = null;
4749 boolean booting = false;
4750 boolean enableScreen = false;
4751
4752 synchronized (this) {
4753 if (token != null) {
4754 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
4755 }
4756
4757 // Get the activity record.
4758 int index = indexOfTokenLocked(token, false);
4759 if (index >= 0) {
4760 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4761
4762 // No longer need to keep the device awake.
4763 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
4764 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
4765 mLaunchingActivity.release();
4766 }
4767
4768 // We are now idle. If someone is waiting for a thumbnail from
4769 // us, we can now deliver.
4770 r.idle = true;
4771 scheduleAppGcsLocked();
4772 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
4773 sendThumbnail = r.app.thread;
4774 r.thumbnailNeeded = false;
4775 }
4776
4777 // If this activity is fullscreen, set up to hide those under it.
4778
4779 if (DEBUG_VISBILITY) Log.v(TAG, "Idle activity for " + r);
4780 ensureActivitiesVisibleLocked(null, 0);
4781
4782 //Log.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
4783 if (!mBooted && !fromTimeout) {
4784 mBooted = true;
4785 enableScreen = true;
4786 }
4787 }
4788
4789 // Atomically retrieve all of the other things to do.
4790 stops = processStoppingActivitiesLocked(true);
4791 NS = stops != null ? stops.size() : 0;
4792 if ((NF=mFinishingActivities.size()) > 0) {
4793 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
4794 mFinishingActivities.clear();
4795 }
4796 if ((NT=mCancelledThumbnails.size()) > 0) {
4797 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
4798 mCancelledThumbnails.clear();
4799 }
4800
4801 booting = mBooting;
4802 mBooting = false;
4803 }
4804
4805 int i;
4806
4807 // Send thumbnail if requested.
4808 if (sendThumbnail != null) {
4809 try {
4810 sendThumbnail.requestThumbnail(token);
4811 } catch (Exception e) {
4812 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
4813 sendPendingThumbnail(null, token, null, null, true);
4814 }
4815 }
4816
4817 // Stop any activities that are scheduled to do so but have been
4818 // waiting for the next one to start.
4819 for (i=0; i<NS; i++) {
4820 HistoryRecord r = (HistoryRecord)stops.get(i);
4821 synchronized (this) {
4822 if (r.finishing) {
4823 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
4824 } else {
4825 stopActivityLocked(r);
4826 }
4827 }
4828 }
4829
4830 // Finish any activities that are scheduled to do so but have been
4831 // waiting for the next one to start.
4832 for (i=0; i<NF; i++) {
4833 HistoryRecord r = (HistoryRecord)finishes.get(i);
4834 synchronized (this) {
4835 destroyActivityLocked(r, true);
4836 }
4837 }
4838
4839 // Report back to any thumbnail receivers.
4840 for (i=0; i<NT; i++) {
4841 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
4842 sendPendingThumbnail(r, null, null, null, true);
4843 }
4844
4845 if (booting) {
4846 // Ensure that any processes we had put on hold are now started
4847 // up.
4848 final int NP = mProcessesOnHold.size();
4849 if (NP > 0) {
4850 ArrayList<ProcessRecord> procs =
4851 new ArrayList<ProcessRecord>(mProcessesOnHold);
4852 for (int ip=0; ip<NP; ip++) {
4853 this.startProcessLocked(procs.get(ip), "on-hold", null);
4854 }
4855 }
4856 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
4857 // Tell anyone interested that we are done booting!
4858 synchronized (this) {
4859 broadcastIntentLocked(null, null,
4860 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
4861 null, null, 0, null, null,
4862 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
4863 false, false, MY_PID, Process.SYSTEM_UID);
4864 }
4865 }
4866 }
4867
4868 trimApplications();
4869 //dump();
4870 //mWindowManager.dump();
4871
4872 if (enableScreen) {
4873 EventLog.writeEvent(LOG_BOOT_PROGRESS_ENABLE_SCREEN,
4874 SystemClock.uptimeMillis());
4875 enableScreenAfterBoot();
4876 }
4877 }
4878
4879 public final void activityPaused(IBinder token, Bundle icicle) {
4880 // Refuse possible leaked file descriptors
4881 if (icicle != null && icicle.hasFileDescriptors()) {
4882 throw new IllegalArgumentException("File descriptors passed in Bundle");
4883 }
4884
4885 final long origId = Binder.clearCallingIdentity();
4886 activityPaused(token, icicle, false);
4887 Binder.restoreCallingIdentity(origId);
4888 }
4889
4890 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
4891 if (DEBUG_PAUSE) Log.v(
4892 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
4893 + ", timeout=" + timeout);
4894
4895 HistoryRecord r = null;
4896
4897 synchronized (this) {
4898 int index = indexOfTokenLocked(token, false);
4899 if (index >= 0) {
4900 r = (HistoryRecord)mHistory.get(index);
4901 if (!timeout) {
4902 r.icicle = icicle;
4903 r.haveState = true;
4904 }
4905 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4906 if (mPausingActivity == r) {
4907 r.state = ActivityState.PAUSED;
4908 completePauseLocked();
4909 } else {
4910 EventLog.writeEvent(LOG_AM_FAILED_TO_PAUSE_ACTIVITY,
4911 System.identityHashCode(r), r.shortComponentName,
4912 mPausingActivity != null
4913 ? mPausingActivity.shortComponentName : "(none)");
4914 }
4915 }
4916 }
4917 }
4918
4919 public final void activityStopped(IBinder token, Bitmap thumbnail,
4920 CharSequence description) {
4921 if (localLOGV) Log.v(
4922 TAG, "Activity stopped: token=" + token);
4923
4924 HistoryRecord r = null;
4925
4926 final long origId = Binder.clearCallingIdentity();
4927
4928 synchronized (this) {
4929 int index = indexOfTokenLocked(token, false);
4930 if (index >= 0) {
4931 r = (HistoryRecord)mHistory.get(index);
4932 r.thumbnail = thumbnail;
4933 r.description = description;
4934 r.stopped = true;
4935 r.state = ActivityState.STOPPED;
4936 if (!r.finishing) {
4937 if (r.configDestroy) {
4938 destroyActivityLocked(r, true);
4939 resumeTopActivityLocked(null);
4940 }
4941 }
4942 }
4943 }
4944
4945 if (r != null) {
4946 sendPendingThumbnail(r, null, null, null, false);
4947 }
4948
4949 trimApplications();
4950
4951 Binder.restoreCallingIdentity(origId);
4952 }
4953
4954 public final void activityDestroyed(IBinder token) {
4955 if (DEBUG_SWITCH) Log.v(TAG, "ACTIVITY DESTROYED: " + token);
4956 synchronized (this) {
4957 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
4958
4959 int index = indexOfTokenLocked(token, false);
4960 if (index >= 0) {
4961 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4962 if (r.state == ActivityState.DESTROYING) {
4963 final long origId = Binder.clearCallingIdentity();
4964 removeActivityFromHistoryLocked(r);
4965 Binder.restoreCallingIdentity(origId);
4966 }
4967 }
4968 }
4969 }
4970
4971 public String getCallingPackage(IBinder token) {
4972 synchronized (this) {
4973 HistoryRecord r = getCallingRecordLocked(token);
4974 return r != null && r.app != null ? r.app.processName : null;
4975 }
4976 }
4977
4978 public ComponentName getCallingActivity(IBinder token) {
4979 synchronized (this) {
4980 HistoryRecord r = getCallingRecordLocked(token);
4981 return r != null ? r.intent.getComponent() : null;
4982 }
4983 }
4984
4985 private HistoryRecord getCallingRecordLocked(IBinder token) {
4986 int index = indexOfTokenLocked(token, true);
4987 if (index >= 0) {
4988 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4989 if (r != null) {
4990 return r.resultTo;
4991 }
4992 }
4993 return null;
4994 }
4995
4996 public ComponentName getActivityClassForToken(IBinder token) {
4997 synchronized(this) {
4998 int index = indexOfTokenLocked(token, false);
4999 if (index >= 0) {
5000 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5001 return r.intent.getComponent();
5002 }
5003 return null;
5004 }
5005 }
5006
5007 public String getPackageForToken(IBinder token) {
5008 synchronized(this) {
5009 int index = indexOfTokenLocked(token, false);
5010 if (index >= 0) {
5011 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5012 return r.packageName;
5013 }
5014 return null;
5015 }
5016 }
5017
5018 public IIntentSender getIntentSender(int type,
5019 String packageName, IBinder token, String resultWho,
5020 int requestCode, Intent intent, String resolvedType, int flags) {
5021 // Refuse possible leaked file descriptors
5022 if (intent != null && intent.hasFileDescriptors() == true) {
5023 throw new IllegalArgumentException("File descriptors passed in Intent");
5024 }
5025
5026 synchronized(this) {
5027 int callingUid = Binder.getCallingUid();
5028 try {
5029 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5030 Process.supportsProcesses()) {
5031 int uid = ActivityThread.getPackageManager()
5032 .getPackageUid(packageName);
5033 if (uid != Binder.getCallingUid()) {
5034 String msg = "Permission Denial: getIntentSender() from pid="
5035 + Binder.getCallingPid()
5036 + ", uid=" + Binder.getCallingUid()
5037 + ", (need uid=" + uid + ")"
5038 + " is not allowed to send as package " + packageName;
5039 Log.w(TAG, msg);
5040 throw new SecurityException(msg);
5041 }
5042 }
5043 } catch (RemoteException e) {
5044 throw new SecurityException(e);
5045 }
5046 HistoryRecord activity = null;
5047 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
5048 int index = indexOfTokenLocked(token, false);
5049 if (index < 0) {
5050 return null;
5051 }
5052 activity = (HistoryRecord)mHistory.get(index);
5053 if (activity.finishing) {
5054 return null;
5055 }
5056 }
5057
5058 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5059 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5060 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5061 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5062 |PendingIntent.FLAG_UPDATE_CURRENT);
5063
5064 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5065 type, packageName, activity, resultWho,
5066 requestCode, intent, resolvedType, flags);
5067 WeakReference<PendingIntentRecord> ref;
5068 ref = mIntentSenderRecords.get(key);
5069 PendingIntentRecord rec = ref != null ? ref.get() : null;
5070 if (rec != null) {
5071 if (!cancelCurrent) {
5072 if (updateCurrent) {
5073 rec.key.requestIntent.replaceExtras(intent);
5074 }
5075 return rec;
5076 }
5077 rec.canceled = true;
5078 mIntentSenderRecords.remove(key);
5079 }
5080 if (noCreate) {
5081 return rec;
5082 }
5083 rec = new PendingIntentRecord(this, key, callingUid);
5084 mIntentSenderRecords.put(key, rec.ref);
5085 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
5086 if (activity.pendingResults == null) {
5087 activity.pendingResults
5088 = new HashSet<WeakReference<PendingIntentRecord>>();
5089 }
5090 activity.pendingResults.add(rec.ref);
5091 }
5092 return rec;
5093 }
5094 }
5095
5096 public void cancelIntentSender(IIntentSender sender) {
5097 if (!(sender instanceof PendingIntentRecord)) {
5098 return;
5099 }
5100 synchronized(this) {
5101 PendingIntentRecord rec = (PendingIntentRecord)sender;
5102 try {
5103 int uid = ActivityThread.getPackageManager()
5104 .getPackageUid(rec.key.packageName);
5105 if (uid != Binder.getCallingUid()) {
5106 String msg = "Permission Denial: cancelIntentSender() from pid="
5107 + Binder.getCallingPid()
5108 + ", uid=" + Binder.getCallingUid()
5109 + " is not allowed to cancel packges "
5110 + rec.key.packageName;
5111 Log.w(TAG, msg);
5112 throw new SecurityException(msg);
5113 }
5114 } catch (RemoteException e) {
5115 throw new SecurityException(e);
5116 }
5117 cancelIntentSenderLocked(rec, true);
5118 }
5119 }
5120
5121 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
5122 rec.canceled = true;
5123 mIntentSenderRecords.remove(rec.key);
5124 if (cleanActivity && rec.key.activity != null) {
5125 rec.key.activity.pendingResults.remove(rec.ref);
5126 }
5127 }
5128
5129 public String getPackageForIntentSender(IIntentSender pendingResult) {
5130 if (!(pendingResult instanceof PendingIntentRecord)) {
5131 return null;
5132 }
5133 synchronized(this) {
5134 try {
5135 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
5136 return res.key.packageName;
5137 } catch (ClassCastException e) {
5138 }
5139 }
5140 return null;
5141 }
5142
5143 public void setProcessLimit(int max) {
5144 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5145 "setProcessLimit()");
5146 mProcessLimit = max;
5147 }
5148
5149 public int getProcessLimit() {
5150 return mProcessLimit;
5151 }
5152
5153 void foregroundTokenDied(ForegroundToken token) {
5154 synchronized (ActivityManagerService.this) {
5155 synchronized (mPidsSelfLocked) {
5156 ForegroundToken cur
5157 = mForegroundProcesses.get(token.pid);
5158 if (cur != token) {
5159 return;
5160 }
5161 mForegroundProcesses.remove(token.pid);
5162 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
5163 if (pr == null) {
5164 return;
5165 }
5166 pr.forcingToForeground = null;
5167 pr.foregroundServices = false;
5168 }
5169 updateOomAdjLocked();
5170 }
5171 }
5172
5173 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
5174 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
5175 "setProcessForeground()");
5176 synchronized(this) {
5177 boolean changed = false;
5178
5179 synchronized (mPidsSelfLocked) {
5180 ProcessRecord pr = mPidsSelfLocked.get(pid);
5181 if (pr == null) {
5182 Log.w(TAG, "setProcessForeground called on unknown pid: " + pid);
5183 return;
5184 }
5185 ForegroundToken oldToken = mForegroundProcesses.get(pid);
5186 if (oldToken != null) {
5187 oldToken.token.unlinkToDeath(oldToken, 0);
5188 mForegroundProcesses.remove(pid);
5189 pr.forcingToForeground = null;
5190 changed = true;
5191 }
5192 if (isForeground && token != null) {
5193 ForegroundToken newToken = new ForegroundToken() {
5194 public void binderDied() {
5195 foregroundTokenDied(this);
5196 }
5197 };
5198 newToken.pid = pid;
5199 newToken.token = token;
5200 try {
5201 token.linkToDeath(newToken, 0);
5202 mForegroundProcesses.put(pid, newToken);
5203 pr.forcingToForeground = token;
5204 changed = true;
5205 } catch (RemoteException e) {
5206 // If the process died while doing this, we will later
5207 // do the cleanup with the process death link.
5208 }
5209 }
5210 }
5211
5212 if (changed) {
5213 updateOomAdjLocked();
5214 }
5215 }
5216 }
5217
5218 // =========================================================
5219 // PERMISSIONS
5220 // =========================================================
5221
5222 static class PermissionController extends IPermissionController.Stub {
5223 ActivityManagerService mActivityManagerService;
5224 PermissionController(ActivityManagerService activityManagerService) {
5225 mActivityManagerService = activityManagerService;
5226 }
5227
5228 public boolean checkPermission(String permission, int pid, int uid) {
5229 return mActivityManagerService.checkPermission(permission, pid,
5230 uid) == PackageManager.PERMISSION_GRANTED;
5231 }
5232 }
5233
5234 /**
5235 * This can be called with or without the global lock held.
5236 */
5237 int checkComponentPermission(String permission, int pid, int uid,
5238 int reqUid) {
5239 // We might be performing an operation on behalf of an indirect binder
5240 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
5241 // client identity accordingly before proceeding.
5242 Identity tlsIdentity = sCallerIdentity.get();
5243 if (tlsIdentity != null) {
5244 Log.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
5245 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
5246 uid = tlsIdentity.uid;
5247 pid = tlsIdentity.pid;
5248 }
5249
5250 // Root, system server and our own process get to do everything.
5251 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
5252 !Process.supportsProcesses()) {
5253 return PackageManager.PERMISSION_GRANTED;
5254 }
5255 // If the target requires a specific UID, always fail for others.
5256 if (reqUid >= 0 && uid != reqUid) {
5257 return PackageManager.PERMISSION_DENIED;
5258 }
5259 if (permission == null) {
5260 return PackageManager.PERMISSION_GRANTED;
5261 }
5262 try {
5263 return ActivityThread.getPackageManager()
5264 .checkUidPermission(permission, uid);
5265 } catch (RemoteException e) {
5266 // Should never happen, but if it does... deny!
5267 Log.e(TAG, "PackageManager is dead?!?", e);
5268 }
5269 return PackageManager.PERMISSION_DENIED;
5270 }
5271
5272 /**
5273 * As the only public entry point for permissions checking, this method
5274 * can enforce the semantic that requesting a check on a null global
5275 * permission is automatically denied. (Internally a null permission
5276 * string is used when calling {@link #checkComponentPermission} in cases
5277 * when only uid-based security is needed.)
5278 *
5279 * This can be called with or without the global lock held.
5280 */
5281 public int checkPermission(String permission, int pid, int uid) {
5282 if (permission == null) {
5283 return PackageManager.PERMISSION_DENIED;
5284 }
5285 return checkComponentPermission(permission, pid, uid, -1);
5286 }
5287
5288 /**
5289 * Binder IPC calls go through the public entry point.
5290 * This can be called with or without the global lock held.
5291 */
5292 int checkCallingPermission(String permission) {
5293 return checkPermission(permission,
5294 Binder.getCallingPid(),
5295 Binder.getCallingUid());
5296 }
5297
5298 /**
5299 * This can be called with or without the global lock held.
5300 */
5301 void enforceCallingPermission(String permission, String func) {
5302 if (checkCallingPermission(permission)
5303 == PackageManager.PERMISSION_GRANTED) {
5304 return;
5305 }
5306
5307 String msg = "Permission Denial: " + func + " from pid="
5308 + Binder.getCallingPid()
5309 + ", uid=" + Binder.getCallingUid()
5310 + " requires " + permission;
5311 Log.w(TAG, msg);
5312 throw new SecurityException(msg);
5313 }
5314
5315 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
5316 ProviderInfo pi, int uid, int modeFlags) {
5317 try {
5318 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
5319 if ((pi.readPermission != null) &&
5320 (pm.checkUidPermission(pi.readPermission, uid)
5321 != PackageManager.PERMISSION_GRANTED)) {
5322 return false;
5323 }
5324 }
5325 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
5326 if ((pi.writePermission != null) &&
5327 (pm.checkUidPermission(pi.writePermission, uid)
5328 != PackageManager.PERMISSION_GRANTED)) {
5329 return false;
5330 }
5331 }
5332 return true;
5333 } catch (RemoteException e) {
5334 return false;
5335 }
5336 }
5337
5338 private final boolean checkUriPermissionLocked(Uri uri, int uid,
5339 int modeFlags) {
5340 // Root gets to do everything.
5341 if (uid == 0 || !Process.supportsProcesses()) {
5342 return true;
5343 }
5344 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
5345 if (perms == null) return false;
5346 UriPermission perm = perms.get(uri);
5347 if (perm == null) return false;
5348 return (modeFlags&perm.modeFlags) == modeFlags;
5349 }
5350
5351 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
5352 // Another redirected-binder-call permissions check as in
5353 // {@link checkComponentPermission}.
5354 Identity tlsIdentity = sCallerIdentity.get();
5355 if (tlsIdentity != null) {
5356 uid = tlsIdentity.uid;
5357 pid = tlsIdentity.pid;
5358 }
5359
5360 // Our own process gets to do everything.
5361 if (pid == MY_PID) {
5362 return PackageManager.PERMISSION_GRANTED;
5363 }
5364 synchronized(this) {
5365 return checkUriPermissionLocked(uri, uid, modeFlags)
5366 ? PackageManager.PERMISSION_GRANTED
5367 : PackageManager.PERMISSION_DENIED;
5368 }
5369 }
5370
5371 private void grantUriPermissionLocked(int callingUid,
5372 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
5373 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5374 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5375 if (modeFlags == 0) {
5376 return;
5377 }
5378
5379 final IPackageManager pm = ActivityThread.getPackageManager();
5380
5381 // If this is not a content: uri, we can't do anything with it.
5382 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
5383 return;
5384 }
5385
5386 String name = uri.getAuthority();
5387 ProviderInfo pi = null;
5388 ContentProviderRecord cpr
5389 = (ContentProviderRecord)mProvidersByName.get(name);
5390 if (cpr != null) {
5391 pi = cpr.info;
5392 } else {
5393 try {
5394 pi = pm.resolveContentProvider(name,
5395 PackageManager.GET_URI_PERMISSION_PATTERNS);
5396 } catch (RemoteException ex) {
5397 }
5398 }
5399 if (pi == null) {
5400 Log.w(TAG, "No content provider found for: " + name);
5401 return;
5402 }
5403
5404 int targetUid;
5405 try {
5406 targetUid = pm.getPackageUid(targetPkg);
5407 if (targetUid < 0) {
5408 return;
5409 }
5410 } catch (RemoteException ex) {
5411 return;
5412 }
5413
5414 // First... does the target actually need this permission?
5415 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
5416 // No need to grant the target this permission.
5417 return;
5418 }
5419
5420 // Second... maybe someone else has already granted the
5421 // permission?
5422 if (checkUriPermissionLocked(uri, targetUid, modeFlags)) {
5423 // No need to grant the target this permission.
5424 return;
5425 }
5426
5427 // Third... is the provider allowing granting of URI permissions?
5428 if (!pi.grantUriPermissions) {
5429 throw new SecurityException("Provider " + pi.packageName
5430 + "/" + pi.name
5431 + " does not allow granting of Uri permissions (uri "
5432 + uri + ")");
5433 }
5434 if (pi.uriPermissionPatterns != null) {
5435 final int N = pi.uriPermissionPatterns.length;
5436 boolean allowed = false;
5437 for (int i=0; i<N; i++) {
5438 if (pi.uriPermissionPatterns[i] != null
5439 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
5440 allowed = true;
5441 break;
5442 }
5443 }
5444 if (!allowed) {
5445 throw new SecurityException("Provider " + pi.packageName
5446 + "/" + pi.name
5447 + " does not allow granting of permission to path of Uri "
5448 + uri);
5449 }
5450 }
5451
5452 // Fourth... does the caller itself have permission to access
5453 // this uri?
5454 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
5455 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
5456 throw new SecurityException("Uid " + callingUid
5457 + " does not have permission to uri " + uri);
5458 }
5459 }
5460
5461 // Okay! So here we are: the caller has the assumed permission
5462 // to the uri, and the target doesn't. Let's now give this to
5463 // the target.
5464
5465 HashMap<Uri, UriPermission> targetUris
5466 = mGrantedUriPermissions.get(targetUid);
5467 if (targetUris == null) {
5468 targetUris = new HashMap<Uri, UriPermission>();
5469 mGrantedUriPermissions.put(targetUid, targetUris);
5470 }
5471
5472 UriPermission perm = targetUris.get(uri);
5473 if (perm == null) {
5474 perm = new UriPermission(targetUid, uri);
5475 targetUris.put(uri, perm);
5476
5477 }
5478 perm.modeFlags |= modeFlags;
5479 if (activity == null) {
5480 perm.globalModeFlags |= modeFlags;
5481 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
5482 perm.readActivities.add(activity);
5483 if (activity.readUriPermissions == null) {
5484 activity.readUriPermissions = new HashSet<UriPermission>();
5485 }
5486 activity.readUriPermissions.add(perm);
5487 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
5488 perm.writeActivities.add(activity);
5489 if (activity.writeUriPermissions == null) {
5490 activity.writeUriPermissions = new HashSet<UriPermission>();
5491 }
5492 activity.writeUriPermissions.add(perm);
5493 }
5494 }
5495
5496 private void grantUriPermissionFromIntentLocked(int callingUid,
5497 String targetPkg, Intent intent, HistoryRecord activity) {
5498 if (intent == null) {
5499 return;
5500 }
5501 Uri data = intent.getData();
5502 if (data == null) {
5503 return;
5504 }
5505 grantUriPermissionLocked(callingUid, targetPkg, data,
5506 intent.getFlags(), activity);
5507 }
5508
5509 public void grantUriPermission(IApplicationThread caller, String targetPkg,
5510 Uri uri, int modeFlags) {
5511 synchronized(this) {
5512 final ProcessRecord r = getRecordForAppLocked(caller);
5513 if (r == null) {
5514 throw new SecurityException("Unable to find app for caller "
5515 + caller
5516 + " when granting permission to uri " + uri);
5517 }
5518 if (targetPkg == null) {
5519 Log.w(TAG, "grantUriPermission: null target");
5520 return;
5521 }
5522 if (uri == null) {
5523 Log.w(TAG, "grantUriPermission: null uri");
5524 return;
5525 }
5526
5527 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
5528 null);
5529 }
5530 }
5531
5532 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
5533 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
5534 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
5535 HashMap<Uri, UriPermission> perms
5536 = mGrantedUriPermissions.get(perm.uid);
5537 if (perms != null) {
5538 perms.remove(perm.uri);
5539 if (perms.size() == 0) {
5540 mGrantedUriPermissions.remove(perm.uid);
5541 }
5542 }
5543 }
5544 }
5545
5546 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
5547 if (activity.readUriPermissions != null) {
5548 for (UriPermission perm : activity.readUriPermissions) {
5549 perm.readActivities.remove(activity);
5550 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
5551 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
5552 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
5553 removeUriPermissionIfNeededLocked(perm);
5554 }
5555 }
5556 }
5557 if (activity.writeUriPermissions != null) {
5558 for (UriPermission perm : activity.writeUriPermissions) {
5559 perm.writeActivities.remove(activity);
5560 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
5561 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
5562 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
5563 removeUriPermissionIfNeededLocked(perm);
5564 }
5565 }
5566 }
5567 }
5568
5569 private void revokeUriPermissionLocked(int callingUid, Uri uri,
5570 int modeFlags) {
5571 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5572 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5573 if (modeFlags == 0) {
5574 return;
5575 }
5576
5577 final IPackageManager pm = ActivityThread.getPackageManager();
5578
5579 final String authority = uri.getAuthority();
5580 ProviderInfo pi = null;
5581 ContentProviderRecord cpr
5582 = (ContentProviderRecord)mProvidersByName.get(authority);
5583 if (cpr != null) {
5584 pi = cpr.info;
5585 } else {
5586 try {
5587 pi = pm.resolveContentProvider(authority,
5588 PackageManager.GET_URI_PERMISSION_PATTERNS);
5589 } catch (RemoteException ex) {
5590 }
5591 }
5592 if (pi == null) {
5593 Log.w(TAG, "No content provider found for: " + authority);
5594 return;
5595 }
5596
5597 // Does the caller have this permission on the URI?
5598 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
5599 // Right now, if you are not the original owner of the permission,
5600 // you are not allowed to revoke it.
5601 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
5602 throw new SecurityException("Uid " + callingUid
5603 + " does not have permission to uri " + uri);
5604 //}
5605 }
5606
5607 // Go through all of the permissions and remove any that match.
5608 final List<String> SEGMENTS = uri.getPathSegments();
5609 if (SEGMENTS != null) {
5610 final int NS = SEGMENTS.size();
5611 int N = mGrantedUriPermissions.size();
5612 for (int i=0; i<N; i++) {
5613 HashMap<Uri, UriPermission> perms
5614 = mGrantedUriPermissions.valueAt(i);
5615 Iterator<UriPermission> it = perms.values().iterator();
5616 toploop:
5617 while (it.hasNext()) {
5618 UriPermission perm = it.next();
5619 Uri targetUri = perm.uri;
5620 if (!authority.equals(targetUri.getAuthority())) {
5621 continue;
5622 }
5623 List<String> targetSegments = targetUri.getPathSegments();
5624 if (targetSegments == null) {
5625 continue;
5626 }
5627 if (targetSegments.size() < NS) {
5628 continue;
5629 }
5630 for (int j=0; j<NS; j++) {
5631 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
5632 continue toploop;
5633 }
5634 }
5635 perm.clearModes(modeFlags);
5636 if (perm.modeFlags == 0) {
5637 it.remove();
5638 }
5639 }
5640 if (perms.size() == 0) {
5641 mGrantedUriPermissions.remove(
5642 mGrantedUriPermissions.keyAt(i));
5643 N--;
5644 i--;
5645 }
5646 }
5647 }
5648 }
5649
5650 public void revokeUriPermission(IApplicationThread caller, Uri uri,
5651 int modeFlags) {
5652 synchronized(this) {
5653 final ProcessRecord r = getRecordForAppLocked(caller);
5654 if (r == null) {
5655 throw new SecurityException("Unable to find app for caller "
5656 + caller
5657 + " when revoking permission to uri " + uri);
5658 }
5659 if (uri == null) {
5660 Log.w(TAG, "revokeUriPermission: null uri");
5661 return;
5662 }
5663
5664 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5665 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5666 if (modeFlags == 0) {
5667 return;
5668 }
5669
5670 final IPackageManager pm = ActivityThread.getPackageManager();
5671
5672 final String authority = uri.getAuthority();
5673 ProviderInfo pi = null;
5674 ContentProviderRecord cpr
5675 = (ContentProviderRecord)mProvidersByName.get(authority);
5676 if (cpr != null) {
5677 pi = cpr.info;
5678 } else {
5679 try {
5680 pi = pm.resolveContentProvider(authority,
5681 PackageManager.GET_URI_PERMISSION_PATTERNS);
5682 } catch (RemoteException ex) {
5683 }
5684 }
5685 if (pi == null) {
5686 Log.w(TAG, "No content provider found for: " + authority);
5687 return;
5688 }
5689
5690 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
5691 }
5692 }
5693
5694 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
5695 synchronized (this) {
5696 ProcessRecord app =
5697 who != null ? getRecordForAppLocked(who) : null;
5698 if (app == null) return;
5699
5700 Message msg = Message.obtain();
5701 msg.what = WAIT_FOR_DEBUGGER_MSG;
5702 msg.obj = app;
5703 msg.arg1 = waiting ? 1 : 0;
5704 mHandler.sendMessage(msg);
5705 }
5706 }
5707
5708 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
5709 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08005710 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005711 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08005712 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005713 }
5714
5715 // =========================================================
5716 // TASK MANAGEMENT
5717 // =========================================================
5718
5719 public List getTasks(int maxNum, int flags,
5720 IThumbnailReceiver receiver) {
5721 ArrayList list = new ArrayList();
5722
5723 PendingThumbnailsRecord pending = null;
5724 IApplicationThread topThumbnail = null;
5725 HistoryRecord topRecord = null;
5726
5727 synchronized(this) {
5728 if (localLOGV) Log.v(
5729 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
5730 + ", receiver=" + receiver);
5731
5732 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
5733 != PackageManager.PERMISSION_GRANTED) {
5734 if (receiver != null) {
5735 // If the caller wants to wait for pending thumbnails,
5736 // it ain't gonna get them.
5737 try {
5738 receiver.finished();
5739 } catch (RemoteException ex) {
5740 }
5741 }
5742 String msg = "Permission Denial: getTasks() from pid="
5743 + Binder.getCallingPid()
5744 + ", uid=" + Binder.getCallingUid()
5745 + " requires " + android.Manifest.permission.GET_TASKS;
5746 Log.w(TAG, msg);
5747 throw new SecurityException(msg);
5748 }
5749
5750 int pos = mHistory.size()-1;
5751 HistoryRecord next =
5752 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
5753 HistoryRecord top = null;
5754 CharSequence topDescription = null;
5755 TaskRecord curTask = null;
5756 int numActivities = 0;
5757 int numRunning = 0;
5758 while (pos >= 0 && maxNum > 0) {
5759 final HistoryRecord r = next;
5760 pos--;
5761 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
5762
5763 // Initialize state for next task if needed.
5764 if (top == null ||
5765 (top.state == ActivityState.INITIALIZING
5766 && top.task == r.task)) {
5767 top = r;
5768 topDescription = r.description;
5769 curTask = r.task;
5770 numActivities = numRunning = 0;
5771 }
5772
5773 // Add 'r' into the current task.
5774 numActivities++;
5775 if (r.app != null && r.app.thread != null) {
5776 numRunning++;
5777 }
5778 if (topDescription == null) {
5779 topDescription = r.description;
5780 }
5781
5782 if (localLOGV) Log.v(
5783 TAG, r.intent.getComponent().flattenToShortString()
5784 + ": task=" + r.task);
5785
5786 // If the next one is a different task, generate a new
5787 // TaskInfo entry for what we have.
5788 if (next == null || next.task != curTask) {
5789 ActivityManager.RunningTaskInfo ci
5790 = new ActivityManager.RunningTaskInfo();
5791 ci.id = curTask.taskId;
5792 ci.baseActivity = r.intent.getComponent();
5793 ci.topActivity = top.intent.getComponent();
5794 ci.thumbnail = top.thumbnail;
5795 ci.description = topDescription;
5796 ci.numActivities = numActivities;
5797 ci.numRunning = numRunning;
5798 //System.out.println(
5799 // "#" + maxNum + ": " + " descr=" + ci.description);
5800 if (ci.thumbnail == null && receiver != null) {
5801 if (localLOGV) Log.v(
5802 TAG, "State=" + top.state + "Idle=" + top.idle
5803 + " app=" + top.app
5804 + " thr=" + (top.app != null ? top.app.thread : null));
5805 if (top.state == ActivityState.RESUMED
5806 || top.state == ActivityState.PAUSING) {
5807 if (top.idle && top.app != null
5808 && top.app.thread != null) {
5809 topRecord = top;
5810 topThumbnail = top.app.thread;
5811 } else {
5812 top.thumbnailNeeded = true;
5813 }
5814 }
5815 if (pending == null) {
5816 pending = new PendingThumbnailsRecord(receiver);
5817 }
5818 pending.pendingRecords.add(top);
5819 }
5820 list.add(ci);
5821 maxNum--;
5822 top = null;
5823 }
5824 }
5825
5826 if (pending != null) {
5827 mPendingThumbnails.add(pending);
5828 }
5829 }
5830
5831 if (localLOGV) Log.v(TAG, "We have pending thumbnails: " + pending);
5832
5833 if (topThumbnail != null) {
5834 if (localLOGV) Log.v(TAG, "Requesting top thumbnail");
5835 try {
5836 topThumbnail.requestThumbnail(topRecord);
5837 } catch (Exception e) {
5838 Log.w(TAG, "Exception thrown when requesting thumbnail", e);
5839 sendPendingThumbnail(null, topRecord, null, null, true);
5840 }
5841 }
5842
5843 if (pending == null && receiver != null) {
5844 // In this case all thumbnails were available and the client
5845 // is being asked to be told when the remaining ones come in...
5846 // which is unusually, since the top-most currently running
5847 // activity should never have a canned thumbnail! Oh well.
5848 try {
5849 receiver.finished();
5850 } catch (RemoteException ex) {
5851 }
5852 }
5853
5854 return list;
5855 }
5856
5857 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5858 int flags) {
5859 synchronized (this) {
5860 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5861 "getRecentTasks()");
5862
5863 final int N = mRecentTasks.size();
5864 ArrayList<ActivityManager.RecentTaskInfo> res
5865 = new ArrayList<ActivityManager.RecentTaskInfo>(
5866 maxNum < N ? maxNum : N);
5867 for (int i=0; i<N && maxNum > 0; i++) {
5868 TaskRecord tr = mRecentTasks.get(i);
5869 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
5870 || (tr.intent == null)
5871 || ((tr.intent.getFlags()
5872 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5873 ActivityManager.RecentTaskInfo rti
5874 = new ActivityManager.RecentTaskInfo();
5875 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
5876 rti.baseIntent = new Intent(
5877 tr.intent != null ? tr.intent : tr.affinityIntent);
5878 rti.origActivity = tr.origActivity;
5879 res.add(rti);
5880 maxNum--;
5881 }
5882 }
5883 return res;
5884 }
5885 }
5886
5887 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5888 int j;
5889 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
5890 TaskRecord jt = startTask;
5891
5892 // First look backwards
5893 for (j=startIndex-1; j>=0; j--) {
5894 HistoryRecord r = (HistoryRecord)mHistory.get(j);
5895 if (r.task != jt) {
5896 jt = r.task;
5897 if (affinity.equals(jt.affinity)) {
5898 return j;
5899 }
5900 }
5901 }
5902
5903 // Now look forwards
5904 final int N = mHistory.size();
5905 jt = startTask;
5906 for (j=startIndex+1; j<N; j++) {
5907 HistoryRecord r = (HistoryRecord)mHistory.get(j);
5908 if (r.task != jt) {
5909 if (affinity.equals(jt.affinity)) {
5910 return j;
5911 }
5912 jt = r.task;
5913 }
5914 }
5915
5916 // Might it be at the top?
5917 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
5918 return N-1;
5919 }
5920
5921 return -1;
5922 }
5923
5924 /**
5925 * Perform a reset of the given task, if needed as part of launching it.
5926 * Returns the new HistoryRecord at the top of the task.
5927 */
5928 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
5929 HistoryRecord newActivity) {
5930 boolean forceReset = (newActivity.info.flags
5931 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
5932 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
5933 if ((newActivity.info.flags
5934 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
5935 forceReset = true;
5936 }
5937 }
5938
5939 final TaskRecord task = taskTop.task;
5940
5941 // We are going to move through the history list so that we can look
5942 // at each activity 'target' with 'below' either the interesting
5943 // activity immediately below it in the stack or null.
5944 HistoryRecord target = null;
5945 int targetI = 0;
5946 int taskTopI = -1;
5947 int replyChainEnd = -1;
5948 int lastReparentPos = -1;
5949 for (int i=mHistory.size()-1; i>=-1; i--) {
5950 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
5951
5952 if (below != null && below.finishing) {
5953 continue;
5954 }
5955 if (target == null) {
5956 target = below;
5957 targetI = i;
5958 // If we were in the middle of a reply chain before this
5959 // task, it doesn't appear like the root of the chain wants
5960 // anything interesting, so drop it.
5961 replyChainEnd = -1;
5962 continue;
5963 }
5964
5965 final int flags = target.info.flags;
5966
5967 final boolean finishOnTaskLaunch =
5968 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
5969 final boolean allowTaskReparenting =
5970 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
5971
5972 if (target.task == task) {
5973 // We are inside of the task being reset... we'll either
5974 // finish this activity, push it out for another task,
5975 // or leave it as-is. We only do this
5976 // for activities that are not the root of the task (since
5977 // if we finish the root, we may no longer have the task!).
5978 if (taskTopI < 0) {
5979 taskTopI = targetI;
5980 }
5981 if (below != null && below.task == task) {
5982 final boolean clearWhenTaskReset =
5983 (target.intent.getFlags()
5984 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
5985 if (!finishOnTaskLaunch && target.resultTo != null) {
5986 // If this activity is sending a reply to a previous
5987 // activity, we can't do anything with it now until
5988 // we reach the start of the reply chain.
5989 // XXX note that we are assuming the result is always
5990 // to the previous activity, which is almost always
5991 // the case but we really shouldn't count on.
5992 if (replyChainEnd < 0) {
5993 replyChainEnd = targetI;
5994 }
5995 } else if (!finishOnTaskLaunch && allowTaskReparenting
5996 && target.taskAffinity != null
5997 && !target.taskAffinity.equals(task.affinity)) {
5998 // If this activity has an affinity for another
5999 // task, then we need to move it out of here. We will
6000 // move it as far out of the way as possible, to the
6001 // bottom of the activity stack. This also keeps it
6002 // correctly ordered with any activities we previously
6003 // moved.
6004 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6005 if (target.taskAffinity != null
6006 && target.taskAffinity.equals(p.task.affinity)) {
6007 // If the activity currently at the bottom has the
6008 // same task affinity as the one we are moving,
6009 // then merge it into the same task.
6010 target.task = p.task;
6011 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6012 + " out to bottom task " + p.task);
6013 } else {
6014 mCurTask++;
6015 if (mCurTask <= 0) {
6016 mCurTask = 1;
6017 }
6018 target.task = new TaskRecord(mCurTask, target.info, null,
6019 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6020 target.task.affinityIntent = target.intent;
6021 if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
6022 + " out to new task " + target.task);
6023 }
6024 mWindowManager.setAppGroupId(target, task.taskId);
6025 if (replyChainEnd < 0) {
6026 replyChainEnd = targetI;
6027 }
6028 int dstPos = 0;
6029 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6030 p = (HistoryRecord)mHistory.get(srcPos);
6031 if (p.finishing) {
6032 continue;
6033 }
6034 if (DEBUG_TASKS) Log.v(TAG, "Pushing next activity " + p
6035 + " out to target's task " + target.task);
6036 task.numActivities--;
6037 p.task = target.task;
6038 target.task.numActivities++;
6039 mHistory.remove(srcPos);
6040 mHistory.add(dstPos, p);
6041 mWindowManager.moveAppToken(dstPos, p);
6042 mWindowManager.setAppGroupId(p, p.task.taskId);
6043 dstPos++;
6044 if (VALIDATE_TOKENS) {
6045 mWindowManager.validateAppTokens(mHistory);
6046 }
6047 i++;
6048 }
6049 if (taskTop == p) {
6050 taskTop = below;
6051 }
6052 if (taskTopI == replyChainEnd) {
6053 taskTopI = -1;
6054 }
6055 replyChainEnd = -1;
6056 addRecentTask(target.task);
6057 } else if (forceReset || finishOnTaskLaunch
6058 || clearWhenTaskReset) {
6059 // If the activity should just be removed -- either
6060 // because it asks for it, or the task should be
6061 // cleared -- then finish it and anything that is
6062 // part of its reply chain.
6063 if (clearWhenTaskReset) {
6064 // In this case, we want to finish this activity
6065 // and everything above it, so be sneaky and pretend
6066 // like these are all in the reply chain.
6067 replyChainEnd = targetI+1;
6068 while (replyChainEnd < mHistory.size() &&
6069 ((HistoryRecord)mHistory.get(
6070 replyChainEnd)).task == task) {
6071 replyChainEnd++;
6072 }
6073 replyChainEnd--;
6074 } else if (replyChainEnd < 0) {
6075 replyChainEnd = targetI;
6076 }
6077 HistoryRecord p = null;
6078 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6079 p = (HistoryRecord)mHistory.get(srcPos);
6080 if (p.finishing) {
6081 continue;
6082 }
6083 if (finishActivityLocked(p, srcPos,
6084 Activity.RESULT_CANCELED, null, "reset")) {
6085 replyChainEnd--;
6086 srcPos--;
6087 }
6088 }
6089 if (taskTop == p) {
6090 taskTop = below;
6091 }
6092 if (taskTopI == replyChainEnd) {
6093 taskTopI = -1;
6094 }
6095 replyChainEnd = -1;
6096 } else {
6097 // If we were in the middle of a chain, well the
6098 // activity that started it all doesn't want anything
6099 // special, so leave it all as-is.
6100 replyChainEnd = -1;
6101 }
6102 } else {
6103 // Reached the bottom of the task -- any reply chain
6104 // should be left as-is.
6105 replyChainEnd = -1;
6106 }
6107
6108 } else if (target.resultTo != null) {
6109 // If this activity is sending a reply to a previous
6110 // activity, we can't do anything with it now until
6111 // we reach the start of the reply chain.
6112 // XXX note that we are assuming the result is always
6113 // to the previous activity, which is almost always
6114 // the case but we really shouldn't count on.
6115 if (replyChainEnd < 0) {
6116 replyChainEnd = targetI;
6117 }
6118
6119 } else if (taskTopI >= 0 && allowTaskReparenting
6120 && task.affinity != null
6121 && task.affinity.equals(target.taskAffinity)) {
6122 // We are inside of another task... if this activity has
6123 // an affinity for our task, then either remove it if we are
6124 // clearing or move it over to our task. Note that
6125 // we currently punt on the case where we are resetting a
6126 // task that is not at the top but who has activities above
6127 // with an affinity to it... this is really not a normal
6128 // case, and we will need to later pull that task to the front
6129 // and usually at that point we will do the reset and pick
6130 // up those remaining activities. (This only happens if
6131 // someone starts an activity in a new task from an activity
6132 // in a task that is not currently on top.)
6133 if (forceReset || finishOnTaskLaunch) {
6134 if (replyChainEnd < 0) {
6135 replyChainEnd = targetI;
6136 }
6137 HistoryRecord p = null;
6138 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6139 p = (HistoryRecord)mHistory.get(srcPos);
6140 if (p.finishing) {
6141 continue;
6142 }
6143 if (finishActivityLocked(p, srcPos,
6144 Activity.RESULT_CANCELED, null, "reset")) {
6145 taskTopI--;
6146 lastReparentPos--;
6147 replyChainEnd--;
6148 srcPos--;
6149 }
6150 }
6151 replyChainEnd = -1;
6152 } else {
6153 if (replyChainEnd < 0) {
6154 replyChainEnd = targetI;
6155 }
6156 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
6157 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
6158 if (p.finishing) {
6159 continue;
6160 }
6161 if (lastReparentPos < 0) {
6162 lastReparentPos = taskTopI;
6163 taskTop = p;
6164 } else {
6165 lastReparentPos--;
6166 }
6167 mHistory.remove(srcPos);
6168 p.task.numActivities--;
6169 p.task = task;
6170 mHistory.add(lastReparentPos, p);
6171 if (DEBUG_TASKS) Log.v(TAG, "Pulling activity " + p
6172 + " in to resetting task " + task);
6173 task.numActivities++;
6174 mWindowManager.moveAppToken(lastReparentPos, p);
6175 mWindowManager.setAppGroupId(p, p.task.taskId);
6176 if (VALIDATE_TOKENS) {
6177 mWindowManager.validateAppTokens(mHistory);
6178 }
6179 }
6180 replyChainEnd = -1;
6181
6182 // Now we've moved it in to place... but what if this is
6183 // a singleTop activity and we have put it on top of another
6184 // instance of the same activity? Then we drop the instance
6185 // below so it remains singleTop.
6186 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
6187 for (int j=lastReparentPos-1; j>=0; j--) {
6188 HistoryRecord p = (HistoryRecord)mHistory.get(j);
6189 if (p.finishing) {
6190 continue;
6191 }
6192 if (p.intent.getComponent().equals(target.intent.getComponent())) {
6193 if (finishActivityLocked(p, j,
6194 Activity.RESULT_CANCELED, null, "replace")) {
6195 taskTopI--;
6196 lastReparentPos--;
6197 }
6198 }
6199 }
6200 }
6201 }
6202 }
6203
6204 target = below;
6205 targetI = i;
6206 }
6207
6208 return taskTop;
6209 }
6210
6211 /**
6212 * TODO: Add mWatcher hook
6213 */
6214 public void moveTaskToFront(int task) {
6215 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6216 "moveTaskToFront()");
6217
6218 synchronized(this) {
6219 final long origId = Binder.clearCallingIdentity();
6220 try {
6221 int N = mRecentTasks.size();
6222 for (int i=0; i<N; i++) {
6223 TaskRecord tr = mRecentTasks.get(i);
6224 if (tr.taskId == task) {
6225 moveTaskToFrontLocked(tr);
6226 return;
6227 }
6228 }
6229 for (int i=mHistory.size()-1; i>=0; i--) {
6230 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
6231 if (hr.task.taskId == task) {
6232 moveTaskToFrontLocked(hr.task);
6233 return;
6234 }
6235 }
6236 } finally {
6237 Binder.restoreCallingIdentity(origId);
6238 }
6239 }
6240 }
6241
6242 private final void moveTaskToFrontLocked(TaskRecord tr) {
6243 if (DEBUG_SWITCH) Log.v(TAG, "moveTaskToFront: " + tr);
6244
6245 final int task = tr.taskId;
6246 int top = mHistory.size()-1;
6247
6248 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
6249 // nothing to do!
6250 return;
6251 }
6252
6253 if (DEBUG_TRANSITION) Log.v(TAG,
6254 "Prepare to front transition: task=" + tr);
6255 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
6256
6257 ArrayList moved = new ArrayList();
6258
6259 // Applying the affinities may have removed entries from the history,
6260 // so get the size again.
6261 top = mHistory.size()-1;
6262 int pos = top;
6263
6264 // Shift all activities with this task up to the top
6265 // of the stack, keeping them in the same internal order.
6266 while (pos >= 0) {
6267 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
6268 if (localLOGV) Log.v(
6269 TAG, "At " + pos + " ckp " + r.task + ": " + r);
6270 boolean first = true;
6271 if (r.task.taskId == task) {
6272 if (localLOGV) Log.v(TAG, "Removing and adding at " + top);
6273 mHistory.remove(pos);
6274 mHistory.add(top, r);
6275 moved.add(0, r);
6276 top--;
6277 if (first) {
6278 addRecentTask(r.task);
6279 first = false;
6280 }
6281 }
6282 pos--;
6283 }
6284
6285 mWindowManager.moveAppTokensToTop(moved);
6286 if (VALIDATE_TOKENS) {
6287 mWindowManager.validateAppTokens(mHistory);
6288 }
6289
6290 finishTaskMove(task);
6291 EventLog.writeEvent(LOG_TASK_TO_FRONT, task);
6292 }
6293
6294 private final void finishTaskMove(int task) {
6295 resumeTopActivityLocked(null);
6296 }
6297
6298 public void moveTaskToBack(int task) {
6299 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6300 "moveTaskToBack()");
6301
6302 synchronized(this) {
6303 final long origId = Binder.clearCallingIdentity();
6304 moveTaskToBackLocked(task);
6305 Binder.restoreCallingIdentity(origId);
6306 }
6307 }
6308
6309 /**
6310 * Moves an activity, and all of the other activities within the same task, to the bottom
6311 * of the history stack. The activity's order within the task is unchanged.
6312 *
6313 * @param token A reference to the activity we wish to move
6314 * @param nonRoot If false then this only works if the activity is the root
6315 * of a task; if true it will work for any activity in a task.
6316 * @return Returns true if the move completed, false if not.
6317 */
6318 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
6319 synchronized(this) {
6320 final long origId = Binder.clearCallingIdentity();
6321 int taskId = getTaskForActivityLocked(token, !nonRoot);
6322 if (taskId >= 0) {
6323 return moveTaskToBackLocked(taskId);
6324 }
6325 Binder.restoreCallingIdentity(origId);
6326 }
6327 return false;
6328 }
6329
6330 /**
6331 * Worker method for rearranging history stack. Implements the function of moving all
6332 * activities for a specific task (gathering them if disjoint) into a single group at the
6333 * bottom of the stack.
6334 *
6335 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
6336 * to premeptively cancel the move.
6337 *
6338 * @param task The taskId to collect and move to the bottom.
6339 * @return Returns true if the move completed, false if not.
6340 */
6341 private final boolean moveTaskToBackLocked(int task) {
6342 Log.i(TAG, "moveTaskToBack: " + task);
6343
6344 // If we have a watcher, preflight the move before committing to it. First check
6345 // for *other* available tasks, but if none are available, then try again allowing the
6346 // current task to be selected.
6347 if (mWatcher != null) {
6348 HistoryRecord next = topRunningActivityLocked(null, task);
6349 if (next == null) {
6350 next = topRunningActivityLocked(null, 0);
6351 }
6352 if (next != null) {
6353 // ask watcher if this is allowed
6354 boolean moveOK = true;
6355 try {
6356 moveOK = mWatcher.activityResuming(next.packageName);
6357 } catch (RemoteException e) {
6358 mWatcher = null;
6359 }
6360 if (!moveOK) {
6361 return false;
6362 }
6363 }
6364 }
6365
6366 ArrayList moved = new ArrayList();
6367
6368 if (DEBUG_TRANSITION) Log.v(TAG,
6369 "Prepare to back transition: task=" + task);
6370 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
6371
6372 final int N = mHistory.size();
6373 int bottom = 0;
6374 int pos = 0;
6375
6376 // Shift all activities with this task down to the bottom
6377 // of the stack, keeping them in the same internal order.
6378 while (pos < N) {
6379 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
6380 if (localLOGV) Log.v(
6381 TAG, "At " + pos + " ckp " + r.task + ": " + r);
6382 if (r.task.taskId == task) {
6383 if (localLOGV) Log.v(TAG, "Removing and adding at " + (N-1));
6384 mHistory.remove(pos);
6385 mHistory.add(bottom, r);
6386 moved.add(r);
6387 bottom++;
6388 }
6389 pos++;
6390 }
6391
6392 mWindowManager.moveAppTokensToBottom(moved);
6393 if (VALIDATE_TOKENS) {
6394 mWindowManager.validateAppTokens(mHistory);
6395 }
6396
6397 finishTaskMove(task);
6398 return true;
6399 }
6400
6401 public void moveTaskBackwards(int task) {
6402 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
6403 "moveTaskBackwards()");
6404
6405 synchronized(this) {
6406 final long origId = Binder.clearCallingIdentity();
6407 moveTaskBackwardsLocked(task);
6408 Binder.restoreCallingIdentity(origId);
6409 }
6410 }
6411
6412 private final void moveTaskBackwardsLocked(int task) {
6413 Log.e(TAG, "moveTaskBackwards not yet implemented!");
6414 }
6415
6416 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
6417 synchronized(this) {
6418 return getTaskForActivityLocked(token, onlyRoot);
6419 }
6420 }
6421
6422 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
6423 final int N = mHistory.size();
6424 TaskRecord lastTask = null;
6425 for (int i=0; i<N; i++) {
6426 HistoryRecord r = (HistoryRecord)mHistory.get(i);
6427 if (r == token) {
6428 if (!onlyRoot || lastTask != r.task) {
6429 return r.task.taskId;
6430 }
6431 return -1;
6432 }
6433 lastTask = r.task;
6434 }
6435
6436 return -1;
6437 }
6438
6439 /**
6440 * Returns the top activity in any existing task matching the given
6441 * Intent. Returns null if no such task is found.
6442 */
6443 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
6444 ComponentName cls = intent.getComponent();
6445 if (info.targetActivity != null) {
6446 cls = new ComponentName(info.packageName, info.targetActivity);
6447 }
6448
6449 TaskRecord cp = null;
6450
6451 final int N = mHistory.size();
6452 for (int i=(N-1); i>=0; i--) {
6453 HistoryRecord r = (HistoryRecord)mHistory.get(i);
6454 if (!r.finishing && r.task != cp
6455 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
6456 cp = r.task;
6457 //Log.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
6458 // + "/aff=" + r.task.affinity + " to new cls="
6459 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
6460 if (r.task.affinity != null) {
6461 if (r.task.affinity.equals(info.taskAffinity)) {
6462 //Log.i(TAG, "Found matching affinity!");
6463 return r;
6464 }
6465 } else if (r.task.intent != null
6466 && r.task.intent.getComponent().equals(cls)) {
6467 //Log.i(TAG, "Found matching class!");
6468 //dump();
6469 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
6470 return r;
6471 } else if (r.task.affinityIntent != null
6472 && r.task.affinityIntent.getComponent().equals(cls)) {
6473 //Log.i(TAG, "Found matching class!");
6474 //dump();
6475 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
6476 return r;
6477 }
6478 }
6479 }
6480
6481 return null;
6482 }
6483
6484 /**
6485 * Returns the first activity (starting from the top of the stack) that
6486 * is the same as the given activity. Returns null if no such activity
6487 * is found.
6488 */
6489 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
6490 ComponentName cls = intent.getComponent();
6491 if (info.targetActivity != null) {
6492 cls = new ComponentName(info.packageName, info.targetActivity);
6493 }
6494
6495 final int N = mHistory.size();
6496 for (int i=(N-1); i>=0; i--) {
6497 HistoryRecord r = (HistoryRecord)mHistory.get(i);
6498 if (!r.finishing) {
6499 if (r.intent.getComponent().equals(cls)) {
6500 //Log.i(TAG, "Found matching class!");
6501 //dump();
6502 //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
6503 return r;
6504 }
6505 }
6506 }
6507
6508 return null;
6509 }
6510
6511 public void finishOtherInstances(IBinder token, ComponentName className) {
6512 synchronized(this) {
6513 final long origId = Binder.clearCallingIdentity();
6514
6515 int N = mHistory.size();
6516 TaskRecord lastTask = null;
6517 for (int i=0; i<N; i++) {
6518 HistoryRecord r = (HistoryRecord)mHistory.get(i);
6519 if (r.realActivity.equals(className)
6520 && r != token && lastTask != r.task) {
6521 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
6522 null, "others")) {
6523 i--;
6524 N--;
6525 }
6526 }
6527 lastTask = r.task;
6528 }
6529
6530 Binder.restoreCallingIdentity(origId);
6531 }
6532 }
6533
6534 // =========================================================
6535 // THUMBNAILS
6536 // =========================================================
6537
6538 public void reportThumbnail(IBinder token,
6539 Bitmap thumbnail, CharSequence description) {
6540 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
6541 final long origId = Binder.clearCallingIdentity();
6542 sendPendingThumbnail(null, token, thumbnail, description, true);
6543 Binder.restoreCallingIdentity(origId);
6544 }
6545
6546 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
6547 Bitmap thumbnail, CharSequence description, boolean always) {
6548 TaskRecord task = null;
6549 ArrayList receivers = null;
6550
6551 //System.out.println("Send pending thumbnail: " + r);
6552
6553 synchronized(this) {
6554 if (r == null) {
6555 int index = indexOfTokenLocked(token, false);
6556 if (index < 0) {
6557 return;
6558 }
6559 r = (HistoryRecord)mHistory.get(index);
6560 }
6561 if (thumbnail == null) {
6562 thumbnail = r.thumbnail;
6563 description = r.description;
6564 }
6565 if (thumbnail == null && !always) {
6566 // If there is no thumbnail, and this entry is not actually
6567 // going away, then abort for now and pick up the next
6568 // thumbnail we get.
6569 return;
6570 }
6571 task = r.task;
6572
6573 int N = mPendingThumbnails.size();
6574 int i=0;
6575 while (i<N) {
6576 PendingThumbnailsRecord pr =
6577 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
6578 //System.out.println("Looking in " + pr.pendingRecords);
6579 if (pr.pendingRecords.remove(r)) {
6580 if (receivers == null) {
6581 receivers = new ArrayList();
6582 }
6583 receivers.add(pr);
6584 if (pr.pendingRecords.size() == 0) {
6585 pr.finished = true;
6586 mPendingThumbnails.remove(i);
6587 N--;
6588 continue;
6589 }
6590 }
6591 i++;
6592 }
6593 }
6594
6595 if (receivers != null) {
6596 final int N = receivers.size();
6597 for (int i=0; i<N; i++) {
6598 try {
6599 PendingThumbnailsRecord pr =
6600 (PendingThumbnailsRecord)receivers.get(i);
6601 pr.receiver.newThumbnail(
6602 task != null ? task.taskId : -1, thumbnail, description);
6603 if (pr.finished) {
6604 pr.receiver.finished();
6605 }
6606 } catch (Exception e) {
6607 Log.w(TAG, "Exception thrown when sending thumbnail", e);
6608 }
6609 }
6610 }
6611 }
6612
6613 // =========================================================
6614 // CONTENT PROVIDERS
6615 // =========================================================
6616
6617 private final List generateApplicationProvidersLocked(ProcessRecord app) {
6618 List providers = null;
6619 try {
6620 providers = ActivityThread.getPackageManager().
6621 queryContentProviders(app.processName, app.info.uid,
6622 PackageManager.GET_SHARED_LIBRARY_FILES
6623 | PackageManager.GET_URI_PERMISSION_PATTERNS);
6624 } catch (RemoteException ex) {
6625 }
6626 if (providers != null) {
6627 final int N = providers.size();
6628 for (int i=0; i<N; i++) {
6629 ProviderInfo cpi =
6630 (ProviderInfo)providers.get(i);
6631 ContentProviderRecord cpr =
6632 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
6633 if (cpr == null) {
6634 cpr = new ContentProviderRecord(cpi, app.info);
6635 mProvidersByClass.put(cpi.name, cpr);
6636 }
6637 app.pubProviders.put(cpi.name, cpr);
6638 app.addPackage(cpi.applicationInfo.packageName);
6639 }
6640 }
6641 return providers;
6642 }
6643
6644 private final String checkContentProviderPermissionLocked(
6645 ProviderInfo cpi, ProcessRecord r, int mode) {
6646 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
6647 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
6648 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
6649 cpi.exported ? -1 : cpi.applicationInfo.uid)
6650 == PackageManager.PERMISSION_GRANTED
6651 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
6652 return null;
6653 }
6654 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
6655 cpi.exported ? -1 : cpi.applicationInfo.uid)
6656 == PackageManager.PERMISSION_GRANTED) {
6657 return null;
6658 }
6659 String msg = "Permission Denial: opening provider " + cpi.name
6660 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
6661 + ", uid=" + callingUid + ") requires "
6662 + cpi.readPermission + " or " + cpi.writePermission;
6663 Log.w(TAG, msg);
6664 return msg;
6665 }
6666
6667 private final ContentProviderHolder getContentProviderImpl(
6668 IApplicationThread caller, String name) {
6669 ContentProviderRecord cpr;
6670 ProviderInfo cpi = null;
6671
6672 synchronized(this) {
6673 ProcessRecord r = null;
6674 if (caller != null) {
6675 r = getRecordForAppLocked(caller);
6676 if (r == null) {
6677 throw new SecurityException(
6678 "Unable to find app for caller " + caller
6679 + " (pid=" + Binder.getCallingPid()
6680 + ") when getting content provider " + name);
6681 }
6682 }
6683
6684 // First check if this content provider has been published...
6685 cpr = (ContentProviderRecord)mProvidersByName.get(name);
6686 if (cpr != null) {
6687 cpi = cpr.info;
6688 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
6689 return new ContentProviderHolder(cpi,
6690 cpi.readPermission != null
6691 ? cpi.readPermission : cpi.writePermission);
6692 }
6693
6694 if (r != null && cpr.canRunHere(r)) {
6695 // This provider has been published or is in the process
6696 // of being published... but it is also allowed to run
6697 // in the caller's process, so don't make a connection
6698 // and just let the caller instantiate its own instance.
6699 if (cpr.provider != null) {
6700 // don't give caller the provider object, it needs
6701 // to make its own.
6702 cpr = new ContentProviderRecord(cpr);
6703 }
6704 return cpr;
6705 }
6706
6707 final long origId = Binder.clearCallingIdentity();
6708
6709 // In this case the provider is a single instance, so we can
6710 // return it right away.
6711 if (r != null) {
6712 r.conProviders.add(cpr);
6713 cpr.clients.add(r);
6714 } else {
6715 cpr.externals++;
6716 }
6717
6718 if (cpr.app != null) {
6719 updateOomAdjLocked(cpr.app);
6720 }
6721
6722 Binder.restoreCallingIdentity(origId);
6723
6724 } else {
6725 try {
6726 cpi = ActivityThread.getPackageManager().
6727 resolveContentProvider(name, PackageManager.GET_URI_PERMISSION_PATTERNS);
6728 } catch (RemoteException ex) {
6729 }
6730 if (cpi == null) {
6731 return null;
6732 }
6733
6734 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
6735 return new ContentProviderHolder(cpi,
6736 cpi.readPermission != null
6737 ? cpi.readPermission : cpi.writePermission);
6738 }
6739
6740 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
6741 final boolean firstClass = cpr == null;
6742 if (firstClass) {
6743 try {
6744 ApplicationInfo ai =
6745 ActivityThread.getPackageManager().
6746 getApplicationInfo(
6747 cpi.applicationInfo.packageName,
6748 PackageManager.GET_SHARED_LIBRARY_FILES);
6749 if (ai == null) {
6750 Log.w(TAG, "No package info for content provider "
6751 + cpi.name);
6752 return null;
6753 }
6754 cpr = new ContentProviderRecord(cpi, ai);
6755 } catch (RemoteException ex) {
6756 // pm is in same process, this will never happen.
6757 }
6758 }
6759
6760 if (r != null && cpr.canRunHere(r)) {
6761 // If this is a multiprocess provider, then just return its
6762 // info and allow the caller to instantiate it. Only do
6763 // this if the provider is the same user as the caller's
6764 // process, or can run as root (so can be in any process).
6765 return cpr;
6766 }
6767
6768 if (false) {
6769 RuntimeException e = new RuntimeException("foo");
6770 //Log.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
6771 // + " pruid " + ai.uid + "): " + cpi.className, e);
6772 }
6773
6774 // This is single process, and our app is now connecting to it.
6775 // See if we are already in the process of launching this
6776 // provider.
6777 final int N = mLaunchingProviders.size();
6778 int i;
6779 for (i=0; i<N; i++) {
6780 if (mLaunchingProviders.get(i) == cpr) {
6781 break;
6782 }
6783 if (false) {
6784 final ContentProviderRecord rec =
6785 (ContentProviderRecord)mLaunchingProviders.get(i);
6786 if (rec.info.name.equals(cpr.info.name)) {
6787 cpr = rec;
6788 break;
6789 }
6790 }
6791 }
6792
6793 // If the provider is not already being launched, then get it
6794 // started.
6795 if (i >= N) {
6796 final long origId = Binder.clearCallingIdentity();
6797 ProcessRecord proc = startProcessLocked(cpi.processName,
6798 cpr.appInfo, false, 0, "content provider",
6799 new ComponentName(cpi.applicationInfo.packageName,
6800 cpi.name));
6801 if (proc == null) {
6802 Log.w(TAG, "Unable to launch app "
6803 + cpi.applicationInfo.packageName + "/"
6804 + cpi.applicationInfo.uid + " for provider "
6805 + name + ": process is bad");
6806 return null;
6807 }
6808 cpr.launchingApp = proc;
6809 mLaunchingProviders.add(cpr);
6810 Binder.restoreCallingIdentity(origId);
6811 }
6812
6813 // Make sure the provider is published (the same provider class
6814 // may be published under multiple names).
6815 if (firstClass) {
6816 mProvidersByClass.put(cpi.name, cpr);
6817 }
6818 mProvidersByName.put(name, cpr);
6819
6820 if (r != null) {
6821 r.conProviders.add(cpr);
6822 cpr.clients.add(r);
6823 } else {
6824 cpr.externals++;
6825 }
6826 }
6827 }
6828
6829 // Wait for the provider to be published...
6830 synchronized (cpr) {
6831 while (cpr.provider == null) {
6832 if (cpr.launchingApp == null) {
6833 Log.w(TAG, "Unable to launch app "
6834 + cpi.applicationInfo.packageName + "/"
6835 + cpi.applicationInfo.uid + " for provider "
6836 + name + ": launching app became null");
6837 EventLog.writeEvent(LOG_AM_PROVIDER_LOST_PROCESS,
6838 cpi.applicationInfo.packageName,
6839 cpi.applicationInfo.uid, name);
6840 return null;
6841 }
6842 try {
6843 cpr.wait();
6844 } catch (InterruptedException ex) {
6845 }
6846 }
6847 }
6848 return cpr;
6849 }
6850
6851 public final ContentProviderHolder getContentProvider(
6852 IApplicationThread caller, String name) {
6853 if (caller == null) {
6854 String msg = "null IApplicationThread when getting content provider "
6855 + name;
6856 Log.w(TAG, msg);
6857 throw new SecurityException(msg);
6858 }
6859
6860 return getContentProviderImpl(caller, name);
6861 }
6862
6863 private ContentProviderHolder getContentProviderExternal(String name) {
6864 return getContentProviderImpl(null, name);
6865 }
6866
6867 /**
6868 * Drop a content provider from a ProcessRecord's bookkeeping
6869 * @param cpr
6870 */
6871 public void removeContentProvider(IApplicationThread caller, String name) {
6872 synchronized (this) {
6873 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
6874 if(cpr == null) {
6875 //remove from mProvidersByClass
6876 if(localLOGV) Log.v(TAG, name+" content provider not found in providers list");
6877 return;
6878 }
6879 final ProcessRecord r = getRecordForAppLocked(caller);
6880 if (r == null) {
6881 throw new SecurityException(
6882 "Unable to find app for caller " + caller +
6883 " when removing content provider " + name);
6884 }
6885 //update content provider record entry info
6886 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
6887 if(localLOGV) Log.v(TAG, "Removing content provider requested by "+
6888 r.info.processName+" from process "+localCpr.appInfo.processName);
6889 if(localCpr.appInfo.processName == r.info.processName) {
6890 //should not happen. taken care of as a local provider
6891 if(localLOGV) Log.v(TAG, "local provider doing nothing Ignoring other names");
6892 return;
6893 } else {
6894 localCpr.clients.remove(r);
6895 r.conProviders.remove(localCpr);
6896 }
6897 updateOomAdjLocked();
6898 }
6899 }
6900
6901 private void removeContentProviderExternal(String name) {
6902 synchronized (this) {
6903 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
6904 if(cpr == null) {
6905 //remove from mProvidersByClass
6906 if(localLOGV) Log.v(TAG, name+" content provider not found in providers list");
6907 return;
6908 }
6909
6910 //update content provider record entry info
6911 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
6912 localCpr.externals--;
6913 if (localCpr.externals < 0) {
6914 Log.e(TAG, "Externals < 0 for content provider " + localCpr);
6915 }
6916 updateOomAdjLocked();
6917 }
6918 }
6919
6920 public final void publishContentProviders(IApplicationThread caller,
6921 List<ContentProviderHolder> providers) {
6922 if (providers == null) {
6923 return;
6924 }
6925
6926 synchronized(this) {
6927 final ProcessRecord r = getRecordForAppLocked(caller);
6928 if (r == null) {
6929 throw new SecurityException(
6930 "Unable to find app for caller " + caller
6931 + " (pid=" + Binder.getCallingPid()
6932 + ") when publishing content providers");
6933 }
6934
6935 final long origId = Binder.clearCallingIdentity();
6936
6937 final int N = providers.size();
6938 for (int i=0; i<N; i++) {
6939 ContentProviderHolder src = providers.get(i);
6940 if (src == null || src.info == null || src.provider == null) {
6941 continue;
6942 }
6943 ContentProviderRecord dst =
6944 (ContentProviderRecord)r.pubProviders.get(src.info.name);
6945 if (dst != null) {
6946 mProvidersByClass.put(dst.info.name, dst);
6947 String names[] = dst.info.authority.split(";");
6948 for (int j = 0; j < names.length; j++) {
6949 mProvidersByName.put(names[j], dst);
6950 }
6951
6952 int NL = mLaunchingProviders.size();
6953 int j;
6954 for (j=0; j<NL; j++) {
6955 if (mLaunchingProviders.get(j) == dst) {
6956 mLaunchingProviders.remove(j);
6957 j--;
6958 NL--;
6959 }
6960 }
6961 synchronized (dst) {
6962 dst.provider = src.provider;
6963 dst.app = r;
6964 dst.notifyAll();
6965 }
6966 updateOomAdjLocked(r);
6967 }
6968 }
6969
6970 Binder.restoreCallingIdentity(origId);
6971 }
6972 }
6973
6974 public static final void installSystemProviders() {
6975 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
6976 List providers = mSelf.generateApplicationProvidersLocked(app);
6977 mSystemThread.installSystemProviders(providers);
6978 }
6979
6980 // =========================================================
6981 // GLOBAL MANAGEMENT
6982 // =========================================================
6983
6984 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
6985 ApplicationInfo info, String customProcess) {
6986 String proc = customProcess != null ? customProcess : info.processName;
6987 BatteryStatsImpl.Uid.Proc ps = null;
6988 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6989 synchronized (stats) {
6990 ps = stats.getProcessStatsLocked(info.uid, proc);
6991 }
6992 return new ProcessRecord(ps, thread, info, proc);
6993 }
6994
6995 final ProcessRecord addAppLocked(ApplicationInfo info) {
6996 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
6997
6998 if (app == null) {
6999 app = newProcessRecordLocked(null, info, null);
7000 mProcessNames.put(info.processName, info.uid, app);
7001 updateLRUListLocked(app, true);
7002 }
7003
7004 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
7005 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
7006 app.persistent = true;
7007 app.maxAdj = CORE_SERVER_ADJ;
7008 }
7009 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
7010 mPersistentStartingProcesses.add(app);
7011 startProcessLocked(app, "added application", app.processName);
7012 }
7013
7014 return app;
7015 }
7016
7017 public void unhandledBack() {
7018 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
7019 "unhandledBack()");
7020
7021 synchronized(this) {
7022 int count = mHistory.size();
7023 if (Config.LOGD) Log.d(
7024 TAG, "Performing unhandledBack(): stack size = " + count);
7025 if (count > 1) {
7026 final long origId = Binder.clearCallingIdentity();
7027 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
7028 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
7029 Binder.restoreCallingIdentity(origId);
7030 }
7031 }
7032 }
7033
7034 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
7035 String name = uri.getAuthority();
7036 ContentProviderHolder cph = getContentProviderExternal(name);
7037 ParcelFileDescriptor pfd = null;
7038 if (cph != null) {
7039 // We record the binder invoker's uid in thread-local storage before
7040 // going to the content provider to open the file. Later, in the code
7041 // that handles all permissions checks, we look for this uid and use
7042 // that rather than the Activity Manager's own uid. The effect is that
7043 // we do the check against the caller's permissions even though it looks
7044 // to the content provider like the Activity Manager itself is making
7045 // the request.
7046 sCallerIdentity.set(new Identity(
7047 Binder.getCallingPid(), Binder.getCallingUid()));
7048 try {
7049 pfd = cph.provider.openFile(uri, "r");
7050 } catch (FileNotFoundException e) {
7051 // do nothing; pfd will be returned null
7052 } finally {
7053 // Ensure that whatever happens, we clean up the identity state
7054 sCallerIdentity.remove();
7055 }
7056
7057 // We've got the fd now, so we're done with the provider.
7058 removeContentProviderExternal(name);
7059 } else {
7060 Log.d(TAG, "Failed to get provider for authority '" + name + "'");
7061 }
7062 return pfd;
7063 }
7064
7065 public void goingToSleep() {
7066 synchronized(this) {
7067 mSleeping = true;
7068 mWindowManager.setEventDispatching(false);
7069
7070 if (mResumedActivity != null) {
7071 pauseIfSleepingLocked();
7072 } else {
7073 Log.w(TAG, "goingToSleep with no resumed activity!");
7074 }
7075 }
7076 }
7077
7078 void pauseIfSleepingLocked() {
7079 if (mSleeping) {
7080 if (!mGoingToSleep.isHeld()) {
7081 mGoingToSleep.acquire();
7082 if (mLaunchingActivity.isHeld()) {
7083 mLaunchingActivity.release();
7084 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
7085 }
7086 }
7087
7088 // If we are not currently pausing an activity, get the current
7089 // one to pause. If we are pausing one, we will just let that stuff
7090 // run and release the wake lock when all done.
7091 if (mPausingActivity == null) {
7092 if (DEBUG_PAUSE) Log.v(TAG, "Sleep needs to pause...");
7093 if (DEBUG_USER_LEAVING) Log.v(TAG, "Sleep => pause with userLeaving=false");
7094 startPausingLocked(false, true);
7095 }
7096 }
7097 }
7098
7099 public void wakingUp() {
7100 synchronized(this) {
7101 if (mGoingToSleep.isHeld()) {
7102 mGoingToSleep.release();
7103 }
7104 mWindowManager.setEventDispatching(true);
7105 mSleeping = false;
7106 resumeTopActivityLocked(null);
7107 }
7108 }
7109
7110 public void setDebugApp(String packageName, boolean waitForDebugger,
7111 boolean persistent) {
7112 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
7113 "setDebugApp()");
7114
7115 // Note that this is not really thread safe if there are multiple
7116 // callers into it at the same time, but that's not a situation we
7117 // care about.
7118 if (persistent) {
7119 final ContentResolver resolver = mContext.getContentResolver();
7120 Settings.System.putString(
7121 resolver, Settings.System.DEBUG_APP,
7122 packageName);
7123 Settings.System.putInt(
7124 resolver, Settings.System.WAIT_FOR_DEBUGGER,
7125 waitForDebugger ? 1 : 0);
7126 }
7127
7128 synchronized (this) {
7129 if (!persistent) {
7130 mOrigDebugApp = mDebugApp;
7131 mOrigWaitForDebugger = mWaitForDebugger;
7132 }
7133 mDebugApp = packageName;
7134 mWaitForDebugger = waitForDebugger;
7135 mDebugTransient = !persistent;
7136 if (packageName != null) {
7137 final long origId = Binder.clearCallingIdentity();
7138 uninstallPackageLocked(packageName, -1, false);
7139 Binder.restoreCallingIdentity(origId);
7140 }
7141 }
7142 }
7143
7144 public void setAlwaysFinish(boolean enabled) {
7145 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
7146 "setAlwaysFinish()");
7147
7148 Settings.System.putInt(
7149 mContext.getContentResolver(),
7150 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
7151
7152 synchronized (this) {
7153 mAlwaysFinishActivities = enabled;
7154 }
7155 }
7156
7157 public void setActivityWatcher(IActivityWatcher watcher) {
7158 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
7159 "setActivityWatcher()");
7160 synchronized (this) {
7161 mWatcher = watcher;
7162 }
7163 }
7164
7165 public final void enterSafeMode() {
7166 synchronized(this) {
7167 // It only makes sense to do this before the system is ready
7168 // and started launching other packages.
7169 if (!mSystemReady) {
7170 try {
7171 ActivityThread.getPackageManager().enterSafeMode();
7172 } catch (RemoteException e) {
7173 }
7174
7175 View v = LayoutInflater.from(mContext).inflate(
7176 com.android.internal.R.layout.safe_mode, null);
7177 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
7178 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
7179 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
7180 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
7181 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
7182 lp.format = v.getBackground().getOpacity();
7183 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
7184 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
7185 ((WindowManager)mContext.getSystemService(
7186 Context.WINDOW_SERVICE)).addView(v, lp);
7187 }
7188 }
7189 }
7190
7191 public void noteWakeupAlarm(IIntentSender sender) {
7192 if (!(sender instanceof PendingIntentRecord)) {
7193 return;
7194 }
7195 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
7196 synchronized (stats) {
7197 if (mBatteryStatsService.isOnBattery()) {
7198 mBatteryStatsService.enforceCallingPermission();
7199 PendingIntentRecord rec = (PendingIntentRecord)sender;
7200 int MY_UID = Binder.getCallingUid();
7201 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
7202 BatteryStatsImpl.Uid.Pkg pkg =
7203 stats.getPackageStatsLocked(uid, rec.key.packageName);
7204 pkg.incWakeupsLocked();
7205 }
7206 }
7207 }
7208
7209 public boolean killPidsForMemory(int[] pids) {
7210 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
7211 throw new SecurityException("killPidsForMemory only available to the system");
7212 }
7213
7214 // XXX Note: don't acquire main activity lock here, because the window
7215 // manager calls in with its locks held.
7216
7217 boolean killed = false;
7218 synchronized (mPidsSelfLocked) {
7219 int[] types = new int[pids.length];
7220 int worstType = 0;
7221 for (int i=0; i<pids.length; i++) {
7222 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
7223 if (proc != null) {
7224 int type = proc.setAdj;
7225 types[i] = type;
7226 if (type > worstType) {
7227 worstType = type;
7228 }
7229 }
7230 }
7231
7232 // If the worse oom_adj is somewhere in the hidden proc LRU range,
7233 // then constrain it so we will kill all hidden procs.
7234 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
7235 worstType = HIDDEN_APP_MIN_ADJ;
7236 }
7237 Log.w(TAG, "Killing processes for memory at adjustment " + worstType);
7238 for (int i=0; i<pids.length; i++) {
7239 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
7240 if (proc == null) {
7241 continue;
7242 }
7243 int adj = proc.setAdj;
7244 if (adj >= worstType) {
7245 Log.w(TAG, "Killing for memory: " + proc + " (adj "
7246 + adj + ")");
7247 EventLog.writeEvent(LOG_AM_KILL_FOR_MEMORY, proc.pid,
7248 proc.processName, adj);
7249 killed = true;
7250 Process.killProcess(pids[i]);
7251 }
7252 }
7253 }
7254 return killed;
7255 }
7256
7257 public void reportPss(IApplicationThread caller, int pss) {
7258 Watchdog.PssRequestor req;
7259 String name;
7260 ProcessRecord callerApp;
7261 synchronized (this) {
7262 if (caller == null) {
7263 return;
7264 }
7265 callerApp = getRecordForAppLocked(caller);
7266 if (callerApp == null) {
7267 return;
7268 }
7269 callerApp.lastPss = pss;
7270 req = callerApp;
7271 name = callerApp.processName;
7272 }
7273 Watchdog.getInstance().reportPss(req, name, pss);
7274 if (!callerApp.persistent) {
7275 removeRequestedPss(callerApp);
7276 }
7277 }
7278
7279 public void requestPss(Runnable completeCallback) {
7280 ArrayList<ProcessRecord> procs;
7281 synchronized (this) {
7282 mRequestPssCallback = completeCallback;
7283 mRequestPssList.clear();
7284 for (int i=mLRUProcesses.size()-1; i>=0; i--) {
7285 ProcessRecord proc = mLRUProcesses.get(i);
7286 if (!proc.persistent) {
7287 mRequestPssList.add(proc);
7288 }
7289 }
7290 procs = new ArrayList<ProcessRecord>(mRequestPssList);
7291 }
7292
7293 int oldPri = Process.getThreadPriority(Process.myTid());
7294 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
7295 for (int i=procs.size()-1; i>=0; i--) {
7296 ProcessRecord proc = procs.get(i);
7297 proc.lastPss = 0;
7298 proc.requestPss();
7299 }
7300 Process.setThreadPriority(oldPri);
7301 }
7302
7303 void removeRequestedPss(ProcessRecord proc) {
7304 Runnable callback = null;
7305 synchronized (this) {
7306 if (mRequestPssList.remove(proc)) {
7307 if (mRequestPssList.size() == 0) {
7308 callback = mRequestPssCallback;
7309 mRequestPssCallback = null;
7310 }
7311 }
7312 }
7313
7314 if (callback != null) {
7315 callback.run();
7316 }
7317 }
7318
7319 public void collectPss(Watchdog.PssStats stats) {
7320 stats.mEmptyPss = 0;
7321 stats.mEmptyCount = 0;
7322 stats.mBackgroundPss = 0;
7323 stats.mBackgroundCount = 0;
7324 stats.mServicePss = 0;
7325 stats.mServiceCount = 0;
7326 stats.mVisiblePss = 0;
7327 stats.mVisibleCount = 0;
7328 stats.mForegroundPss = 0;
7329 stats.mForegroundCount = 0;
7330 stats.mNoPssCount = 0;
7331 synchronized (this) {
7332 int i;
7333 int NPD = mProcDeaths.length < stats.mProcDeaths.length
7334 ? mProcDeaths.length : stats.mProcDeaths.length;
7335 int aggr = 0;
7336 for (i=0; i<NPD; i++) {
7337 aggr += mProcDeaths[i];
7338 stats.mProcDeaths[i] = aggr;
7339 }
7340 while (i<stats.mProcDeaths.length) {
7341 stats.mProcDeaths[i] = 0;
7342 i++;
7343 }
7344
7345 for (i=mLRUProcesses.size()-1; i>=0; i--) {
7346 ProcessRecord proc = mLRUProcesses.get(i);
7347 if (proc.persistent) {
7348 continue;
7349 }
7350 //Log.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
7351 if (proc.lastPss == 0) {
7352 stats.mNoPssCount++;
7353 continue;
7354 }
7355 if (proc.setAdj == EMPTY_APP_ADJ) {
7356 stats.mEmptyPss += proc.lastPss;
7357 stats.mEmptyCount++;
7358 } else if (proc.setAdj == CONTENT_PROVIDER_ADJ) {
7359 stats.mEmptyPss += proc.lastPss;
7360 stats.mEmptyCount++;
7361 } else if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
7362 stats.mBackgroundPss += proc.lastPss;
7363 stats.mBackgroundCount++;
7364 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
7365 stats.mVisiblePss += proc.lastPss;
7366 stats.mVisibleCount++;
7367 } else {
7368 stats.mForegroundPss += proc.lastPss;
7369 stats.mForegroundCount++;
7370 }
7371 }
7372 }
7373 }
7374
7375 public final void startRunning(String pkg, String cls, String action,
7376 String data) {
7377 synchronized(this) {
7378 if (mStartRunning) {
7379 return;
7380 }
7381 mStartRunning = true;
7382 mTopComponent = pkg != null && cls != null
7383 ? new ComponentName(pkg, cls) : null;
7384 mTopAction = action != null ? action : Intent.ACTION_MAIN;
7385 mTopData = data;
7386 if (!mSystemReady) {
7387 return;
7388 }
7389 }
7390
7391 systemReady();
7392 }
7393
7394 private void retrieveSettings() {
7395 final ContentResolver resolver = mContext.getContentResolver();
7396 String debugApp = Settings.System.getString(
7397 resolver, Settings.System.DEBUG_APP);
7398 boolean waitForDebugger = Settings.System.getInt(
7399 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
7400 boolean alwaysFinishActivities = Settings.System.getInt(
7401 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
7402
7403 Configuration configuration = new Configuration();
7404 Settings.System.getConfiguration(resolver, configuration);
7405
7406 synchronized (this) {
7407 mDebugApp = mOrigDebugApp = debugApp;
7408 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
7409 mAlwaysFinishActivities = alwaysFinishActivities;
7410 // This happens before any activities are started, so we can
7411 // change mConfiguration in-place.
7412 mConfiguration.updateFrom(configuration);
7413 }
7414 }
7415
7416 public boolean testIsSystemReady() {
7417 // no need to synchronize(this) just to read & return the value
7418 return mSystemReady;
7419 }
7420
7421 public void systemReady() {
7422 // In the simulator, startRunning will never have been called, which
7423 // normally sets a few crucial variables. Do it here instead.
7424 if (!Process.supportsProcesses()) {
7425 mStartRunning = true;
7426 mTopAction = Intent.ACTION_MAIN;
7427 }
7428
7429 synchronized(this) {
7430 if (mSystemReady) {
7431 return;
7432 }
7433 mSystemReady = true;
7434 if (!mStartRunning) {
7435 return;
7436 }
7437 }
7438
7439 if (Config.LOGD) Log.d(TAG, "Start running!");
7440 EventLog.writeEvent(LOG_BOOT_PROGRESS_AMS_READY,
7441 SystemClock.uptimeMillis());
7442
7443 synchronized(this) {
7444 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
7445 ResolveInfo ri = mContext.getPackageManager()
7446 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
7447 0);
7448 CharSequence errorMsg = null;
7449 if (ri != null) {
7450 ActivityInfo ai = ri.activityInfo;
7451 ApplicationInfo app = ai.applicationInfo;
7452 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7453 mTopAction = Intent.ACTION_FACTORY_TEST;
7454 mTopData = null;
7455 mTopComponent = new ComponentName(app.packageName,
7456 ai.name);
7457 } else {
7458 errorMsg = mContext.getResources().getText(
7459 com.android.internal.R.string.factorytest_not_system);
7460 }
7461 } else {
7462 errorMsg = mContext.getResources().getText(
7463 com.android.internal.R.string.factorytest_no_action);
7464 }
7465 if (errorMsg != null) {
7466 mTopAction = null;
7467 mTopData = null;
7468 mTopComponent = null;
7469 Message msg = Message.obtain();
7470 msg.what = SHOW_FACTORY_ERROR_MSG;
7471 msg.getData().putCharSequence("msg", errorMsg);
7472 mHandler.sendMessage(msg);
7473 }
7474 }
7475 }
7476
7477 retrieveSettings();
7478
7479 synchronized (this) {
7480 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
7481 try {
7482 List apps = ActivityThread.getPackageManager().
7483 getPersistentApplications(PackageManager.GET_SHARED_LIBRARY_FILES);
7484 if (apps != null) {
7485 int N = apps.size();
7486 int i;
7487 for (i=0; i<N; i++) {
7488 ApplicationInfo info
7489 = (ApplicationInfo)apps.get(i);
7490 if (info != null &&
7491 !info.packageName.equals("android")) {
7492 addAppLocked(info);
7493 }
7494 }
7495 }
7496 } catch (RemoteException ex) {
7497 // pm is in same process, this will never happen.
7498 }
7499 }
7500
7501 try {
7502 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
7503 Message msg = Message.obtain();
7504 msg.what = SHOW_UID_ERROR_MSG;
7505 mHandler.sendMessage(msg);
7506 }
7507 } catch (RemoteException e) {
7508 }
7509
7510 // Start up initial activity.
7511 mBooting = true;
7512 resumeTopActivityLocked(null);
7513 }
7514 }
7515
7516 boolean makeAppCrashingLocked(ProcessRecord app,
7517 String tag, String shortMsg, String longMsg, byte[] crashData) {
7518 app.crashing = true;
7519 app.crashingReport = generateProcessError(app,
7520 ActivityManager.ProcessErrorStateInfo.CRASHED, tag, shortMsg, longMsg, crashData);
7521 startAppProblemLocked(app);
7522 app.stopFreezingAllLocked();
7523 return handleAppCrashLocked(app);
7524 }
7525
7526 void makeAppNotRespondingLocked(ProcessRecord app,
7527 String tag, String shortMsg, String longMsg, byte[] crashData) {
7528 app.notResponding = true;
7529 app.notRespondingReport = generateProcessError(app,
7530 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING, tag, shortMsg, longMsg,
7531 crashData);
7532 startAppProblemLocked(app);
7533 app.stopFreezingAllLocked();
7534 }
7535
7536 /**
7537 * Generate a process error record, suitable for attachment to a ProcessRecord.
7538 *
7539 * @param app The ProcessRecord in which the error occurred.
7540 * @param condition Crashing, Application Not Responding, etc. Values are defined in
7541 * ActivityManager.AppErrorStateInfo
7542 * @param tag The tag that was passed into handleApplicationError(). Typically the classname.
7543 * @param shortMsg Short message describing the crash.
7544 * @param longMsg Long message describing the crash.
7545 * @param crashData Raw data passed into handleApplicationError(). Typically a stack trace.
7546 *
7547 * @return Returns a fully-formed AppErrorStateInfo record.
7548 */
7549 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
7550 int condition, String tag, String shortMsg, String longMsg, byte[] crashData) {
7551 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
7552
7553 report.condition = condition;
7554 report.processName = app.processName;
7555 report.pid = app.pid;
7556 report.uid = app.info.uid;
7557 report.tag = tag;
7558 report.shortMsg = shortMsg;
7559 report.longMsg = longMsg;
7560 report.crashData = crashData;
7561
7562 return report;
7563 }
7564
7565 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog,
7566 boolean crashed) {
7567 synchronized (this) {
7568 app.crashing = false;
7569 app.crashingReport = null;
7570 app.notResponding = false;
7571 app.notRespondingReport = null;
7572 if (app.anrDialog == fromDialog) {
7573 app.anrDialog = null;
7574 }
7575 if (app.waitDialog == fromDialog) {
7576 app.waitDialog = null;
7577 }
7578 if (app.pid > 0 && app.pid != MY_PID) {
7579 if (crashed) {
7580 handleAppCrashLocked(app);
7581 }
7582 Log.i(ActivityManagerService.TAG, "Killing process "
7583 + app.processName
7584 + " (pid=" + app.pid + ") at user's request");
7585 Process.killProcess(app.pid);
7586 }
7587
7588 }
7589 }
7590
7591 boolean handleAppCrashLocked(ProcessRecord app) {
7592 long now = SystemClock.uptimeMillis();
7593
7594 Long crashTime = mProcessCrashTimes.get(app.info.processName,
7595 app.info.uid);
7596 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
7597 // This process loses!
7598 Log.w(TAG, "Process " + app.info.processName
7599 + " has crashed too many times: killing!");
7600 EventLog.writeEvent(LOG_AM_PROCESS_CRASHED_TOO_MUCH,
7601 app.info.processName, app.info.uid);
7602 killServicesLocked(app, false);
7603 for (int i=mHistory.size()-1; i>=0; i--) {
7604 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7605 if (r.app == app) {
7606 if (Config.LOGD) Log.d(
7607 TAG, " Force finishing activity "
7608 + r.intent.getComponent().flattenToShortString());
7609 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
7610 }
7611 }
7612 if (!app.persistent) {
7613 // We don't want to start this process again until the user
7614 // explicitly does so... but for persistent process, we really
7615 // need to keep it running. If a persistent process is actually
7616 // repeatedly crashing, then badness for everyone.
7617 EventLog.writeEvent(LOG_AM_PROCESS_BAD, app.info.uid,
7618 app.info.processName);
7619 mBadProcesses.put(app.info.processName, app.info.uid, now);
7620 app.bad = true;
7621 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
7622 app.removed = true;
7623 removeProcessLocked(app, false);
7624 return false;
7625 }
7626 }
7627
7628 // Bump up the crash count of any services currently running in the proc.
7629 if (app.services.size() != 0) {
7630 // Any services running in the application need to be placed
7631 // back in the pending list.
7632 Iterator it = app.services.iterator();
7633 while (it.hasNext()) {
7634 ServiceRecord sr = (ServiceRecord)it.next();
7635 sr.crashCount++;
7636 }
7637 }
7638
7639 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
7640 return true;
7641 }
7642
7643 void startAppProblemLocked(ProcessRecord app) {
7644 skipCurrentReceiverLocked(app);
7645 }
7646
7647 void skipCurrentReceiverLocked(ProcessRecord app) {
7648 boolean reschedule = false;
7649 BroadcastRecord r = app.curReceiver;
7650 if (r != null) {
7651 // The current broadcast is waiting for this app's receiver
7652 // to be finished. Looks like that's not going to happen, so
7653 // let the broadcast continue.
7654 logBroadcastReceiverDiscard(r);
7655 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
7656 r.resultExtras, r.resultAbort, true);
7657 reschedule = true;
7658 }
7659 r = mPendingBroadcast;
7660 if (r != null && r.curApp == app) {
7661 if (DEBUG_BROADCAST) Log.v(TAG,
7662 "skip & discard pending app " + r);
7663 logBroadcastReceiverDiscard(r);
7664 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
7665 r.resultExtras, r.resultAbort, true);
7666 reschedule = true;
7667 }
7668 if (reschedule) {
7669 scheduleBroadcastsLocked();
7670 }
7671 }
7672
7673 public int handleApplicationError(IBinder app, int flags,
7674 String tag, String shortMsg, String longMsg, byte[] crashData) {
7675 AppErrorResult result = new AppErrorResult();
7676
7677 ProcessRecord r = null;
7678 synchronized (this) {
7679 if (app != null) {
7680 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7681 final int NA = apps.size();
7682 for (int ia=0; ia<NA; ia++) {
7683 ProcessRecord p = apps.valueAt(ia);
7684 if (p.thread != null && p.thread.asBinder() == app) {
7685 r = p;
7686 break;
7687 }
7688 }
7689 }
7690 }
7691
7692 if (r != null) {
7693 // The application has crashed. Send the SIGQUIT to the process so
7694 // that it can dump its state.
7695 Process.sendSignal(r.pid, Process.SIGNAL_QUIT);
7696 //Log.i(TAG, "Current system threads:");
7697 //Process.sendSignal(MY_PID, Process.SIGNAL_QUIT);
7698 }
7699
7700 if (mWatcher != null) {
7701 try {
7702 String name = r != null ? r.processName : null;
7703 int pid = r != null ? r.pid : Binder.getCallingPid();
7704 if (!mWatcher.appCrashed(name, pid,
7705 shortMsg, longMsg, crashData)) {
7706 Log.w(TAG, "Force-killing crashed app " + name
7707 + " at watcher's request");
7708 Process.killProcess(pid);
7709 return 0;
7710 }
7711 } catch (RemoteException e) {
7712 mWatcher = null;
7713 }
7714 }
7715
7716 final long origId = Binder.clearCallingIdentity();
7717
7718 // If this process is running instrumentation, finish it.
7719 if (r != null && r.instrumentationClass != null) {
7720 Log.w(TAG, "Error in app " + r.processName
7721 + " running instrumentation " + r.instrumentationClass + ":");
7722 if (shortMsg != null) Log.w(TAG, " " + shortMsg);
7723 if (longMsg != null) Log.w(TAG, " " + longMsg);
7724 Bundle info = new Bundle();
7725 info.putString("shortMsg", shortMsg);
7726 info.putString("longMsg", longMsg);
7727 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7728 Binder.restoreCallingIdentity(origId);
7729 return 0;
7730 }
7731
7732 if (r != null) {
7733 if (!makeAppCrashingLocked(r, tag, shortMsg, longMsg, crashData)) {
7734 return 0;
7735 }
7736 } else {
7737 Log.w(TAG, "Some application object " + app + " tag " + tag
7738 + " has crashed, but I don't know who it is.");
7739 Log.w(TAG, "ShortMsg:" + shortMsg);
7740 Log.w(TAG, "LongMsg:" + longMsg);
7741 Binder.restoreCallingIdentity(origId);
7742 return 0;
7743 }
7744
7745 Message msg = Message.obtain();
7746 msg.what = SHOW_ERROR_MSG;
7747 HashMap data = new HashMap();
7748 data.put("result", result);
7749 data.put("app", r);
7750 data.put("flags", flags);
7751 data.put("shortMsg", shortMsg);
7752 data.put("longMsg", longMsg);
7753 if (r != null && (r.info.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7754 // For system processes, submit crash data to the server.
7755 data.put("crashData", crashData);
7756 }
7757 msg.obj = data;
7758 mHandler.sendMessage(msg);
7759
7760 Binder.restoreCallingIdentity(origId);
7761 }
7762
7763 int res = result.get();
7764
7765 synchronized (this) {
7766 if (r != null) {
7767 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7768 SystemClock.uptimeMillis());
7769 }
7770 }
7771
7772 return res;
7773 }
7774
7775 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7776 // assume our apps are happy - lazy create the list
7777 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7778
7779 synchronized (this) {
7780
7781 // iterate across all processes
7782 final int N = mLRUProcesses.size();
7783 for (int i = 0; i < N; i++) {
7784 ProcessRecord app = mLRUProcesses.get(i);
7785 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7786 // This one's in trouble, so we'll generate a report for it
7787 // crashes are higher priority (in case there's a crash *and* an anr)
7788 ActivityManager.ProcessErrorStateInfo report = null;
7789 if (app.crashing) {
7790 report = app.crashingReport;
7791 } else if (app.notResponding) {
7792 report = app.notRespondingReport;
7793 }
7794
7795 if (report != null) {
7796 if (errList == null) {
7797 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7798 }
7799 errList.add(report);
7800 } else {
7801 Log.w(TAG, "Missing app error report, app = " + app.processName +
7802 " crashing = " + app.crashing +
7803 " notResponding = " + app.notResponding);
7804 }
7805 }
7806 }
7807 }
7808
7809 return errList;
7810 }
7811
7812 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7813 // Lazy instantiation of list
7814 List<ActivityManager.RunningAppProcessInfo> runList = null;
7815 synchronized (this) {
7816 // Iterate across all processes
7817 final int N = mLRUProcesses.size();
7818 for (int i = 0; i < N; i++) {
7819 ProcessRecord app = mLRUProcesses.get(i);
7820 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7821 // Generate process state info for running application
7822 ActivityManager.RunningAppProcessInfo currApp =
7823 new ActivityManager.RunningAppProcessInfo(app.processName,
7824 app.pid, app.getPackageList());
7825 int adj = app.curAdj;
7826 if (adj >= CONTENT_PROVIDER_ADJ) {
7827 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7828 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7829 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007830 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7831 } else if (adj >= HOME_APP_ADJ) {
7832 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7833 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007834 } else if (adj >= SECONDARY_SERVER_ADJ) {
7835 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
7836 } else if (adj >= VISIBLE_APP_ADJ) {
7837 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7838 } else {
7839 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7840 }
7841 //Log.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
7842 // + " lru=" + currApp.lru);
7843 if (runList == null) {
7844 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7845 }
7846 runList.add(currApp);
7847 }
7848 }
7849 }
7850 return runList;
7851 }
7852
7853 @Override
7854 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
7855 synchronized (this) {
7856 if (checkCallingPermission(android.Manifest.permission.DUMP)
7857 != PackageManager.PERMISSION_GRANTED) {
7858 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7859 + Binder.getCallingPid()
7860 + ", uid=" + Binder.getCallingUid()
7861 + " without permission "
7862 + android.Manifest.permission.DUMP);
7863 return;
7864 }
7865 if (args.length != 0 && "service".equals(args[0])) {
7866 dumpService(fd, pw, args);
7867 return;
7868 }
7869 pw.println("Activities in Current Activity Manager State:");
7870 dumpHistoryList(pw, mHistory, " ", "History");
7871 pw.println(" ");
7872 pw.println(" Running activities (most recent first):");
7873 dumpHistoryList(pw, mLRUActivities, " ", "Running");
7874 if (mWaitingVisibleActivities.size() > 0) {
7875 pw.println(" ");
7876 pw.println(" Activities waiting for another to become visible:");
7877 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Waiting");
7878 }
7879 if (mStoppingActivities.size() > 0) {
7880 pw.println(" ");
7881 pw.println(" Activities waiting to stop:");
7882 dumpHistoryList(pw, mStoppingActivities, " ", "Stopping");
7883 }
7884 if (mFinishingActivities.size() > 0) {
7885 pw.println(" ");
7886 pw.println(" Activities waiting to finish:");
7887 dumpHistoryList(pw, mFinishingActivities, " ", "Finishing");
7888 }
7889
7890 pw.println(" ");
7891 pw.println(" mPausingActivity: " + mPausingActivity);
7892 pw.println(" mResumedActivity: " + mResumedActivity);
7893 pw.println(" mFocusedActivity: " + mFocusedActivity);
7894 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
7895
7896 if (mRecentTasks.size() > 0) {
7897 pw.println(" ");
7898 pw.println("Recent tasks in Current Activity Manager State:");
7899
7900 final int N = mRecentTasks.size();
7901 for (int i=0; i<N; i++) {
7902 pw.println(" Recent Task #" + i);
7903 mRecentTasks.get(i).dump(pw, " ");
7904 }
7905 }
7906
7907 pw.println(" ");
7908 pw.println(" mCurTask: " + mCurTask);
7909
7910 pw.println(" ");
7911 pw.println("Processes in Current Activity Manager State:");
7912
7913 boolean needSep = false;
7914 int numPers = 0;
7915
7916 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7917 final int NA = procs.size();
7918 for (int ia=0; ia<NA; ia++) {
7919 if (!needSep) {
7920 pw.println(" All known processes:");
7921 needSep = true;
7922 }
7923 ProcessRecord r = procs.valueAt(ia);
7924 pw.println((r.persistent ? " *PERSISTENT* Process [" : " Process [")
7925 + r.processName + "] UID " + procs.keyAt(ia));
7926 r.dump(pw, " ");
7927 if (r.persistent) {
7928 numPers++;
7929 }
7930 }
7931 }
7932
7933 if (mLRUProcesses.size() > 0) {
7934 if (needSep) pw.println(" ");
7935 needSep = true;
7936 pw.println(" Running processes (most recent first):");
7937 dumpProcessList(pw, mLRUProcesses, " ",
7938 "Running Norm Proc", "Running PERS Proc", true);
7939 needSep = true;
7940 }
7941
7942 synchronized (mPidsSelfLocked) {
7943 if (mPidsSelfLocked.size() > 0) {
7944 if (needSep) pw.println(" ");
7945 needSep = true;
7946 pw.println(" PID mappings:");
7947 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7948 pw.println(" PID #" + mPidsSelfLocked.keyAt(i)
7949 + ": " + mPidsSelfLocked.valueAt(i));
7950 }
7951 }
7952 }
7953
7954 if (mForegroundProcesses.size() > 0) {
7955 if (needSep) pw.println(" ");
7956 needSep = true;
7957 pw.println(" Foreground Processes:");
7958 for (int i=0; i<mForegroundProcesses.size(); i++) {
7959 pw.println(" PID #" + mForegroundProcesses.keyAt(i)
7960 + ": " + mForegroundProcesses.valueAt(i));
7961 }
7962 }
7963
7964 if (mPersistentStartingProcesses.size() > 0) {
7965 if (needSep) pw.println(" ");
7966 needSep = true;
7967 pw.println(" Persisent processes that are starting:");
7968 dumpProcessList(pw, mPersistentStartingProcesses, " ",
7969 "Starting Initial Proc", "Restarting PERS Proc", false);
7970 }
7971
7972 if (mStartingProcesses.size() > 0) {
7973 if (needSep) pw.println(" ");
7974 needSep = true;
7975 pw.println(" Processes that are starting:");
7976 dumpProcessList(pw, mStartingProcesses, " ",
7977 "Starting Norm Proc", "Starting PERS Proc", false);
7978 }
7979
7980 if (mRemovedProcesses.size() > 0) {
7981 if (needSep) pw.println(" ");
7982 needSep = true;
7983 pw.println(" Processes that are being removed:");
7984 dumpProcessList(pw, mRemovedProcesses, " ",
7985 "Removed Norm Proc", "Removed PERS Proc", false);
7986 }
7987
7988 if (mProcessesOnHold.size() > 0) {
7989 if (needSep) pw.println(" ");
7990 needSep = true;
7991 pw.println(" Processes that are on old until the system is ready:");
7992 dumpProcessList(pw, mProcessesOnHold, " ",
7993 "OnHold Norm Proc", "OnHold PERS Proc", false);
7994 }
7995
7996 if (mProcessCrashTimes.getMap().size() > 0) {
7997 if (needSep) pw.println(" ");
7998 needSep = true;
7999 pw.println(" Time since processes crashed:");
8000 long now = SystemClock.uptimeMillis();
8001 for (Map.Entry<String, SparseArray<Long>> procs
8002 : mProcessCrashTimes.getMap().entrySet()) {
8003 SparseArray<Long> uids = procs.getValue();
8004 final int N = uids.size();
8005 for (int i=0; i<N; i++) {
8006 pw.println(" Process " + procs.getKey()
8007 + " uid " + uids.keyAt(i)
8008 + ": last crashed "
8009 + (now-uids.valueAt(i)) + " ms ago");
8010 }
8011 }
8012 }
8013
8014 if (mBadProcesses.getMap().size() > 0) {
8015 if (needSep) pw.println(" ");
8016 needSep = true;
8017 pw.println(" Bad processes:");
8018 for (Map.Entry<String, SparseArray<Long>> procs
8019 : mBadProcesses.getMap().entrySet()) {
8020 SparseArray<Long> uids = procs.getValue();
8021 final int N = uids.size();
8022 for (int i=0; i<N; i++) {
8023 pw.println(" Bad process " + procs.getKey()
8024 + " uid " + uids.keyAt(i)
8025 + ": crashed at time " + uids.valueAt(i));
8026 }
8027 }
8028 }
8029
8030 pw.println(" ");
8031 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project4df24232009-03-05 14:34:35 -08008032 pw.println(" mHomeProcess: " + mHomeProcess);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008033 pw.println(" mConfiguration: " + mConfiguration);
8034 pw.println(" mStartRunning=" + mStartRunning
8035 + " mSystemReady=" + mSystemReady
8036 + " mBooting=" + mBooting
8037 + " mBooted=" + mBooted
8038 + " mFactoryTest=" + mFactoryTest);
8039 pw.println(" mSleeping=" + mSleeping);
8040 pw.println(" mGoingToSleep=" + mGoingToSleep);
8041 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
8042 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
8043 + " mDebugTransient=" + mDebugTransient
8044 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
8045 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
8046 + " mWatcher=" + mWatcher);
8047 }
8048 }
8049
8050 /**
8051 * There are three ways to call this:
8052 * - no service specified: dump all the services
8053 * - a flattened component name that matched an existing service was specified as the
8054 * first arg: dump that one service
8055 * - the first arg isn't the flattened component name of an existing service:
8056 * dump all services whose component contains the first arg as a substring
8057 */
8058 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args) {
8059 String[] newArgs;
8060 String componentNameString;
8061 ServiceRecord r;
8062 if (args.length == 1) {
8063 componentNameString = null;
8064 newArgs = EMPTY_STRING_ARRAY;
8065 r = null;
8066 } else {
8067 componentNameString = args[1];
8068 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
8069 r = componentName != null ? mServices.get(componentName) : null;
8070 newArgs = new String[args.length - 2];
8071 if (args.length > 2) System.arraycopy(args, 2, newArgs, 0, args.length - 2);
8072 }
8073
8074 if (r != null) {
8075 dumpService(fd, pw, r, newArgs);
8076 } else {
8077 for (ServiceRecord r1 : mServices.values()) {
8078 if (componentNameString == null
8079 || r1.name.flattenToString().contains(componentNameString)) {
8080 dumpService(fd, pw, r1, newArgs);
8081 }
8082 }
8083 }
8084 }
8085
8086 /**
8087 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8088 * there is a thread associated with the service.
8089 */
8090 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
8091 pw.println(" Service " + r.name.flattenToString());
8092 if (r.app != null && r.app.thread != null) {
8093 try {
8094 // flush anything that is already in the PrintWriter since the thread is going
8095 // to write to the file descriptor directly
8096 pw.flush();
8097 r.app.thread.dumpService(fd, r, args);
8098 pw.print("\n");
8099 } catch (RemoteException e) {
8100 pw.println("got a RemoteException while dumping the service");
8101 }
8102 }
8103 }
8104
8105 void dumpBroadcasts(PrintWriter pw) {
8106 synchronized (this) {
8107 if (checkCallingPermission(android.Manifest.permission.DUMP)
8108 != PackageManager.PERMISSION_GRANTED) {
8109 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8110 + Binder.getCallingPid()
8111 + ", uid=" + Binder.getCallingUid()
8112 + " without permission "
8113 + android.Manifest.permission.DUMP);
8114 return;
8115 }
8116 pw.println("Broadcasts in Current Activity Manager State:");
8117
8118 if (mRegisteredReceivers.size() > 0) {
8119 pw.println(" ");
8120 pw.println(" Registered Receivers:");
8121 Iterator it = mRegisteredReceivers.values().iterator();
8122 while (it.hasNext()) {
8123 ReceiverList r = (ReceiverList)it.next();
8124 pw.println(" Receiver " + r.receiver);
8125 r.dump(pw, " ");
8126 }
8127 }
8128
8129 pw.println(" ");
8130 pw.println("Receiver Resolver Table:");
8131 mReceiverResolver.dump(new PrintWriterPrinter(pw), " ");
8132
8133 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8134 || mPendingBroadcast != null) {
8135 if (mParallelBroadcasts.size() > 0) {
8136 pw.println(" ");
8137 pw.println(" Active broadcasts:");
8138 }
8139 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8140 pw.println(" Broadcast #" + i + ":");
8141 mParallelBroadcasts.get(i).dump(pw, " ");
8142 }
8143 if (mOrderedBroadcasts.size() > 0) {
8144 pw.println(" ");
8145 pw.println(" Active serialized broadcasts:");
8146 }
8147 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8148 pw.println(" Serialized Broadcast #" + i + ":");
8149 mOrderedBroadcasts.get(i).dump(pw, " ");
8150 }
8151 pw.println(" ");
8152 pw.println(" Pending broadcast:");
8153 if (mPendingBroadcast != null) {
8154 mPendingBroadcast.dump(pw, " ");
8155 } else {
8156 pw.println(" (null)");
8157 }
8158 }
8159
8160 pw.println(" ");
8161 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
8162 if (mStickyBroadcasts != null) {
8163 pw.println(" ");
8164 pw.println(" Sticky broadcasts:");
8165 for (Map.Entry<String, ArrayList<Intent>> ent
8166 : mStickyBroadcasts.entrySet()) {
8167 pw.println(" Sticky action " + ent.getKey() + ":");
8168 ArrayList<Intent> intents = ent.getValue();
8169 final int N = intents.size();
8170 for (int i=0; i<N; i++) {
8171 pw.println(" " + intents.get(i));
8172 }
8173 }
8174 }
8175
8176 pw.println(" ");
8177 pw.println(" mHandler:");
8178 mHandler.dump(new PrintWriterPrinter(pw), " ");
8179 }
8180 }
8181
8182 void dumpServices(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("Services in Current Activity Manager State:");
8194
8195 boolean needSep = false;
8196
8197 if (mServices.size() > 0) {
8198 pw.println(" Active services:");
8199 Iterator<ServiceRecord> it = mServices.values().iterator();
8200 while (it.hasNext()) {
8201 ServiceRecord r = it.next();
8202 pw.println(" Service " + r.shortName);
8203 r.dump(pw, " ");
8204 }
8205 needSep = true;
8206 }
8207
8208 if (mPendingServices.size() > 0) {
8209 if (needSep) pw.println(" ");
8210 pw.println(" Pending services:");
8211 for (int i=0; i<mPendingServices.size(); i++) {
8212 ServiceRecord r = mPendingServices.get(i);
8213 pw.println(" Pending Service " + r.shortName);
8214 r.dump(pw, " ");
8215 }
8216 needSep = true;
8217 }
8218
8219 if (mRestartingServices.size() > 0) {
8220 if (needSep) pw.println(" ");
8221 pw.println(" Restarting services:");
8222 for (int i=0; i<mRestartingServices.size(); i++) {
8223 ServiceRecord r = mRestartingServices.get(i);
8224 pw.println(" Restarting Service " + r.shortName);
8225 r.dump(pw, " ");
8226 }
8227 needSep = true;
8228 }
8229
8230 if (mStoppingServices.size() > 0) {
8231 if (needSep) pw.println(" ");
8232 pw.println(" Stopping services:");
8233 for (int i=0; i<mStoppingServices.size(); i++) {
8234 ServiceRecord r = mStoppingServices.get(i);
8235 pw.println(" Stopping Service " + r.shortName);
8236 r.dump(pw, " ");
8237 }
8238 needSep = true;
8239 }
8240
8241 if (mServiceConnections.size() > 0) {
8242 if (needSep) pw.println(" ");
8243 pw.println(" Connection bindings to services:");
8244 Iterator<ConnectionRecord> it
8245 = mServiceConnections.values().iterator();
8246 while (it.hasNext()) {
8247 ConnectionRecord r = it.next();
8248 pw.println(" " + r.binding.service.shortName
8249 + " -> " + r.conn.asBinder());
8250 r.dump(pw, " ");
8251 }
8252 }
8253 }
8254 }
8255
8256 void dumpProviders(PrintWriter pw) {
8257 synchronized (this) {
8258 if (checkCallingPermission(android.Manifest.permission.DUMP)
8259 != PackageManager.PERMISSION_GRANTED) {
8260 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8261 + Binder.getCallingPid()
8262 + ", uid=" + Binder.getCallingUid()
8263 + " without permission "
8264 + android.Manifest.permission.DUMP);
8265 return;
8266 }
8267
8268 pw.println("Content Providers in Current Activity Manager State:");
8269
8270 boolean needSep = false;
8271
8272 if (mProvidersByName.size() > 0) {
8273 pw.println(" Published content providers (by name):");
8274 Iterator it = mProvidersByName.entrySet().iterator();
8275 while (it.hasNext()) {
8276 Map.Entry e = (Map.Entry)it.next();
8277 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
8278 pw.println(" Provider " + (String)e.getKey());
8279 r.dump(pw, " ");
8280 }
8281 needSep = true;
8282 }
8283
8284 if (mProvidersByClass.size() > 0) {
8285 if (needSep) pw.println(" ");
8286 pw.println(" Published content providers (by class):");
8287 Iterator it = mProvidersByClass.entrySet().iterator();
8288 while (it.hasNext()) {
8289 Map.Entry e = (Map.Entry)it.next();
8290 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
8291 pw.println(" Provider " + (String)e.getKey());
8292 r.dump(pw, " ");
8293 }
8294 needSep = true;
8295 }
8296
8297 if (mLaunchingProviders.size() > 0) {
8298 if (needSep) pw.println(" ");
8299 pw.println(" Launching content providers:");
8300 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8301 pw.println(" Provider #" + i + ":");
8302 ((ContentProviderRecord)mLaunchingProviders.get(i)).dump(pw, " ");
8303 }
8304 needSep = true;
8305 }
8306
8307 pw.println();
8308 pw.println("Granted Uri Permissions:");
8309 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8310 int uid = mGrantedUriPermissions.keyAt(i);
8311 HashMap<Uri, UriPermission> perms
8312 = mGrantedUriPermissions.valueAt(i);
8313 pw.println(" Uris granted to uid " + uid + ":");
8314 for (UriPermission perm : perms.values()) {
8315 perm.dump(pw, " ");
8316 }
8317 }
8318 }
8319 }
8320
8321 void dumpSenders(PrintWriter pw) {
8322 synchronized (this) {
8323 if (checkCallingPermission(android.Manifest.permission.DUMP)
8324 != PackageManager.PERMISSION_GRANTED) {
8325 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8326 + Binder.getCallingPid()
8327 + ", uid=" + Binder.getCallingUid()
8328 + " without permission "
8329 + android.Manifest.permission.DUMP);
8330 return;
8331 }
8332
8333 pw.println("Intent Senders in Current Activity Manager State:");
8334
8335 if (this.mIntentSenderRecords.size() > 0) {
8336 Iterator<WeakReference<PendingIntentRecord>> it
8337 = mIntentSenderRecords.values().iterator();
8338 while (it.hasNext()) {
8339 WeakReference<PendingIntentRecord> ref = it.next();
8340 PendingIntentRecord rec = ref != null ? ref.get(): null;
8341 if (rec != null) {
8342 pw.println(" IntentSender " + rec);
8343 rec.dump(pw, " ");
8344 } else {
8345 pw.println(" IntentSender " + ref);
8346 }
8347 }
8348 }
8349 }
8350 }
8351
8352 private static final void dumpHistoryList(PrintWriter pw, List list,
8353 String prefix, String label) {
8354 TaskRecord lastTask = null;
8355 for (int i=list.size()-1; i>=0; i--) {
8356 HistoryRecord r = (HistoryRecord)list.get(i);
8357 if (lastTask != r.task) {
8358 lastTask = r.task;
8359 lastTask.dump(pw, prefix + " ");
8360 }
8361 pw.println(prefix + " " + label + " #" + i + ":");
8362 r.dump(pw, prefix + " ");
8363 }
8364 }
8365
8366 private static final int dumpProcessList(PrintWriter pw, List list,
8367 String prefix, String normalLabel, String persistentLabel,
8368 boolean inclOomAdj) {
8369 int numPers = 0;
8370 for (int i=list.size()-1; i>=0; i--) {
8371 ProcessRecord r = (ProcessRecord)list.get(i);
8372 if (false) {
8373 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
8374 + " #" + i + ":");
8375 r.dump(pw, prefix + " ");
8376 } else if (inclOomAdj) {
8377 pw.println(String.format("%s%s #%2d: oom_adj=%3d %s",
8378 prefix, (r.persistent ? persistentLabel : normalLabel),
8379 i, r.setAdj, r.toString()));
8380 } else {
8381 pw.println(String.format("%s%s #%2d: %s",
8382 prefix, (r.persistent ? persistentLabel : normalLabel),
8383 i, r.toString()));
8384 }
8385 if (r.persistent) {
8386 numPers++;
8387 }
8388 }
8389 return numPers;
8390 }
8391
8392 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
8393 PrintWriter pw, List list, String prefix, String[] args) {
8394 final boolean isCheckinRequest = scanArgs(args, "-c");
8395 long uptime = SystemClock.uptimeMillis();
8396 long realtime = SystemClock.elapsedRealtime();
8397
8398 if (isCheckinRequest) {
8399 // short checkin version
8400 pw.println(uptime + "," + realtime);
8401 pw.flush();
8402 } else {
8403 pw.println("Applications Memory Usage (kB):");
8404 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8405 }
8406 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8407 ProcessRecord r = (ProcessRecord)list.get(i);
8408 if (r.thread != null) {
8409 if (!isCheckinRequest) {
8410 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8411 pw.flush();
8412 }
8413 try {
8414 r.thread.asBinder().dump(fd, args);
8415 } catch (RemoteException e) {
8416 if (!isCheckinRequest) {
8417 pw.println("Got RemoteException!");
8418 pw.flush();
8419 }
8420 }
8421 }
8422 }
8423 }
8424
8425 /**
8426 * Searches array of arguments for the specified string
8427 * @param args array of argument strings
8428 * @param value value to search for
8429 * @return true if the value is contained in the array
8430 */
8431 private static boolean scanArgs(String[] args, String value) {
8432 if (args != null) {
8433 for (String arg : args) {
8434 if (value.equals(arg)) {
8435 return true;
8436 }
8437 }
8438 }
8439 return false;
8440 }
8441
8442 private final int indexOfTokenLocked(IBinder token, boolean required) {
8443 int count = mHistory.size();
8444
8445 // convert the token to an entry in the history.
8446 HistoryRecord r = null;
8447 int index = -1;
8448 for (int i=count-1; i>=0; i--) {
8449 Object o = mHistory.get(i);
8450 if (o == token) {
8451 r = (HistoryRecord)o;
8452 index = i;
8453 break;
8454 }
8455 }
8456 if (index < 0 && required) {
8457 RuntimeInit.crash(TAG, new InvalidTokenException(token));
8458 }
8459
8460 return index;
8461 }
8462
8463 static class InvalidTokenException extends Exception {
8464 InvalidTokenException(IBinder token) {
8465 super("Bad activity token: " + token);
8466 }
8467 }
8468
8469 private final void killServicesLocked(ProcessRecord app,
8470 boolean allowRestart) {
8471 // Report disconnected services.
8472 if (false) {
8473 // XXX we are letting the client link to the service for
8474 // death notifications.
8475 if (app.services.size() > 0) {
8476 Iterator it = app.services.iterator();
8477 while (it.hasNext()) {
8478 ServiceRecord r = (ServiceRecord)it.next();
8479 if (r.connections.size() > 0) {
8480 Iterator<ConnectionRecord> jt
8481 = r.connections.values().iterator();
8482 while (jt.hasNext()) {
8483 ConnectionRecord c = jt.next();
8484 if (c.binding.client != app) {
8485 try {
8486 //c.conn.connected(r.className, null);
8487 } catch (Exception e) {
8488 // todo: this should be asynchronous!
8489 Log.w(TAG, "Exception thrown disconnected servce "
8490 + r.shortName
8491 + " from app " + app.processName, e);
8492 }
8493 }
8494 }
8495 }
8496 }
8497 }
8498 }
8499
8500 // Clean up any connections this application has to other services.
8501 if (app.connections.size() > 0) {
8502 Iterator<ConnectionRecord> it = app.connections.iterator();
8503 while (it.hasNext()) {
8504 ConnectionRecord r = it.next();
8505 removeConnectionLocked(r, app, null);
8506 }
8507 }
8508 app.connections.clear();
8509
8510 if (app.services.size() != 0) {
8511 // Any services running in the application need to be placed
8512 // back in the pending list.
8513 Iterator it = app.services.iterator();
8514 while (it.hasNext()) {
8515 ServiceRecord sr = (ServiceRecord)it.next();
8516 synchronized (sr.stats.getBatteryStats()) {
8517 sr.stats.stopLaunchedLocked();
8518 }
8519 sr.app = null;
8520 sr.executeNesting = 0;
8521 mStoppingServices.remove(sr);
8522 if (sr.bindings.size() > 0) {
8523 Iterator<IntentBindRecord> bindings
8524 = sr.bindings.values().iterator();
8525 while (bindings.hasNext()) {
8526 IntentBindRecord b = bindings.next();
8527 if (DEBUG_SERVICE) Log.v(TAG, "Killing binding " + b
8528 + ": shouldUnbind=" + b.hasBound);
8529 b.binder = null;
8530 b.requested = b.received = b.hasBound = false;
8531 }
8532 }
8533
8534 if (sr.crashCount >= 2) {
8535 Log.w(TAG, "Service crashed " + sr.crashCount
8536 + " times, stopping: " + sr);
8537 EventLog.writeEvent(LOG_AM_SERVICE_CRASHED_TOO_MUCH,
8538 sr.crashCount, sr.shortName, app.pid);
8539 bringDownServiceLocked(sr, true);
8540 } else if (!allowRestart) {
8541 bringDownServiceLocked(sr, true);
8542 } else {
8543 scheduleServiceRestartLocked(sr);
8544 }
8545 }
8546
8547 if (!allowRestart) {
8548 app.services.clear();
8549 }
8550 }
8551
8552 app.executingServices.clear();
8553 }
8554
8555 private final void removeDyingProviderLocked(ProcessRecord proc,
8556 ContentProviderRecord cpr) {
8557 synchronized (cpr) {
8558 cpr.launchingApp = null;
8559 cpr.notifyAll();
8560 }
8561
8562 mProvidersByClass.remove(cpr.info.name);
8563 String names[] = cpr.info.authority.split(";");
8564 for (int j = 0; j < names.length; j++) {
8565 mProvidersByName.remove(names[j]);
8566 }
8567
8568 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8569 while (cit.hasNext()) {
8570 ProcessRecord capp = cit.next();
8571 if (!capp.persistent && capp.thread != null
8572 && capp.pid != 0
8573 && capp.pid != MY_PID) {
8574 Log.i(TAG, "Killing app " + capp.processName
8575 + " (pid " + capp.pid
8576 + ") because provider " + cpr.info.name
8577 + " is in dying process " + proc.processName);
8578 Process.killProcess(capp.pid);
8579 }
8580 }
8581
8582 mLaunchingProviders.remove(cpr);
8583 }
8584
8585 /**
8586 * Main code for cleaning up a process when it has gone away. This is
8587 * called both as a result of the process dying, or directly when stopping
8588 * a process when running in single process mode.
8589 */
8590 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8591 boolean restarting, int index) {
8592 if (index >= 0) {
8593 mLRUProcesses.remove(index);
8594 }
8595
8596 // Dismiss any open dialogs.
8597 if (app.crashDialog != null) {
8598 app.crashDialog.dismiss();
8599 app.crashDialog = null;
8600 }
8601 if (app.anrDialog != null) {
8602 app.anrDialog.dismiss();
8603 app.anrDialog = null;
8604 }
8605 if (app.waitDialog != null) {
8606 app.waitDialog.dismiss();
8607 app.waitDialog = null;
8608 }
8609
8610 app.crashing = false;
8611 app.notResponding = false;
8612
8613 app.resetPackageList();
8614 app.thread = null;
8615 app.forcingToForeground = null;
8616 app.foregroundServices = false;
8617
8618 killServicesLocked(app, true);
8619
8620 boolean restart = false;
8621
8622 int NL = mLaunchingProviders.size();
8623
8624 // Remove published content providers.
8625 if (!app.pubProviders.isEmpty()) {
8626 Iterator it = app.pubProviders.values().iterator();
8627 while (it.hasNext()) {
8628 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8629 cpr.provider = null;
8630 cpr.app = null;
8631
8632 // See if someone is waiting for this provider... in which
8633 // case we don't remove it, but just let it restart.
8634 int i = 0;
8635 if (!app.bad) {
8636 for (; i<NL; i++) {
8637 if (mLaunchingProviders.get(i) == cpr) {
8638 restart = true;
8639 break;
8640 }
8641 }
8642 } else {
8643 i = NL;
8644 }
8645
8646 if (i >= NL) {
8647 removeDyingProviderLocked(app, cpr);
8648 NL = mLaunchingProviders.size();
8649 }
8650 }
8651 app.pubProviders.clear();
8652 }
8653
8654 // Look through the content providers we are waiting to have launched,
8655 // and if any run in this process then either schedule a restart of
8656 // the process or kill the client waiting for it if this process has
8657 // gone bad.
8658 for (int i=0; i<NL; i++) {
8659 ContentProviderRecord cpr = (ContentProviderRecord)
8660 mLaunchingProviders.get(i);
8661 if (cpr.launchingApp == app) {
8662 if (!app.bad) {
8663 restart = true;
8664 } else {
8665 removeDyingProviderLocked(app, cpr);
8666 NL = mLaunchingProviders.size();
8667 }
8668 }
8669 }
8670
8671 // Unregister from connected content providers.
8672 if (!app.conProviders.isEmpty()) {
8673 Iterator it = app.conProviders.iterator();
8674 while (it.hasNext()) {
8675 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8676 cpr.clients.remove(app);
8677 }
8678 app.conProviders.clear();
8679 }
8680
8681 skipCurrentReceiverLocked(app);
8682
8683 // Unregister any receivers.
8684 if (app.receivers.size() > 0) {
8685 Iterator<ReceiverList> it = app.receivers.iterator();
8686 while (it.hasNext()) {
8687 removeReceiverLocked(it.next());
8688 }
8689 app.receivers.clear();
8690 }
8691
8692 // If the caller is restarting this app, then leave it in its
8693 // current lists and let the caller take care of it.
8694 if (restarting) {
8695 return;
8696 }
8697
8698 if (!app.persistent) {
8699 if (DEBUG_PROCESSES) Log.v(TAG,
8700 "Removing non-persistent process during cleanup: " + app);
8701 mProcessNames.remove(app.processName, app.info.uid);
8702 } else if (!app.removed) {
8703 // This app is persistent, so we need to keep its record around.
8704 // If it is not already on the pending app list, add it there
8705 // and start a new process for it.
8706 app.thread = null;
8707 app.forcingToForeground = null;
8708 app.foregroundServices = false;
8709 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8710 mPersistentStartingProcesses.add(app);
8711 restart = true;
8712 }
8713 }
8714 mProcessesOnHold.remove(app);
8715
The Android Open Source Project4df24232009-03-05 14:34:35 -08008716 if (app == mHomeProcess) {
8717 mHomeProcess = null;
8718 }
8719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008720 if (restart) {
8721 // We have components that still need to be running in the
8722 // process, so re-launch it.
8723 mProcessNames.put(app.processName, app.info.uid, app);
8724 startProcessLocked(app, "restart", app.processName);
8725 } else if (app.pid > 0 && app.pid != MY_PID) {
8726 // Goodbye!
8727 synchronized (mPidsSelfLocked) {
8728 mPidsSelfLocked.remove(app.pid);
8729 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8730 }
8731 app.pid = 0;
8732 }
8733 }
8734
8735 // =========================================================
8736 // SERVICES
8737 // =========================================================
8738
8739 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8740 ActivityManager.RunningServiceInfo info =
8741 new ActivityManager.RunningServiceInfo();
8742 info.service = r.name;
8743 if (r.app != null) {
8744 info.pid = r.app.pid;
8745 }
8746 info.process = r.processName;
8747 info.foreground = r.isForeground;
8748 info.activeSince = r.createTime;
8749 info.started = r.startRequested;
8750 info.clientCount = r.connections.size();
8751 info.crashCount = r.crashCount;
8752 info.lastActivityTime = r.lastActivity;
8753 return info;
8754 }
8755
8756 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8757 int flags) {
8758 synchronized (this) {
8759 ArrayList<ActivityManager.RunningServiceInfo> res
8760 = new ArrayList<ActivityManager.RunningServiceInfo>();
8761
8762 if (mServices.size() > 0) {
8763 Iterator<ServiceRecord> it = mServices.values().iterator();
8764 while (it.hasNext() && res.size() < maxNum) {
8765 res.add(makeRunningServiceInfoLocked(it.next()));
8766 }
8767 }
8768
8769 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8770 ServiceRecord r = mRestartingServices.get(i);
8771 ActivityManager.RunningServiceInfo info =
8772 makeRunningServiceInfoLocked(r);
8773 info.restarting = r.nextRestartTime;
8774 res.add(info);
8775 }
8776
8777 return res;
8778 }
8779 }
8780
8781 private final ServiceRecord findServiceLocked(ComponentName name,
8782 IBinder token) {
8783 ServiceRecord r = mServices.get(name);
8784 return r == token ? r : null;
8785 }
8786
8787 private final class ServiceLookupResult {
8788 final ServiceRecord record;
8789 final String permission;
8790
8791 ServiceLookupResult(ServiceRecord _record, String _permission) {
8792 record = _record;
8793 permission = _permission;
8794 }
8795 };
8796
8797 private ServiceLookupResult findServiceLocked(Intent service,
8798 String resolvedType) {
8799 ServiceRecord r = null;
8800 if (service.getComponent() != null) {
8801 r = mServices.get(service.getComponent());
8802 }
8803 if (r == null) {
8804 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8805 r = mServicesByIntent.get(filter);
8806 }
8807
8808 if (r == null) {
8809 try {
8810 ResolveInfo rInfo =
8811 ActivityThread.getPackageManager().resolveService(
8812 service, resolvedType, 0);
8813 ServiceInfo sInfo =
8814 rInfo != null ? rInfo.serviceInfo : null;
8815 if (sInfo == null) {
8816 return null;
8817 }
8818
8819 ComponentName name = new ComponentName(
8820 sInfo.applicationInfo.packageName, sInfo.name);
8821 r = mServices.get(name);
8822 } catch (RemoteException ex) {
8823 // pm is in same process, this will never happen.
8824 }
8825 }
8826 if (r != null) {
8827 int callingPid = Binder.getCallingPid();
8828 int callingUid = Binder.getCallingUid();
8829 if (checkComponentPermission(r.permission,
8830 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8831 != PackageManager.PERMISSION_GRANTED) {
8832 Log.w(TAG, "Permission Denial: Accessing service " + r.name
8833 + " from pid=" + callingPid
8834 + ", uid=" + callingUid
8835 + " requires " + r.permission);
8836 return new ServiceLookupResult(null, r.permission);
8837 }
8838 return new ServiceLookupResult(r, null);
8839 }
8840 return null;
8841 }
8842
8843 private class ServiceRestarter implements Runnable {
8844 private ServiceRecord mService;
8845
8846 void setService(ServiceRecord service) {
8847 mService = service;
8848 }
8849
8850 public void run() {
8851 synchronized(ActivityManagerService.this) {
8852 performServiceRestartLocked(mService);
8853 }
8854 }
8855 }
8856
8857 private ServiceLookupResult retrieveServiceLocked(Intent service,
8858 String resolvedType, int callingPid, int callingUid) {
8859 ServiceRecord r = null;
8860 if (service.getComponent() != null) {
8861 r = mServices.get(service.getComponent());
8862 }
8863 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8864 r = mServicesByIntent.get(filter);
8865 if (r == null) {
8866 try {
8867 ResolveInfo rInfo =
8868 ActivityThread.getPackageManager().resolveService(
8869 service, resolvedType, PackageManager.GET_SHARED_LIBRARY_FILES);
8870 ServiceInfo sInfo =
8871 rInfo != null ? rInfo.serviceInfo : null;
8872 if (sInfo == null) {
8873 Log.w(TAG, "Unable to start service " + service +
8874 ": not found");
8875 return null;
8876 }
8877
8878 ComponentName name = new ComponentName(
8879 sInfo.applicationInfo.packageName, sInfo.name);
8880 r = mServices.get(name);
8881 if (r == null) {
8882 filter = new Intent.FilterComparison(service.cloneFilter());
8883 ServiceRestarter res = new ServiceRestarter();
8884 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8885 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8886 synchronized (stats) {
8887 ss = stats.getServiceStatsLocked(
8888 sInfo.applicationInfo.uid, sInfo.packageName,
8889 sInfo.name);
8890 }
8891 r = new ServiceRecord(ss, name, filter, sInfo, res);
8892 res.setService(r);
8893 mServices.put(name, r);
8894 mServicesByIntent.put(filter, r);
8895
8896 // Make sure this component isn't in the pending list.
8897 int N = mPendingServices.size();
8898 for (int i=0; i<N; i++) {
8899 ServiceRecord pr = mPendingServices.get(i);
8900 if (pr.name.equals(name)) {
8901 mPendingServices.remove(i);
8902 i--;
8903 N--;
8904 }
8905 }
8906 }
8907 } catch (RemoteException ex) {
8908 // pm is in same process, this will never happen.
8909 }
8910 }
8911 if (r != null) {
8912 if (checkComponentPermission(r.permission,
8913 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8914 != PackageManager.PERMISSION_GRANTED) {
8915 Log.w(TAG, "Permission Denial: Accessing service " + r.name
8916 + " from pid=" + Binder.getCallingPid()
8917 + ", uid=" + Binder.getCallingUid()
8918 + " requires " + r.permission);
8919 return new ServiceLookupResult(null, r.permission);
8920 }
8921 return new ServiceLookupResult(r, null);
8922 }
8923 return null;
8924 }
8925
8926 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8927 long now = SystemClock.uptimeMillis();
8928 if (r.executeNesting == 0 && r.app != null) {
8929 if (r.app.executingServices.size() == 0) {
8930 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8931 msg.obj = r.app;
8932 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8933 }
8934 r.app.executingServices.add(r);
8935 }
8936 r.executeNesting++;
8937 r.executingStart = now;
8938 }
8939
8940 private final void sendServiceArgsLocked(ServiceRecord r,
8941 boolean oomAdjusted) {
8942 final int N = r.startArgs.size();
8943 if (N == 0) {
8944 return;
8945 }
8946
8947 final int BASEID = r.lastStartId - N + 1;
8948 int i = 0;
8949 while (i < N) {
8950 try {
8951 Intent args = r.startArgs.get(i);
8952 if (DEBUG_SERVICE) Log.v(TAG, "Sending arguments to service: "
8953 + r.name + " " + r.intent + " args=" + args);
8954 bumpServiceExecutingLocked(r);
8955 if (!oomAdjusted) {
8956 oomAdjusted = true;
8957 updateOomAdjLocked(r.app);
8958 }
8959 r.app.thread.scheduleServiceArgs(r, BASEID+i, args);
8960 i++;
8961 } catch (Exception e) {
8962 break;
8963 }
8964 }
8965 if (i == N) {
8966 r.startArgs.clear();
8967 } else {
8968 while (i > 0) {
8969 r.startArgs.remove(0);
8970 i--;
8971 }
8972 }
8973 }
8974
8975 private final boolean requestServiceBindingLocked(ServiceRecord r,
8976 IntentBindRecord i, boolean rebind) {
8977 if (r.app == null || r.app.thread == null) {
8978 // If service is not currently running, can't yet bind.
8979 return false;
8980 }
8981 if ((!i.requested || rebind) && i.apps.size() > 0) {
8982 try {
8983 bumpServiceExecutingLocked(r);
8984 if (DEBUG_SERVICE) Log.v(TAG, "Connecting binding " + i
8985 + ": shouldUnbind=" + i.hasBound);
8986 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8987 if (!rebind) {
8988 i.requested = true;
8989 }
8990 i.hasBound = true;
8991 i.doRebind = false;
8992 } catch (RemoteException e) {
8993 return false;
8994 }
8995 }
8996 return true;
8997 }
8998
8999 private final void requestServiceBindingsLocked(ServiceRecord r) {
9000 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9001 while (bindings.hasNext()) {
9002 IntentBindRecord i = bindings.next();
9003 if (!requestServiceBindingLocked(r, i, false)) {
9004 break;
9005 }
9006 }
9007 }
9008
9009 private final void realStartServiceLocked(ServiceRecord r,
9010 ProcessRecord app) throws RemoteException {
9011 if (app.thread == null) {
9012 throw new RemoteException();
9013 }
9014
9015 r.app = app;
9016 r.restartTime = SystemClock.uptimeMillis();
9017
9018 app.services.add(r);
9019 bumpServiceExecutingLocked(r);
9020 updateLRUListLocked(app, true);
9021
9022 boolean created = false;
9023 try {
9024 if (DEBUG_SERVICE) Log.v(TAG, "Scheduling start service: "
9025 + r.name + " " + r.intent);
9026 EventLog.writeEvent(LOG_AM_CREATE_SERVICE,
9027 System.identityHashCode(r), r.shortName,
9028 r.intent.getIntent().toString(), r.app.pid);
9029 synchronized (r.stats.getBatteryStats()) {
9030 r.stats.startLaunchedLocked();
9031 }
9032 app.thread.scheduleCreateService(r, r.serviceInfo);
9033 created = true;
9034 } finally {
9035 if (!created) {
9036 app.services.remove(r);
9037 scheduleServiceRestartLocked(r);
9038 }
9039 }
9040
9041 requestServiceBindingsLocked(r);
9042 sendServiceArgsLocked(r, true);
9043 }
9044
9045 private final void scheduleServiceRestartLocked(ServiceRecord r) {
9046 r.totalRestartCount++;
9047 if (r.restartDelay == 0) {
9048 r.restartCount++;
9049 r.restartDelay = SERVICE_RESTART_DURATION;
9050 } else {
9051 // If it has been a "reasonably long time" since the service
9052 // was started, then reset our restart duration back to
9053 // the beginning, so we don't infinitely increase the duration
9054 // on a service that just occasionally gets killed (which is
9055 // a normal case, due to process being killed to reclaim memory).
9056 long now = SystemClock.uptimeMillis();
9057 if (now > (r.restartTime+(SERVICE_RESTART_DURATION*2*2*2))) {
9058 r.restartCount = 1;
9059 r.restartDelay = SERVICE_RESTART_DURATION;
9060 } else {
9061 r.restartDelay *= 2;
9062 }
9063 }
9064 if (!mRestartingServices.contains(r)) {
9065 mRestartingServices.add(r);
9066 }
9067 mHandler.removeCallbacks(r.restarter);
9068 mHandler.postDelayed(r.restarter, r.restartDelay);
9069 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
9070 Log.w(TAG, "Scheduling restart of crashed service "
9071 + r.shortName + " in " + r.restartDelay + "ms");
9072 EventLog.writeEvent(LOG_AM_SCHEDULE_SERVICE_RESTART,
9073 r.shortName, r.restartDelay);
9074
9075 Message msg = Message.obtain();
9076 msg.what = SERVICE_ERROR_MSG;
9077 msg.obj = r;
9078 mHandler.sendMessage(msg);
9079 }
9080
9081 final void performServiceRestartLocked(ServiceRecord r) {
9082 if (!mRestartingServices.contains(r)) {
9083 return;
9084 }
9085 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9086 }
9087
9088 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9089 if (r.restartDelay == 0) {
9090 return false;
9091 }
9092 r.resetRestartCounter();
9093 mRestartingServices.remove(r);
9094 mHandler.removeCallbacks(r.restarter);
9095 return true;
9096 }
9097
9098 private final boolean bringUpServiceLocked(ServiceRecord r,
9099 int intentFlags, boolean whileRestarting) {
9100 //Log.i(TAG, "Bring up service:");
9101 //r.dump(" ");
9102
9103 if (r.app != null) {
9104 sendServiceArgsLocked(r, false);
9105 return true;
9106 }
9107
9108 if (!whileRestarting && r.restartDelay > 0) {
9109 // If waiting for a restart, then do nothing.
9110 return true;
9111 }
9112
9113 if (DEBUG_SERVICE) Log.v(TAG, "Bringing up service " + r.name
9114 + " " + r.intent);
9115
9116 final String appName = r.processName;
9117 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9118 if (app != null && app.thread != null) {
9119 try {
9120 realStartServiceLocked(r, app);
9121 return true;
9122 } catch (RemoteException e) {
9123 Log.w(TAG, "Exception when starting service " + r.shortName, e);
9124 }
9125
9126 // If a dead object exception was thrown -- fall through to
9127 // restart the application.
9128 }
9129
9130 if (!mPendingServices.contains(r)) {
9131 // Not running -- get it started, and enqueue this service record
9132 // to be executed when the app comes up.
9133 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9134 "service", r.name) == null) {
9135 Log.w(TAG, "Unable to launch app "
9136 + r.appInfo.packageName + "/"
9137 + r.appInfo.uid + " for service "
9138 + r.intent.getIntent() + ": process is bad");
9139 bringDownServiceLocked(r, true);
9140 return false;
9141 }
9142 mPendingServices.add(r);
9143 }
9144 return true;
9145 }
9146
9147 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
9148 //Log.i(TAG, "Bring down service:");
9149 //r.dump(" ");
9150
9151 // Does it still need to run?
9152 if (!force && r.startRequested) {
9153 return;
9154 }
9155 if (r.connections.size() > 0) {
9156 if (!force) {
9157 // XXX should probably keep a count of the number of auto-create
9158 // connections directly in the service.
9159 Iterator<ConnectionRecord> it = r.connections.values().iterator();
9160 while (it.hasNext()) {
9161 ConnectionRecord cr = it.next();
9162 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
9163 return;
9164 }
9165 }
9166 }
9167
9168 // Report to all of the connections that the service is no longer
9169 // available.
9170 Iterator<ConnectionRecord> it = r.connections.values().iterator();
9171 while (it.hasNext()) {
9172 ConnectionRecord c = it.next();
9173 try {
9174 // todo: shouldn't be a synchronous call!
9175 c.conn.connected(r.name, null);
9176 } catch (Exception e) {
9177 Log.w(TAG, "Failure disconnecting service " + r.name +
9178 " to connection " + c.conn.asBinder() +
9179 " (in " + c.binding.client.processName + ")", e);
9180 }
9181 }
9182 }
9183
9184 // Tell the service that it has been unbound.
9185 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9186 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9187 while (it.hasNext()) {
9188 IntentBindRecord ibr = it.next();
9189 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down binding " + ibr
9190 + ": hasBound=" + ibr.hasBound);
9191 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9192 try {
9193 bumpServiceExecutingLocked(r);
9194 updateOomAdjLocked(r.app);
9195 ibr.hasBound = false;
9196 r.app.thread.scheduleUnbindService(r,
9197 ibr.intent.getIntent());
9198 } catch (Exception e) {
9199 Log.w(TAG, "Exception when unbinding service "
9200 + r.shortName, e);
9201 serviceDoneExecutingLocked(r, true);
9202 }
9203 }
9204 }
9205 }
9206
9207 if (DEBUG_SERVICE) Log.v(TAG, "Bringing down service " + r.name
9208 + " " + r.intent);
9209 EventLog.writeEvent(LOG_AM_DESTROY_SERVICE,
9210 System.identityHashCode(r), r.shortName,
9211 (r.app != null) ? r.app.pid : -1);
9212
9213 mServices.remove(r.name);
9214 mServicesByIntent.remove(r.intent);
9215 if (localLOGV) Log.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
9216 r.totalRestartCount = 0;
9217 unscheduleServiceRestartLocked(r);
9218
9219 // Also make sure it is not on the pending list.
9220 int N = mPendingServices.size();
9221 for (int i=0; i<N; i++) {
9222 if (mPendingServices.get(i) == r) {
9223 mPendingServices.remove(i);
9224 if (DEBUG_SERVICE) Log.v(
9225 TAG, "Removed pending service: " + r.shortName);
9226 i--;
9227 N--;
9228 }
9229 }
9230
9231 if (r.app != null) {
9232 synchronized (r.stats.getBatteryStats()) {
9233 r.stats.stopLaunchedLocked();
9234 }
9235 r.app.services.remove(r);
9236 if (r.app.thread != null) {
9237 updateServiceForegroundLocked(r.app, false);
9238 try {
9239 Log.i(TAG, "Stopping service: " + r.shortName);
9240 bumpServiceExecutingLocked(r);
9241 mStoppingServices.add(r);
9242 updateOomAdjLocked(r.app);
9243 r.app.thread.scheduleStopService(r);
9244 } catch (Exception e) {
9245 Log.w(TAG, "Exception when stopping service "
9246 + r.shortName, e);
9247 serviceDoneExecutingLocked(r, true);
9248 }
9249 } else {
9250 if (DEBUG_SERVICE) Log.v(
9251 TAG, "Removed service that has no process: " + r.shortName);
9252 }
9253 } else {
9254 if (DEBUG_SERVICE) Log.v(
9255 TAG, "Removed service that is not running: " + r.shortName);
9256 }
9257 }
9258
9259 ComponentName startServiceLocked(IApplicationThread caller,
9260 Intent service, String resolvedType,
9261 int callingPid, int callingUid) {
9262 synchronized(this) {
9263 if (DEBUG_SERVICE) Log.v(TAG, "startService: " + service
9264 + " type=" + resolvedType + " args=" + service.getExtras());
9265
9266 if (caller != null) {
9267 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9268 if (callerApp == null) {
9269 throw new SecurityException(
9270 "Unable to find app for caller " + caller
9271 + " (pid=" + Binder.getCallingPid()
9272 + ") when starting service " + service);
9273 }
9274 }
9275
9276 ServiceLookupResult res =
9277 retrieveServiceLocked(service, resolvedType,
9278 callingPid, callingUid);
9279 if (res == null) {
9280 return null;
9281 }
9282 if (res.record == null) {
9283 return new ComponentName("!", res.permission != null
9284 ? res.permission : "private to package");
9285 }
9286 ServiceRecord r = res.record;
9287 if (unscheduleServiceRestartLocked(r)) {
9288 if (DEBUG_SERVICE) Log.v(TAG, "START SERVICE WHILE RESTART PENDING: "
9289 + r.shortName);
9290 }
9291 r.startRequested = true;
9292 r.startArgs.add(service);
9293 r.lastStartId++;
9294 if (r.lastStartId < 1) {
9295 r.lastStartId = 1;
9296 }
9297 r.lastActivity = SystemClock.uptimeMillis();
9298 synchronized (r.stats.getBatteryStats()) {
9299 r.stats.startRunningLocked();
9300 }
9301 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9302 return new ComponentName("!", "Service process is bad");
9303 }
9304 return r.name;
9305 }
9306 }
9307
9308 public ComponentName startService(IApplicationThread caller, Intent service,
9309 String resolvedType) {
9310 // Refuse possible leaked file descriptors
9311 if (service != null && service.hasFileDescriptors() == true) {
9312 throw new IllegalArgumentException("File descriptors passed in Intent");
9313 }
9314
9315 synchronized(this) {
9316 final int callingPid = Binder.getCallingPid();
9317 final int callingUid = Binder.getCallingUid();
9318 final long origId = Binder.clearCallingIdentity();
9319 ComponentName res = startServiceLocked(caller, service,
9320 resolvedType, callingPid, callingUid);
9321 Binder.restoreCallingIdentity(origId);
9322 return res;
9323 }
9324 }
9325
9326 ComponentName startServiceInPackage(int uid,
9327 Intent service, String resolvedType) {
9328 synchronized(this) {
9329 final long origId = Binder.clearCallingIdentity();
9330 ComponentName res = startServiceLocked(null, service,
9331 resolvedType, -1, uid);
9332 Binder.restoreCallingIdentity(origId);
9333 return res;
9334 }
9335 }
9336
9337 public int stopService(IApplicationThread caller, Intent service,
9338 String resolvedType) {
9339 // Refuse possible leaked file descriptors
9340 if (service != null && service.hasFileDescriptors() == true) {
9341 throw new IllegalArgumentException("File descriptors passed in Intent");
9342 }
9343
9344 synchronized(this) {
9345 if (DEBUG_SERVICE) Log.v(TAG, "stopService: " + service
9346 + " type=" + resolvedType);
9347
9348 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9349 if (caller != null && callerApp == null) {
9350 throw new SecurityException(
9351 "Unable to find app for caller " + caller
9352 + " (pid=" + Binder.getCallingPid()
9353 + ") when stopping service " + service);
9354 }
9355
9356 // If this service is active, make sure it is stopped.
9357 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9358 if (r != null) {
9359 if (r.record != null) {
9360 synchronized (r.record.stats.getBatteryStats()) {
9361 r.record.stats.stopRunningLocked();
9362 }
9363 r.record.startRequested = false;
9364 final long origId = Binder.clearCallingIdentity();
9365 bringDownServiceLocked(r.record, false);
9366 Binder.restoreCallingIdentity(origId);
9367 return 1;
9368 }
9369 return -1;
9370 }
9371 }
9372
9373 return 0;
9374 }
9375
9376 public IBinder peekService(Intent service, String resolvedType) {
9377 // Refuse possible leaked file descriptors
9378 if (service != null && service.hasFileDescriptors() == true) {
9379 throw new IllegalArgumentException("File descriptors passed in Intent");
9380 }
9381
9382 IBinder ret = null;
9383
9384 synchronized(this) {
9385 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9386
9387 if (r != null) {
9388 // r.record is null if findServiceLocked() failed the caller permission check
9389 if (r.record == null) {
9390 throw new SecurityException(
9391 "Permission Denial: Accessing service " + r.record.name
9392 + " from pid=" + Binder.getCallingPid()
9393 + ", uid=" + Binder.getCallingUid()
9394 + " requires " + r.permission);
9395 }
9396 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9397 if (ib != null) {
9398 ret = ib.binder;
9399 }
9400 }
9401 }
9402
9403 return ret;
9404 }
9405
9406 public boolean stopServiceToken(ComponentName className, IBinder token,
9407 int startId) {
9408 synchronized(this) {
9409 if (DEBUG_SERVICE) Log.v(TAG, "stopServiceToken: " + className
9410 + " " + token + " startId=" + startId);
9411 ServiceRecord r = findServiceLocked(className, token);
9412 if (r != null && (startId < 0 || r.lastStartId == startId)) {
9413 synchronized (r.stats.getBatteryStats()) {
9414 r.stats.stopRunningLocked();
9415 r.startRequested = false;
9416 }
9417 final long origId = Binder.clearCallingIdentity();
9418 bringDownServiceLocked(r, false);
9419 Binder.restoreCallingIdentity(origId);
9420 return true;
9421 }
9422 }
9423 return false;
9424 }
9425
9426 public void setServiceForeground(ComponentName className, IBinder token,
9427 boolean isForeground) {
9428 synchronized(this) {
9429 ServiceRecord r = findServiceLocked(className, token);
9430 if (r != null) {
9431 if (r.isForeground != isForeground) {
9432 final long origId = Binder.clearCallingIdentity();
9433 r.isForeground = isForeground;
9434 if (r.app != null) {
9435 updateServiceForegroundLocked(r.app, true);
9436 }
9437 Binder.restoreCallingIdentity(origId);
9438 }
9439 }
9440 }
9441 }
9442
9443 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9444 boolean anyForeground = false;
9445 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
9446 if (sr.isForeground) {
9447 anyForeground = true;
9448 break;
9449 }
9450 }
9451 if (anyForeground != proc.foregroundServices) {
9452 proc.foregroundServices = anyForeground;
9453 if (oomAdj) {
9454 updateOomAdjLocked();
9455 }
9456 }
9457 }
9458
9459 public int bindService(IApplicationThread caller, IBinder token,
9460 Intent service, String resolvedType,
9461 IServiceConnection connection, int flags) {
9462 // Refuse possible leaked file descriptors
9463 if (service != null && service.hasFileDescriptors() == true) {
9464 throw new IllegalArgumentException("File descriptors passed in Intent");
9465 }
9466
9467 synchronized(this) {
9468 if (DEBUG_SERVICE) Log.v(TAG, "bindService: " + service
9469 + " type=" + resolvedType + " conn=" + connection.asBinder()
9470 + " flags=0x" + Integer.toHexString(flags));
9471 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9472 if (callerApp == null) {
9473 throw new SecurityException(
9474 "Unable to find app for caller " + caller
9475 + " (pid=" + Binder.getCallingPid()
9476 + ") when binding service " + service);
9477 }
9478
9479 HistoryRecord activity = null;
9480 if (token != null) {
9481 int aindex = indexOfTokenLocked(token, false);
9482 if (aindex < 0) {
9483 Log.w(TAG, "Binding with unknown activity: " + token);
9484 return 0;
9485 }
9486 activity = (HistoryRecord)mHistory.get(aindex);
9487 }
9488
9489 ServiceLookupResult res =
9490 retrieveServiceLocked(service, resolvedType,
9491 Binder.getCallingPid(), Binder.getCallingUid());
9492 if (res == null) {
9493 return 0;
9494 }
9495 if (res.record == null) {
9496 return -1;
9497 }
9498 ServiceRecord s = res.record;
9499
9500 final long origId = Binder.clearCallingIdentity();
9501
9502 if (unscheduleServiceRestartLocked(s)) {
9503 if (DEBUG_SERVICE) Log.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
9504 + s.shortName);
9505 }
9506
9507 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9508 ConnectionRecord c = new ConnectionRecord(b, activity,
9509 connection, flags);
9510
9511 IBinder binder = connection.asBinder();
9512 s.connections.put(binder, c);
9513 b.connections.add(c);
9514 if (activity != null) {
9515 if (activity.connections == null) {
9516 activity.connections = new HashSet<ConnectionRecord>();
9517 }
9518 activity.connections.add(c);
9519 }
9520 b.client.connections.add(c);
9521 mServiceConnections.put(binder, c);
9522
9523 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9524 s.lastActivity = SystemClock.uptimeMillis();
9525 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9526 return 0;
9527 }
9528 }
9529
9530 if (s.app != null) {
9531 // This could have made the service more important.
9532 updateOomAdjLocked(s.app);
9533 }
9534
9535 if (DEBUG_SERVICE) Log.v(TAG, "Bind " + s + " with " + b
9536 + ": received=" + b.intent.received
9537 + " apps=" + b.intent.apps.size()
9538 + " doRebind=" + b.intent.doRebind);
9539
9540 if (s.app != null && b.intent.received) {
9541 // Service is already running, so we can immediately
9542 // publish the connection.
9543 try {
9544 c.conn.connected(s.name, b.intent.binder);
9545 } catch (Exception e) {
9546 Log.w(TAG, "Failure sending service " + s.shortName
9547 + " to connection " + c.conn.asBinder()
9548 + " (in " + c.binding.client.processName + ")", e);
9549 }
9550
9551 // If this is the first app connected back to this binding,
9552 // and the service had previously asked to be told when
9553 // rebound, then do so.
9554 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9555 requestServiceBindingLocked(s, b.intent, true);
9556 }
9557 } else if (!b.intent.requested) {
9558 requestServiceBindingLocked(s, b.intent, false);
9559 }
9560
9561 Binder.restoreCallingIdentity(origId);
9562 }
9563
9564 return 1;
9565 }
9566
9567 private void removeConnectionLocked(
9568 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
9569 IBinder binder = c.conn.asBinder();
9570 AppBindRecord b = c.binding;
9571 ServiceRecord s = b.service;
9572 s.connections.remove(binder);
9573 b.connections.remove(c);
9574 if (c.activity != null && c.activity != skipAct) {
9575 if (c.activity.connections != null) {
9576 c.activity.connections.remove(c);
9577 }
9578 }
9579 if (b.client != skipApp) {
9580 b.client.connections.remove(c);
9581 }
9582 mServiceConnections.remove(binder);
9583
9584 if (b.connections.size() == 0) {
9585 b.intent.apps.remove(b.client);
9586 }
9587
9588 if (DEBUG_SERVICE) Log.v(TAG, "Disconnecting binding " + b.intent
9589 + ": shouldUnbind=" + b.intent.hasBound);
9590 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9591 && b.intent.hasBound) {
9592 try {
9593 bumpServiceExecutingLocked(s);
9594 updateOomAdjLocked(s.app);
9595 b.intent.hasBound = false;
9596 // Assume the client doesn't want to know about a rebind;
9597 // we will deal with that later if it asks for one.
9598 b.intent.doRebind = false;
9599 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9600 } catch (Exception e) {
9601 Log.w(TAG, "Exception when unbinding service " + s.shortName, e);
9602 serviceDoneExecutingLocked(s, true);
9603 }
9604 }
9605
9606 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9607 bringDownServiceLocked(s, false);
9608 }
9609 }
9610
9611 public boolean unbindService(IServiceConnection connection) {
9612 synchronized (this) {
9613 IBinder binder = connection.asBinder();
9614 if (DEBUG_SERVICE) Log.v(TAG, "unbindService: conn=" + binder);
9615 ConnectionRecord r = mServiceConnections.get(binder);
9616 if (r == null) {
9617 Log.w(TAG, "Unbind failed: could not find connection for "
9618 + connection.asBinder());
9619 return false;
9620 }
9621
9622 final long origId = Binder.clearCallingIdentity();
9623
9624 removeConnectionLocked(r, null, null);
9625
9626 if (r.binding.service.app != null) {
9627 // This could have made the service less important.
9628 updateOomAdjLocked(r.binding.service.app);
9629 }
9630
9631 Binder.restoreCallingIdentity(origId);
9632 }
9633
9634 return true;
9635 }
9636
9637 public void publishService(IBinder token, Intent intent, IBinder service) {
9638 // Refuse possible leaked file descriptors
9639 if (intent != null && intent.hasFileDescriptors() == true) {
9640 throw new IllegalArgumentException("File descriptors passed in Intent");
9641 }
9642
9643 synchronized(this) {
9644 if (!(token instanceof ServiceRecord)) {
9645 throw new IllegalArgumentException("Invalid service token");
9646 }
9647 ServiceRecord r = (ServiceRecord)token;
9648
9649 final long origId = Binder.clearCallingIdentity();
9650
9651 if (DEBUG_SERVICE) Log.v(TAG, "PUBLISHING SERVICE " + r.name
9652 + " " + intent + ": " + service);
9653 if (r != null) {
9654 Intent.FilterComparison filter
9655 = new Intent.FilterComparison(intent);
9656 IntentBindRecord b = r.bindings.get(filter);
9657 if (b != null && !b.received) {
9658 b.binder = service;
9659 b.requested = true;
9660 b.received = true;
9661 if (r.connections.size() > 0) {
9662 Iterator<ConnectionRecord> it
9663 = r.connections.values().iterator();
9664 while (it.hasNext()) {
9665 ConnectionRecord c = it.next();
9666 if (!filter.equals(c.binding.intent.intent)) {
9667 if (DEBUG_SERVICE) Log.v(
9668 TAG, "Not publishing to: " + c);
9669 if (DEBUG_SERVICE) Log.v(
9670 TAG, "Bound intent: " + c.binding.intent.intent);
9671 if (DEBUG_SERVICE) Log.v(
9672 TAG, "Published intent: " + intent);
9673 continue;
9674 }
9675 if (DEBUG_SERVICE) Log.v(TAG, "Publishing to: " + c);
9676 try {
9677 c.conn.connected(r.name, service);
9678 } catch (Exception e) {
9679 Log.w(TAG, "Failure sending service " + r.name +
9680 " to connection " + c.conn.asBinder() +
9681 " (in " + c.binding.client.processName + ")", e);
9682 }
9683 }
9684 }
9685 }
9686
9687 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9688
9689 Binder.restoreCallingIdentity(origId);
9690 }
9691 }
9692 }
9693
9694 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9695 // Refuse possible leaked file descriptors
9696 if (intent != null && intent.hasFileDescriptors() == true) {
9697 throw new IllegalArgumentException("File descriptors passed in Intent");
9698 }
9699
9700 synchronized(this) {
9701 if (!(token instanceof ServiceRecord)) {
9702 throw new IllegalArgumentException("Invalid service token");
9703 }
9704 ServiceRecord r = (ServiceRecord)token;
9705
9706 final long origId = Binder.clearCallingIdentity();
9707
9708 if (r != null) {
9709 Intent.FilterComparison filter
9710 = new Intent.FilterComparison(intent);
9711 IntentBindRecord b = r.bindings.get(filter);
9712 if (DEBUG_SERVICE) Log.v(TAG, "unbindFinished in " + r
9713 + " at " + b + ": apps="
9714 + (b != null ? b.apps.size() : 0));
9715 if (b != null) {
9716 if (b.apps.size() > 0) {
9717 // Applications have already bound since the last
9718 // unbind, so just rebind right here.
9719 requestServiceBindingLocked(r, b, true);
9720 } else {
9721 // Note to tell the service the next time there is
9722 // a new client.
9723 b.doRebind = true;
9724 }
9725 }
9726
9727 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9728
9729 Binder.restoreCallingIdentity(origId);
9730 }
9731 }
9732 }
9733
9734 public void serviceDoneExecuting(IBinder token) {
9735 synchronized(this) {
9736 if (!(token instanceof ServiceRecord)) {
9737 throw new IllegalArgumentException("Invalid service token");
9738 }
9739 ServiceRecord r = (ServiceRecord)token;
9740 boolean inStopping = mStoppingServices.contains(token);
9741 if (r != null) {
9742 if (DEBUG_SERVICE) Log.v(TAG, "DONE EXECUTING SERVICE " + r.name
9743 + ": nesting=" + r.executeNesting
9744 + ", inStopping=" + inStopping);
9745 if (r != token) {
9746 Log.w(TAG, "Done executing service " + r.name
9747 + " with incorrect token: given " + token
9748 + ", expected " + r);
9749 return;
9750 }
9751
9752 final long origId = Binder.clearCallingIdentity();
9753 serviceDoneExecutingLocked(r, inStopping);
9754 Binder.restoreCallingIdentity(origId);
9755 } else {
9756 Log.w(TAG, "Done executing unknown service " + r.name
9757 + " with token " + token);
9758 }
9759 }
9760 }
9761
9762 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
9763 r.executeNesting--;
9764 if (r.executeNesting <= 0 && r.app != null) {
9765 r.app.executingServices.remove(r);
9766 if (r.app.executingServices.size() == 0) {
9767 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9768 }
9769 if (inStopping) {
9770 mStoppingServices.remove(r);
9771 }
9772 updateOomAdjLocked(r.app);
9773 }
9774 }
9775
9776 void serviceTimeout(ProcessRecord proc) {
9777 synchronized(this) {
9778 if (proc.executingServices.size() == 0 || proc.thread == null) {
9779 return;
9780 }
9781 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9782 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9783 ServiceRecord timeout = null;
9784 long nextTime = 0;
9785 while (it.hasNext()) {
9786 ServiceRecord sr = it.next();
9787 if (sr.executingStart < maxTime) {
9788 timeout = sr;
9789 break;
9790 }
9791 if (sr.executingStart > nextTime) {
9792 nextTime = sr.executingStart;
9793 }
9794 }
9795 if (timeout != null && mLRUProcesses.contains(proc)) {
9796 Log.w(TAG, "Timeout executing service: " + timeout);
9797 appNotRespondingLocked(proc, null, "Executing service "
9798 + timeout.name);
9799 } else {
9800 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9801 msg.obj = proc;
9802 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9803 }
9804 }
9805 }
9806
9807 // =========================================================
9808 // BROADCASTS
9809 // =========================================================
9810
9811 private final List getStickies(String action, IntentFilter filter,
9812 List cur) {
9813 final ContentResolver resolver = mContext.getContentResolver();
9814 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9815 if (list == null) {
9816 return cur;
9817 }
9818 int N = list.size();
9819 for (int i=0; i<N; i++) {
9820 Intent intent = list.get(i);
9821 if (filter.match(resolver, intent, true, TAG) >= 0) {
9822 if (cur == null) {
9823 cur = new ArrayList<Intent>();
9824 }
9825 cur.add(intent);
9826 }
9827 }
9828 return cur;
9829 }
9830
9831 private final void scheduleBroadcastsLocked() {
9832 if (DEBUG_BROADCAST) Log.v(TAG, "Schedule broadcasts: current="
9833 + mBroadcastsScheduled);
9834
9835 if (mBroadcastsScheduled) {
9836 return;
9837 }
9838 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9839 mBroadcastsScheduled = true;
9840 }
9841
9842 public Intent registerReceiver(IApplicationThread caller,
9843 IIntentReceiver receiver, IntentFilter filter, String permission) {
9844 synchronized(this) {
9845 ProcessRecord callerApp = null;
9846 if (caller != null) {
9847 callerApp = getRecordForAppLocked(caller);
9848 if (callerApp == null) {
9849 throw new SecurityException(
9850 "Unable to find app for caller " + caller
9851 + " (pid=" + Binder.getCallingPid()
9852 + ") when registering receiver " + receiver);
9853 }
9854 }
9855
9856 List allSticky = null;
9857
9858 // Look for any matching sticky broadcasts...
9859 Iterator actions = filter.actionsIterator();
9860 if (actions != null) {
9861 while (actions.hasNext()) {
9862 String action = (String)actions.next();
9863 allSticky = getStickies(action, filter, allSticky);
9864 }
9865 } else {
9866 allSticky = getStickies(null, filter, allSticky);
9867 }
9868
9869 // The first sticky in the list is returned directly back to
9870 // the client.
9871 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9872
9873 if (DEBUG_BROADCAST) Log.v(TAG, "Register receiver " + filter
9874 + ": " + sticky);
9875
9876 if (receiver == null) {
9877 return sticky;
9878 }
9879
9880 ReceiverList rl
9881 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9882 if (rl == null) {
9883 rl = new ReceiverList(this, callerApp,
9884 Binder.getCallingPid(),
9885 Binder.getCallingUid(), receiver);
9886 if (rl.app != null) {
9887 rl.app.receivers.add(rl);
9888 } else {
9889 try {
9890 receiver.asBinder().linkToDeath(rl, 0);
9891 } catch (RemoteException e) {
9892 return sticky;
9893 }
9894 rl.linkedToDeath = true;
9895 }
9896 mRegisteredReceivers.put(receiver.asBinder(), rl);
9897 }
9898 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9899 rl.add(bf);
9900 if (!bf.debugCheck()) {
9901 Log.w(TAG, "==> For Dynamic broadast");
9902 }
9903 mReceiverResolver.addFilter(bf);
9904
9905 // Enqueue broadcasts for all existing stickies that match
9906 // this filter.
9907 if (allSticky != null) {
9908 ArrayList receivers = new ArrayList();
9909 receivers.add(bf);
9910
9911 int N = allSticky.size();
9912 for (int i=0; i<N; i++) {
9913 Intent intent = (Intent)allSticky.get(i);
9914 BroadcastRecord r = new BroadcastRecord(intent, null,
9915 null, -1, -1, null, receivers, null, 0, null, null,
9916 false);
9917 if (mParallelBroadcasts.size() == 0) {
9918 scheduleBroadcastsLocked();
9919 }
9920 mParallelBroadcasts.add(r);
9921 }
9922 }
9923
9924 return sticky;
9925 }
9926 }
9927
9928 public void unregisterReceiver(IIntentReceiver receiver) {
9929 if (DEBUG_BROADCAST) Log.v(TAG, "Unregister receiver: " + receiver);
9930
9931 boolean doNext = false;
9932
9933 synchronized(this) {
9934 ReceiverList rl
9935 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9936 if (rl != null) {
9937 if (rl.curBroadcast != null) {
9938 BroadcastRecord r = rl.curBroadcast;
9939 doNext = finishReceiverLocked(
9940 receiver.asBinder(), r.resultCode, r.resultData,
9941 r.resultExtras, r.resultAbort, true);
9942 }
9943
9944 if (rl.app != null) {
9945 rl.app.receivers.remove(rl);
9946 }
9947 removeReceiverLocked(rl);
9948 if (rl.linkedToDeath) {
9949 rl.linkedToDeath = false;
9950 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9951 }
9952 }
9953 }
9954
9955 if (!doNext) {
9956 return;
9957 }
9958
9959 final long origId = Binder.clearCallingIdentity();
9960 processNextBroadcast(false);
9961 trimApplications();
9962 Binder.restoreCallingIdentity(origId);
9963 }
9964
9965 void removeReceiverLocked(ReceiverList rl) {
9966 mRegisteredReceivers.remove(rl.receiver.asBinder());
9967 int N = rl.size();
9968 for (int i=0; i<N; i++) {
9969 mReceiverResolver.removeFilter(rl.get(i));
9970 }
9971 }
9972
9973 private final int broadcastIntentLocked(ProcessRecord callerApp,
9974 String callerPackage, Intent intent, String resolvedType,
9975 IIntentReceiver resultTo, int resultCode, String resultData,
9976 Bundle map, String requiredPermission,
9977 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9978 intent = new Intent(intent);
9979
9980 if (DEBUG_BROADCAST) Log.v(
9981 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9982 + " ordered=" + ordered);
9983 if ((resultTo != null) && !ordered) {
9984 Log.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
9985 }
9986
9987 // Handle special intents: if this broadcast is from the package
9988 // manager about a package being removed, we need to remove all of
9989 // its activities from the history stack.
9990 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9991 intent.getAction());
9992 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9993 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
9994 || uidRemoved) {
9995 if (checkComponentPermission(
9996 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9997 callingPid, callingUid, -1)
9998 == PackageManager.PERMISSION_GRANTED) {
9999 if (uidRemoved) {
10000 final Bundle intentExtras = intent.getExtras();
10001 final int uid = intentExtras != null
10002 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10003 if (uid >= 0) {
10004 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10005 synchronized (bs) {
10006 bs.removeUidStatsLocked(uid);
10007 }
10008 }
10009 } else {
10010 Uri data = intent.getData();
10011 String ssp;
10012 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10013 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10014 uninstallPackageLocked(ssp,
10015 intent.getIntExtra(Intent.EXTRA_UID, -1), false);
10016 }
10017 }
10018 }
10019 } else {
10020 String msg = "Permission Denial: " + intent.getAction()
10021 + " broadcast from " + callerPackage + " (pid=" + callingPid
10022 + ", uid=" + callingUid + ")"
10023 + " requires "
10024 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
10025 Log.w(TAG, msg);
10026 throw new SecurityException(msg);
10027 }
10028 }
10029
10030 /*
10031 * If this is the time zone changed action, queue up a message that will reset the timezone
10032 * of all currently running processes. This message will get queued up before the broadcast
10033 * happens.
10034 */
10035 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10036 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10037 }
10038
10039 // Add to the sticky list if requested.
10040 if (sticky) {
10041 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10042 callingPid, callingUid)
10043 != PackageManager.PERMISSION_GRANTED) {
10044 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10045 + callingPid + ", uid=" + callingUid
10046 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
10047 Log.w(TAG, msg);
10048 throw new SecurityException(msg);
10049 }
10050 if (requiredPermission != null) {
10051 Log.w(TAG, "Can't broadcast sticky intent " + intent
10052 + " and enforce permission " + requiredPermission);
10053 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10054 }
10055 if (intent.getComponent() != null) {
10056 throw new SecurityException(
10057 "Sticky broadcasts can't target a specific component");
10058 }
10059 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10060 if (list == null) {
10061 list = new ArrayList<Intent>();
10062 mStickyBroadcasts.put(intent.getAction(), list);
10063 }
10064 int N = list.size();
10065 int i;
10066 for (i=0; i<N; i++) {
10067 if (intent.filterEquals(list.get(i))) {
10068 // This sticky already exists, replace it.
10069 list.set(i, new Intent(intent));
10070 break;
10071 }
10072 }
10073 if (i >= N) {
10074 list.add(new Intent(intent));
10075 }
10076 }
10077
10078 final ContentResolver resolver = mContext.getContentResolver();
10079
10080 // Figure out who all will receive this broadcast.
10081 List receivers = null;
10082 List<BroadcastFilter> registeredReceivers = null;
10083 try {
10084 if (intent.getComponent() != null) {
10085 // Broadcast is going to one specific receiver class...
10086 ActivityInfo ai = ActivityThread.getPackageManager().
10087 getReceiverInfo(intent.getComponent(), 0);
10088 if (ai != null) {
10089 receivers = new ArrayList();
10090 ResolveInfo ri = new ResolveInfo();
10091 ri.activityInfo = ai;
10092 receivers.add(ri);
10093 }
10094 } else {
10095 // Need to resolve the intent to interested receivers...
10096 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10097 == 0) {
10098 receivers =
10099 ActivityThread.getPackageManager().queryIntentReceivers(
10100 intent, resolvedType, PackageManager.GET_SHARED_LIBRARY_FILES);
10101 }
10102 registeredReceivers = mReceiverResolver.queryIntent(resolver,
10103 intent, resolvedType, false);
10104 }
10105 } catch (RemoteException ex) {
10106 // pm is in same process, this will never happen.
10107 }
10108
10109 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10110 if (!ordered && NR > 0) {
10111 // If we are not serializing this broadcast, then send the
10112 // registered receivers separately so they don't wait for the
10113 // components to be launched.
10114 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10115 callerPackage, callingPid, callingUid, requiredPermission,
10116 registeredReceivers, resultTo, resultCode, resultData, map,
10117 ordered);
10118 if (DEBUG_BROADCAST) Log.v(
10119 TAG, "Enqueueing parallel broadcast " + r
10120 + ": prev had " + mParallelBroadcasts.size());
10121 mParallelBroadcasts.add(r);
10122 scheduleBroadcastsLocked();
10123 registeredReceivers = null;
10124 NR = 0;
10125 }
10126
10127 // Merge into one list.
10128 int ir = 0;
10129 if (receivers != null) {
10130 // A special case for PACKAGE_ADDED: do not allow the package
10131 // being added to see this broadcast. This prevents them from
10132 // using this as a back door to get run as soon as they are
10133 // installed. Maybe in the future we want to have a special install
10134 // broadcast or such for apps, but we'd like to deliberately make
10135 // this decision.
10136 String skipPackage = (intent.ACTION_PACKAGE_ADDED.equals(
10137 intent.getAction()) && intent.getData() != null)
10138 ? intent.getData().getSchemeSpecificPart()
10139 : null;
10140 if (skipPackage != null && receivers != null) {
10141 int NT = receivers.size();
10142 for (int it=0; it<NT; it++) {
10143 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10144 if (curt.activityInfo.packageName.equals(skipPackage)) {
10145 receivers.remove(it);
10146 it--;
10147 NT--;
10148 }
10149 }
10150 }
10151
10152 int NT = receivers != null ? receivers.size() : 0;
10153 int it = 0;
10154 ResolveInfo curt = null;
10155 BroadcastFilter curr = null;
10156 while (it < NT && ir < NR) {
10157 if (curt == null) {
10158 curt = (ResolveInfo)receivers.get(it);
10159 }
10160 if (curr == null) {
10161 curr = registeredReceivers.get(ir);
10162 }
10163 if (curr.getPriority() >= curt.priority) {
10164 // Insert this broadcast record into the final list.
10165 receivers.add(it, curr);
10166 ir++;
10167 curr = null;
10168 it++;
10169 NT++;
10170 } else {
10171 // Skip to the next ResolveInfo in the final list.
10172 it++;
10173 curt = null;
10174 }
10175 }
10176 }
10177 while (ir < NR) {
10178 if (receivers == null) {
10179 receivers = new ArrayList();
10180 }
10181 receivers.add(registeredReceivers.get(ir));
10182 ir++;
10183 }
10184
10185 if ((receivers != null && receivers.size() > 0)
10186 || resultTo != null) {
10187 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10188 callerPackage, callingPid, callingUid, requiredPermission,
10189 receivers, resultTo, resultCode, resultData, map, ordered);
10190 if (DEBUG_BROADCAST) Log.v(
10191 TAG, "Enqueueing ordered broadcast " + r
10192 + ": prev had " + mOrderedBroadcasts.size());
10193 if (DEBUG_BROADCAST) {
10194 int seq = r.intent.getIntExtra("seq", -1);
10195 Log.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
10196 }
10197 mOrderedBroadcasts.add(r);
10198 scheduleBroadcastsLocked();
10199 }
10200
10201 return BROADCAST_SUCCESS;
10202 }
10203
10204 public final int broadcastIntent(IApplicationThread caller,
10205 Intent intent, String resolvedType, IIntentReceiver resultTo,
10206 int resultCode, String resultData, Bundle map,
10207 String requiredPermission, boolean serialized, boolean sticky) {
10208 // Refuse possible leaked file descriptors
10209 if (intent != null && intent.hasFileDescriptors() == true) {
10210 throw new IllegalArgumentException("File descriptors passed in Intent");
10211 }
10212
10213 synchronized(this) {
10214 if (!mSystemReady) {
10215 // if the caller really truly claims to know what they're doing, go
10216 // ahead and allow the broadcast without launching any receivers
10217 int flags = intent.getFlags();
10218 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10219 intent = new Intent(intent);
10220 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10221 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
10222 Log.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10223 + " before boot completion");
10224 throw new IllegalStateException("Cannot broadcast before boot completed");
10225 }
10226 }
10227
10228 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10229 final int callingPid = Binder.getCallingPid();
10230 final int callingUid = Binder.getCallingUid();
10231 final long origId = Binder.clearCallingIdentity();
10232 int res = broadcastIntentLocked(callerApp,
10233 callerApp != null ? callerApp.info.packageName : null,
10234 intent, resolvedType, resultTo,
10235 resultCode, resultData, map, requiredPermission, serialized,
10236 sticky, callingPid, callingUid);
10237 Binder.restoreCallingIdentity(origId);
10238 return res;
10239 }
10240 }
10241
10242 int broadcastIntentInPackage(String packageName, int uid,
10243 Intent intent, String resolvedType, IIntentReceiver resultTo,
10244 int resultCode, String resultData, Bundle map,
10245 String requiredPermission, boolean serialized, boolean sticky) {
10246 synchronized(this) {
10247 final long origId = Binder.clearCallingIdentity();
10248 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10249 resultTo, resultCode, resultData, map, requiredPermission,
10250 serialized, sticky, -1, uid);
10251 Binder.restoreCallingIdentity(origId);
10252 return res;
10253 }
10254 }
10255
10256 public final void unbroadcastIntent(IApplicationThread caller,
10257 Intent intent) {
10258 // Refuse possible leaked file descriptors
10259 if (intent != null && intent.hasFileDescriptors() == true) {
10260 throw new IllegalArgumentException("File descriptors passed in Intent");
10261 }
10262
10263 synchronized(this) {
10264 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10265 != PackageManager.PERMISSION_GRANTED) {
10266 String msg = "Permission Denial: unbroadcastIntent() from pid="
10267 + Binder.getCallingPid()
10268 + ", uid=" + Binder.getCallingUid()
10269 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
10270 Log.w(TAG, msg);
10271 throw new SecurityException(msg);
10272 }
10273 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10274 if (list != null) {
10275 int N = list.size();
10276 int i;
10277 for (i=0; i<N; i++) {
10278 if (intent.filterEquals(list.get(i))) {
10279 list.remove(i);
10280 break;
10281 }
10282 }
10283 }
10284 }
10285 }
10286
10287 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10288 String resultData, Bundle resultExtras, boolean resultAbort,
10289 boolean explicit) {
10290 if (mOrderedBroadcasts.size() == 0) {
10291 if (explicit) {
10292 Log.w(TAG, "finishReceiver called but no pending broadcasts");
10293 }
10294 return false;
10295 }
10296 BroadcastRecord r = mOrderedBroadcasts.get(0);
10297 if (r.receiver == null) {
10298 if (explicit) {
10299 Log.w(TAG, "finishReceiver called but none active");
10300 }
10301 return false;
10302 }
10303 if (r.receiver != receiver) {
10304 Log.w(TAG, "finishReceiver called but active receiver is different");
10305 return false;
10306 }
10307 int state = r.state;
10308 r.state = r.IDLE;
10309 if (state == r.IDLE) {
10310 if (explicit) {
10311 Log.w(TAG, "finishReceiver called but state is IDLE");
10312 }
10313 }
10314 r.receiver = null;
10315 r.intent.setComponent(null);
10316 if (r.curApp != null) {
10317 r.curApp.curReceiver = null;
10318 }
10319 if (r.curFilter != null) {
10320 r.curFilter.receiverList.curBroadcast = null;
10321 }
10322 r.curFilter = null;
10323 r.curApp = null;
10324 r.curComponent = null;
10325 r.curReceiver = null;
10326 mPendingBroadcast = null;
10327
10328 r.resultCode = resultCode;
10329 r.resultData = resultData;
10330 r.resultExtras = resultExtras;
10331 r.resultAbort = resultAbort;
10332
10333 // We will process the next receiver right now if this is finishing
10334 // an app receiver (which is always asynchronous) or after we have
10335 // come back from calling a receiver.
10336 return state == BroadcastRecord.APP_RECEIVE
10337 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10338 }
10339
10340 public void finishReceiver(IBinder who, int resultCode, String resultData,
10341 Bundle resultExtras, boolean resultAbort) {
10342 if (DEBUG_BROADCAST) Log.v(TAG, "Finish receiver: " + who);
10343
10344 // Refuse possible leaked file descriptors
10345 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10346 throw new IllegalArgumentException("File descriptors passed in Bundle");
10347 }
10348
10349 boolean doNext;
10350
10351 final long origId = Binder.clearCallingIdentity();
10352
10353 synchronized(this) {
10354 doNext = finishReceiverLocked(
10355 who, resultCode, resultData, resultExtras, resultAbort, true);
10356 }
10357
10358 if (doNext) {
10359 processNextBroadcast(false);
10360 }
10361 trimApplications();
10362
10363 Binder.restoreCallingIdentity(origId);
10364 }
10365
10366 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10367 if (r.nextReceiver > 0) {
10368 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10369 if (curReceiver instanceof BroadcastFilter) {
10370 BroadcastFilter bf = (BroadcastFilter) curReceiver;
10371 EventLog.writeEvent(LOG_AM_BROADCAST_DISCARD_FILTER,
10372 System.identityHashCode(r),
10373 r.intent.getAction(),
10374 r.nextReceiver - 1,
10375 System.identityHashCode(bf));
10376 } else {
10377 EventLog.writeEvent(LOG_AM_BROADCAST_DISCARD_APP,
10378 System.identityHashCode(r),
10379 r.intent.getAction(),
10380 r.nextReceiver - 1,
10381 ((ResolveInfo)curReceiver).toString());
10382 }
10383 } else {
10384 Log.w(TAG, "Discarding broadcast before first receiver is invoked: "
10385 + r);
10386 EventLog.writeEvent(LOG_AM_BROADCAST_DISCARD_APP,
10387 System.identityHashCode(r),
10388 r.intent.getAction(),
10389 r.nextReceiver,
10390 "NONE");
10391 }
10392 }
10393
10394 private final void broadcastTimeout() {
10395 synchronized (this) {
10396 if (mOrderedBroadcasts.size() == 0) {
10397 return;
10398 }
10399 long now = SystemClock.uptimeMillis();
10400 BroadcastRecord r = mOrderedBroadcasts.get(0);
10401 if ((r.startTime+BROADCAST_TIMEOUT) > now) {
10402 if (DEBUG_BROADCAST) Log.v(TAG,
10403 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10404 + (r.startTime + BROADCAST_TIMEOUT));
10405 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10406 mHandler.sendMessageAtTime(msg, r.startTime+BROADCAST_TIMEOUT);
10407 return;
10408 }
10409
10410 Log.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
10411 r.startTime = now;
10412 r.anrCount++;
10413
10414 // Current receiver has passed its expiration date.
10415 if (r.nextReceiver <= 0) {
10416 Log.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10417 return;
10418 }
10419
10420 ProcessRecord app = null;
10421
10422 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10423 Log.w(TAG, "Receiver during timeout: " + curReceiver);
10424 logBroadcastReceiverDiscard(r);
10425 if (curReceiver instanceof BroadcastFilter) {
10426 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10427 if (bf.receiverList.pid != 0
10428 && bf.receiverList.pid != MY_PID) {
10429 synchronized (this.mPidsSelfLocked) {
10430 app = this.mPidsSelfLocked.get(
10431 bf.receiverList.pid);
10432 }
10433 }
10434 } else {
10435 app = r.curApp;
10436 }
10437
10438 if (app != null) {
10439 appNotRespondingLocked(app, null, "Broadcast of " + r.intent.toString());
10440 }
10441
10442 if (mPendingBroadcast == r) {
10443 mPendingBroadcast = null;
10444 }
10445
10446 // Move on to the next receiver.
10447 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10448 r.resultExtras, r.resultAbort, true);
10449 scheduleBroadcastsLocked();
10450 }
10451 }
10452
10453 private final void processCurBroadcastLocked(BroadcastRecord r,
10454 ProcessRecord app) throws RemoteException {
10455 if (app.thread == null) {
10456 throw new RemoteException();
10457 }
10458 r.receiver = app.thread.asBinder();
10459 r.curApp = app;
10460 app.curReceiver = r;
10461 updateLRUListLocked(app, true);
10462
10463 // Tell the application to launch this receiver.
10464 r.intent.setComponent(r.curComponent);
10465
10466 boolean started = false;
10467 try {
10468 if (DEBUG_BROADCAST) Log.v(TAG,
10469 "Delivering to component " + r.curComponent
10470 + ": " + r);
10471 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10472 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10473 started = true;
10474 } finally {
10475 if (!started) {
10476 r.receiver = null;
10477 r.curApp = null;
10478 app.curReceiver = null;
10479 }
10480 }
10481
10482 }
10483
10484 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
10485 Intent intent, int resultCode, String data,
10486 Bundle extras, boolean ordered) throws RemoteException {
10487 if (app != null && app.thread != null) {
10488 // If we have an app thread, do the call through that so it is
10489 // correctly ordered with other one-way calls.
10490 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
10491 data, extras, ordered);
10492 } else {
10493 receiver.performReceive(intent, resultCode, data, extras, ordered);
10494 }
10495 }
10496
10497 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10498 BroadcastFilter filter, boolean ordered) {
10499 boolean skip = false;
10500 if (filter.requiredPermission != null) {
10501 int perm = checkComponentPermission(filter.requiredPermission,
10502 r.callingPid, r.callingUid, -1);
10503 if (perm != PackageManager.PERMISSION_GRANTED) {
10504 Log.w(TAG, "Permission Denial: broadcasting "
10505 + r.intent.toString()
10506 + " from " + r.callerPackage + " (pid="
10507 + r.callingPid + ", uid=" + r.callingUid + ")"
10508 + " requires " + filter.requiredPermission
10509 + " due to registered receiver " + filter);
10510 skip = true;
10511 }
10512 }
10513 if (r.requiredPermission != null) {
10514 int perm = checkComponentPermission(r.requiredPermission,
10515 filter.receiverList.pid, filter.receiverList.uid, -1);
10516 if (perm != PackageManager.PERMISSION_GRANTED) {
10517 Log.w(TAG, "Permission Denial: receiving "
10518 + r.intent.toString()
10519 + " to " + filter.receiverList.app
10520 + " (pid=" + filter.receiverList.pid
10521 + ", uid=" + filter.receiverList.uid + ")"
10522 + " requires " + r.requiredPermission
10523 + " due to sender " + r.callerPackage
10524 + " (uid " + r.callingUid + ")");
10525 skip = true;
10526 }
10527 }
10528
10529 if (!skip) {
10530 // If this is not being sent as an ordered broadcast, then we
10531 // don't want to touch the fields that keep track of the current
10532 // state of ordered broadcasts.
10533 if (ordered) {
10534 r.receiver = filter.receiverList.receiver.asBinder();
10535 r.curFilter = filter;
10536 filter.receiverList.curBroadcast = r;
10537 r.state = BroadcastRecord.CALL_IN_RECEIVE;
10538 }
10539 try {
10540 if (DEBUG_BROADCAST) {
10541 int seq = r.intent.getIntExtra("seq", -1);
10542 Log.i(TAG, "Sending broadcast " + r.intent.getAction() + " seq=" + seq
10543 + " app=" + filter.receiverList.app);
10544 }
10545 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10546 new Intent(r.intent), r.resultCode,
10547 r.resultData, r.resultExtras, r.ordered);
10548 if (ordered) {
10549 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10550 }
10551 } catch (RemoteException e) {
10552 Log.w(TAG, "Failure sending broadcast " + r.intent, e);
10553 if (ordered) {
10554 r.receiver = null;
10555 r.curFilter = null;
10556 filter.receiverList.curBroadcast = null;
10557 }
10558 }
10559 }
10560 }
10561
10562 private final void processNextBroadcast(boolean fromMsg) {
10563 synchronized(this) {
10564 BroadcastRecord r;
10565
10566 if (DEBUG_BROADCAST) Log.v(TAG, "processNextBroadcast: "
10567 + mParallelBroadcasts.size() + " broadcasts, "
10568 + mOrderedBroadcasts.size() + " serialized broadcasts");
10569
10570 updateCpuStats();
10571
10572 if (fromMsg) {
10573 mBroadcastsScheduled = false;
10574 }
10575
10576 // First, deliver any non-serialized broadcasts right away.
10577 while (mParallelBroadcasts.size() > 0) {
10578 r = mParallelBroadcasts.remove(0);
10579 final int N = r.receivers.size();
10580 for (int i=0; i<N; i++) {
10581 Object target = r.receivers.get(i);
10582 if (DEBUG_BROADCAST) Log.v(TAG,
10583 "Delivering non-serialized to registered "
10584 + target + ": " + r);
10585 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10586 }
10587 }
10588
10589 // Now take care of the next serialized one...
10590
10591 // If we are waiting for a process to come up to handle the next
10592 // broadcast, then do nothing at this point. Just in case, we
10593 // check that the process we're waiting for still exists.
10594 if (mPendingBroadcast != null) {
10595 Log.i(TAG, "processNextBroadcast: waiting for "
10596 + mPendingBroadcast.curApp);
10597
10598 boolean isDead;
10599 synchronized (mPidsSelfLocked) {
10600 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10601 }
10602 if (!isDead) {
10603 // It's still alive, so keep waiting
10604 return;
10605 } else {
10606 Log.w(TAG, "pending app " + mPendingBroadcast.curApp
10607 + " died before responding to broadcast");
10608 mPendingBroadcast = null;
10609 }
10610 }
10611
10612 do {
10613 if (mOrderedBroadcasts.size() == 0) {
10614 // No more broadcasts pending, so all done!
10615 scheduleAppGcsLocked();
10616 return;
10617 }
10618 r = mOrderedBroadcasts.get(0);
10619 boolean forceReceive = false;
10620
10621 // Ensure that even if something goes awry with the timeout
10622 // detection, we catch "hung" broadcasts here, discard them,
10623 // and continue to make progress.
10624 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
10625 long now = SystemClock.uptimeMillis();
10626 if (r.dispatchTime > 0) {
10627 if ((numReceivers > 0) &&
10628 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
10629 Log.w(TAG, "Hung broadcast discarded after timeout failure:"
10630 + " now=" + now
10631 + " dispatchTime=" + r.dispatchTime
10632 + " startTime=" + r.startTime
10633 + " intent=" + r.intent
10634 + " numReceivers=" + numReceivers
10635 + " nextReceiver=" + r.nextReceiver
10636 + " state=" + r.state);
10637 broadcastTimeout(); // forcibly finish this broadcast
10638 forceReceive = true;
10639 r.state = BroadcastRecord.IDLE;
10640 }
10641 }
10642
10643 if (r.state != BroadcastRecord.IDLE) {
10644 if (DEBUG_BROADCAST) Log.d(TAG,
10645 "processNextBroadcast() called when not idle (state="
10646 + r.state + ")");
10647 return;
10648 }
10649
10650 if (r.receivers == null || r.nextReceiver >= numReceivers
10651 || r.resultAbort || forceReceive) {
10652 // No more receivers for this broadcast! Send the final
10653 // result if requested...
10654 if (r.resultTo != null) {
10655 try {
10656 if (DEBUG_BROADCAST) {
10657 int seq = r.intent.getIntExtra("seq", -1);
10658 Log.i(TAG, "Finishing broadcast " + r.intent.getAction()
10659 + " seq=" + seq + " app=" + r.callerApp);
10660 }
10661 performReceive(r.callerApp, r.resultTo,
10662 new Intent(r.intent), r.resultCode,
10663 r.resultData, r.resultExtras, false);
10664 } catch (RemoteException e) {
10665 Log.w(TAG, "Failure sending broadcast result of " + r.intent, e);
10666 }
10667 }
10668
10669 if (DEBUG_BROADCAST) Log.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
10670 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10671
10672 // ... and on to the next...
10673 mOrderedBroadcasts.remove(0);
10674 r = null;
10675 continue;
10676 }
10677 } while (r == null);
10678
10679 // Get the next receiver...
10680 int recIdx = r.nextReceiver++;
10681
10682 // Keep track of when this receiver started, and make sure there
10683 // is a timeout message pending to kill it if need be.
10684 r.startTime = SystemClock.uptimeMillis();
10685 if (recIdx == 0) {
10686 r.dispatchTime = r.startTime;
10687
10688 if (DEBUG_BROADCAST) Log.v(TAG,
10689 "Submitting BROADCAST_TIMEOUT_MSG for "
10690 + (r.startTime + BROADCAST_TIMEOUT));
10691 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10692 mHandler.sendMessageAtTime(msg, r.startTime+BROADCAST_TIMEOUT);
10693 }
10694
10695 Object nextReceiver = r.receivers.get(recIdx);
10696 if (nextReceiver instanceof BroadcastFilter) {
10697 // Simple case: this is a registered receiver who gets
10698 // a direct call.
10699 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
10700 if (DEBUG_BROADCAST) Log.v(TAG,
10701 "Delivering serialized to registered "
10702 + filter + ": " + r);
10703 deliverToRegisteredReceiver(r, filter, r.ordered);
10704 if (r.receiver == null || !r.ordered) {
10705 // The receiver has already finished, so schedule to
10706 // process the next one.
10707 r.state = BroadcastRecord.IDLE;
10708 scheduleBroadcastsLocked();
10709 }
10710 return;
10711 }
10712
10713 // Hard case: need to instantiate the receiver, possibly
10714 // starting its application process to host it.
10715
10716 ResolveInfo info =
10717 (ResolveInfo)nextReceiver;
10718
10719 boolean skip = false;
10720 int perm = checkComponentPermission(info.activityInfo.permission,
10721 r.callingPid, r.callingUid,
10722 info.activityInfo.exported
10723 ? -1 : info.activityInfo.applicationInfo.uid);
10724 if (perm != PackageManager.PERMISSION_GRANTED) {
10725 Log.w(TAG, "Permission Denial: broadcasting "
10726 + r.intent.toString()
10727 + " from " + r.callerPackage + " (pid=" + r.callingPid
10728 + ", uid=" + r.callingUid + ")"
10729 + " requires " + info.activityInfo.permission
10730 + " due to receiver " + info.activityInfo.packageName
10731 + "/" + info.activityInfo.name);
10732 skip = true;
10733 }
10734 if (r.callingUid != Process.SYSTEM_UID &&
10735 r.requiredPermission != null) {
10736 try {
10737 perm = ActivityThread.getPackageManager().
10738 checkPermission(r.requiredPermission,
10739 info.activityInfo.applicationInfo.packageName);
10740 } catch (RemoteException e) {
10741 perm = PackageManager.PERMISSION_DENIED;
10742 }
10743 if (perm != PackageManager.PERMISSION_GRANTED) {
10744 Log.w(TAG, "Permission Denial: receiving "
10745 + r.intent + " to "
10746 + info.activityInfo.applicationInfo.packageName
10747 + " requires " + r.requiredPermission
10748 + " due to sender " + r.callerPackage
10749 + " (uid " + r.callingUid + ")");
10750 skip = true;
10751 }
10752 }
10753 if (r.curApp != null && r.curApp.crashing) {
10754 // If the target process is crashing, just skip it.
10755 skip = true;
10756 }
10757
10758 if (skip) {
10759 r.receiver = null;
10760 r.curFilter = null;
10761 r.state = BroadcastRecord.IDLE;
10762 scheduleBroadcastsLocked();
10763 return;
10764 }
10765
10766 r.state = BroadcastRecord.APP_RECEIVE;
10767 String targetProcess = info.activityInfo.processName;
10768 r.curComponent = new ComponentName(
10769 info.activityInfo.applicationInfo.packageName,
10770 info.activityInfo.name);
10771 r.curReceiver = info.activityInfo;
10772
10773 // Is this receiver's application already running?
10774 ProcessRecord app = getProcessRecordLocked(targetProcess,
10775 info.activityInfo.applicationInfo.uid);
10776 if (app != null && app.thread != null) {
10777 try {
10778 processCurBroadcastLocked(r, app);
10779 return;
10780 } catch (RemoteException e) {
10781 Log.w(TAG, "Exception when sending broadcast to "
10782 + r.curComponent, e);
10783 }
10784
10785 // If a dead object exception was thrown -- fall through to
10786 // restart the application.
10787 }
10788
10789 // Not running -- get it started, and enqueue this history record
10790 // to be executed when the app comes up.
10791 if ((r.curApp=startProcessLocked(targetProcess,
10792 info.activityInfo.applicationInfo, true,
10793 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
10794 "broadcast", r.curComponent)) == null) {
10795 // Ah, this recipient is unavailable. Finish it if necessary,
10796 // and mark the broadcast record as ready for the next.
10797 Log.w(TAG, "Unable to launch app "
10798 + info.activityInfo.applicationInfo.packageName + "/"
10799 + info.activityInfo.applicationInfo.uid + " for broadcast "
10800 + r.intent + ": process is bad");
10801 logBroadcastReceiverDiscard(r);
10802 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10803 r.resultExtras, r.resultAbort, true);
10804 scheduleBroadcastsLocked();
10805 r.state = BroadcastRecord.IDLE;
10806 return;
10807 }
10808
10809 mPendingBroadcast = r;
10810 }
10811 }
10812
10813 // =========================================================
10814 // INSTRUMENTATION
10815 // =========================================================
10816
10817 public boolean startInstrumentation(ComponentName className,
10818 String profileFile, int flags, Bundle arguments,
10819 IInstrumentationWatcher watcher) {
10820 // Refuse possible leaked file descriptors
10821 if (arguments != null && arguments.hasFileDescriptors()) {
10822 throw new IllegalArgumentException("File descriptors passed in Bundle");
10823 }
10824
10825 synchronized(this) {
10826 InstrumentationInfo ii = null;
10827 ApplicationInfo ai = null;
10828 try {
10829 ii = mContext.getPackageManager().getInstrumentationInfo(
10830 className, 0);
10831 ai = mContext.getPackageManager().getApplicationInfo(
10832 ii.targetPackage, PackageManager.GET_SHARED_LIBRARY_FILES);
10833 } catch (PackageManager.NameNotFoundException e) {
10834 }
10835 if (ii == null) {
10836 reportStartInstrumentationFailure(watcher, className,
10837 "Unable to find instrumentation info for: " + className);
10838 return false;
10839 }
10840 if (ai == null) {
10841 reportStartInstrumentationFailure(watcher, className,
10842 "Unable to find instrumentation target package: " + ii.targetPackage);
10843 return false;
10844 }
10845
10846 int match = mContext.getPackageManager().checkSignatures(
10847 ii.targetPackage, ii.packageName);
10848 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10849 String msg = "Permission Denial: starting instrumentation "
10850 + className + " from pid="
10851 + Binder.getCallingPid()
10852 + ", uid=" + Binder.getCallingPid()
10853 + " not allowed because package " + ii.packageName
10854 + " does not have a signature matching the target "
10855 + ii.targetPackage;
10856 reportStartInstrumentationFailure(watcher, className, msg);
10857 throw new SecurityException(msg);
10858 }
10859
10860 final long origId = Binder.clearCallingIdentity();
10861 uninstallPackageLocked(ii.targetPackage, -1, true);
10862 ProcessRecord app = addAppLocked(ai);
10863 app.instrumentationClass = className;
10864 app.instrumentationProfileFile = profileFile;
10865 app.instrumentationArguments = arguments;
10866 app.instrumentationWatcher = watcher;
10867 app.instrumentationResultClass = className;
10868 Binder.restoreCallingIdentity(origId);
10869 }
10870
10871 return true;
10872 }
10873
10874 /**
10875 * Report errors that occur while attempting to start Instrumentation. Always writes the
10876 * error to the logs, but if somebody is watching, send the report there too. This enables
10877 * the "am" command to report errors with more information.
10878 *
10879 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10880 * @param cn The component name of the instrumentation.
10881 * @param report The error report.
10882 */
10883 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10884 ComponentName cn, String report) {
10885 Log.w(TAG, report);
10886 try {
10887 if (watcher != null) {
10888 Bundle results = new Bundle();
10889 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10890 results.putString("Error", report);
10891 watcher.instrumentationStatus(cn, -1, results);
10892 }
10893 } catch (RemoteException e) {
10894 Log.w(TAG, e);
10895 }
10896 }
10897
10898 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10899 if (app.instrumentationWatcher != null) {
10900 try {
10901 // NOTE: IInstrumentationWatcher *must* be oneway here
10902 app.instrumentationWatcher.instrumentationFinished(
10903 app.instrumentationClass,
10904 resultCode,
10905 results);
10906 } catch (RemoteException e) {
10907 }
10908 }
10909 app.instrumentationWatcher = null;
10910 app.instrumentationClass = null;
10911 app.instrumentationProfileFile = null;
10912 app.instrumentationArguments = null;
10913
10914 uninstallPackageLocked(app.processName, -1, false);
10915 }
10916
10917 public void finishInstrumentation(IApplicationThread target,
10918 int resultCode, Bundle results) {
10919 // Refuse possible leaked file descriptors
10920 if (results != null && results.hasFileDescriptors()) {
10921 throw new IllegalArgumentException("File descriptors passed in Intent");
10922 }
10923
10924 synchronized(this) {
10925 ProcessRecord app = getRecordForAppLocked(target);
10926 if (app == null) {
10927 Log.w(TAG, "finishInstrumentation: no app for " + target);
10928 return;
10929 }
10930 final long origId = Binder.clearCallingIdentity();
10931 finishInstrumentationLocked(app, resultCode, results);
10932 Binder.restoreCallingIdentity(origId);
10933 }
10934 }
10935
10936 // =========================================================
10937 // CONFIGURATION
10938 // =========================================================
10939
10940 public ConfigurationInfo getDeviceConfigurationInfo() {
10941 ConfigurationInfo config = new ConfigurationInfo();
10942 synchronized (this) {
10943 config.reqTouchScreen = mConfiguration.touchscreen;
10944 config.reqKeyboardType = mConfiguration.keyboard;
10945 config.reqNavigation = mConfiguration.navigation;
10946 if (mConfiguration.navigation != Configuration.NAVIGATION_NONAV) {
10947 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10948 }
10949 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED) {
10950 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10951 }
10952 }
10953 return config;
10954 }
10955
10956 public Configuration getConfiguration() {
10957 Configuration ci;
10958 synchronized(this) {
10959 ci = new Configuration(mConfiguration);
10960 }
10961 return ci;
10962 }
10963
10964 public void updateConfiguration(Configuration values) {
10965 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10966 "updateConfiguration()");
10967
10968 synchronized(this) {
10969 if (values == null && mWindowManager != null) {
10970 // sentinel: fetch the current configuration from the window manager
10971 values = mWindowManager.computeNewConfiguration();
10972 }
10973
10974 final long origId = Binder.clearCallingIdentity();
10975 updateConfigurationLocked(values, null);
10976 Binder.restoreCallingIdentity(origId);
10977 }
10978 }
10979
10980 /**
10981 * Do either or both things: (1) change the current configuration, and (2)
10982 * make sure the given activity is running with the (now) current
10983 * configuration. Returns true if the activity has been left running, or
10984 * false if <var>starting</var> is being destroyed to match the new
10985 * configuration.
10986 */
10987 public boolean updateConfigurationLocked(Configuration values,
10988 HistoryRecord starting) {
10989 int changes = 0;
10990
10991 boolean kept = true;
10992
10993 if (values != null) {
10994 Configuration newConfig = new Configuration(mConfiguration);
10995 changes = newConfig.updateFrom(values);
10996 if (changes != 0) {
10997 if (DEBUG_SWITCH) {
10998 Log.i(TAG, "Updating configuration to: " + values);
10999 }
11000
11001 EventLog.writeEvent(LOG_CONFIGURATION_CHANGED, changes);
11002
11003 if (values.locale != null) {
11004 saveLocaleLocked(values.locale,
11005 !values.locale.equals(mConfiguration.locale),
11006 values.userSetLocale);
11007 }
11008
11009 mConfiguration = newConfig;
11010
11011 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11012 msg.obj = new Configuration(mConfiguration);
11013 mHandler.sendMessage(msg);
11014
11015 final int N = mLRUProcesses.size();
11016 for (int i=0; i<N; i++) {
11017 ProcessRecord app = mLRUProcesses.get(i);
11018 try {
11019 if (app.thread != null) {
11020 app.thread.scheduleConfigurationChanged(mConfiguration);
11021 }
11022 } catch (Exception e) {
11023 }
11024 }
11025 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
11026 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11027 null, false, false, MY_PID, Process.SYSTEM_UID);
11028 }
11029 }
11030
11031 if (changes != 0 && starting == null) {
11032 // If the configuration changed, and the caller is not already
11033 // in the process of starting an activity, then find the top
11034 // activity to check if its configuration needs to change.
11035 starting = topRunningActivityLocked(null);
11036 }
11037
11038 if (starting != null) {
11039 kept = ensureActivityConfigurationLocked(starting, changes);
11040 if (kept) {
11041 // If this didn't result in the starting activity being
11042 // destroyed, then we need to make sure at this point that all
11043 // other activities are made visible.
11044 if (DEBUG_SWITCH) Log.i(TAG, "Config didn't destroy " + starting
11045 + ", ensuring others are correct.");
11046 ensureActivitiesVisibleLocked(starting, changes);
11047 }
11048 }
11049
11050 return kept;
11051 }
11052
11053 private final boolean relaunchActivityLocked(HistoryRecord r,
11054 int changes, boolean andResume) {
11055 List<ResultInfo> results = null;
11056 List<Intent> newIntents = null;
11057 if (andResume) {
11058 results = r.results;
11059 newIntents = r.newIntents;
11060 }
11061 if (DEBUG_SWITCH) Log.v(TAG, "Relaunching: " + r
11062 + " with results=" + results + " newIntents=" + newIntents
11063 + " andResume=" + andResume);
11064 EventLog.writeEvent(andResume ? LOG_AM_RELAUNCH_RESUME_ACTIVITY
11065 : LOG_AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
11066 r.task.taskId, r.shortComponentName);
11067
11068 r.startFreezingScreenLocked(r.app, 0);
11069
11070 try {
11071 if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting resumed " + r);
11072 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
11073 changes, !andResume);
11074 // Note: don't need to call pauseIfSleepingLocked() here, because
11075 // the caller will only pass in 'andResume' if this activity is
11076 // currently resumed, which implies we aren't sleeping.
11077 } catch (RemoteException e) {
11078 return false;
11079 }
11080
11081 if (andResume) {
11082 r.results = null;
11083 r.newIntents = null;
11084 }
11085
11086 return true;
11087 }
11088
11089 /**
11090 * Make sure the given activity matches the current configuration. Returns
11091 * false if the activity had to be destroyed. Returns true if the
11092 * configuration is the same, or the activity will remain running as-is
11093 * for whatever reason. Ensures the HistoryRecord is updated with the
11094 * correct configuration and all other bookkeeping is handled.
11095 */
11096 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
11097 int globalChanges) {
11098 if (DEBUG_SWITCH) Log.i(TAG, "Ensuring correct configuration: " + r);
11099
11100 // Short circuit: if the two configurations are the exact same
11101 // object (the common case), then there is nothing to do.
11102 Configuration newConfig = mConfiguration;
11103 if (r.configuration == newConfig) {
11104 if (DEBUG_SWITCH) Log.i(TAG, "Configuration unchanged in " + r);
11105 return true;
11106 }
11107
11108 // We don't worry about activities that are finishing.
11109 if (r.finishing) {
11110 if (DEBUG_SWITCH) Log.i(TAG,
11111 "Configuration doesn't matter in finishing " + r);
11112 r.stopFreezingScreenLocked(false);
11113 return true;
11114 }
11115
11116 // Okay we now are going to make this activity have the new config.
11117 // But then we need to figure out how it needs to deal with that.
11118 Configuration oldConfig = r.configuration;
11119 r.configuration = newConfig;
11120
11121 // If the activity isn't currently running, just leave the new
11122 // configuration and it will pick that up next time it starts.
11123 if (r.app == null || r.app.thread == null) {
11124 if (DEBUG_SWITCH) Log.i(TAG,
11125 "Configuration doesn't matter not running " + r);
11126 r.stopFreezingScreenLocked(false);
11127 return true;
11128 }
11129
11130 // If the activity isn't persistent, there is a chance we will
11131 // need to restart it.
11132 if (!r.persistent) {
11133
11134 // Figure out what has changed between the two configurations.
11135 int changes = oldConfig.diff(newConfig);
11136 if (DEBUG_SWITCH) {
11137 Log.i(TAG, "Checking to restart " + r.info.name + ": changed=0x"
11138 + Integer.toHexString(changes) + ", handles=0x"
11139 + Integer.toHexString(r.info.configChanges));
11140 }
11141 if ((changes&(~r.info.configChanges)) != 0) {
11142 // Aha, the activity isn't handling the change, so DIE DIE DIE.
11143 r.configChangeFlags |= changes;
11144 r.startFreezingScreenLocked(r.app, globalChanges);
11145 if (r.app == null || r.app.thread == null) {
11146 if (DEBUG_SWITCH) Log.i(TAG, "Switch is destroying non-running " + r);
11147 destroyActivityLocked(r, true);
11148 } else if (r.state == ActivityState.PAUSING) {
11149 // A little annoying: we are waiting for this activity to
11150 // finish pausing. Let's not do anything now, but just
11151 // flag that it needs to be restarted when done pausing.
11152 r.configDestroy = true;
11153 return true;
11154 } else if (r.state == ActivityState.RESUMED) {
11155 // Try to optimize this case: the configuration is changing
11156 // and we need to restart the top, resumed activity.
11157 // Instead of doing the normal handshaking, just say
11158 // "restart!".
11159 if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting resumed " + r);
11160 relaunchActivityLocked(r, r.configChangeFlags, true);
11161 r.configChangeFlags = 0;
11162 } else {
11163 if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting non-resumed " + r);
11164 relaunchActivityLocked(r, r.configChangeFlags, false);
11165 r.configChangeFlags = 0;
11166 }
11167
11168 // All done... tell the caller we weren't able to keep this
11169 // activity around.
11170 return false;
11171 }
11172 }
11173
11174 // Default case: the activity can handle this new configuration, so
11175 // hand it over. Note that we don't need to give it the new
11176 // configuration, since we always send configuration changes to all
11177 // process when they happen so it can just use whatever configuration
11178 // it last got.
11179 if (r.app != null && r.app.thread != null) {
11180 try {
11181 r.app.thread.scheduleActivityConfigurationChanged(r);
11182 } catch (RemoteException e) {
11183 // If process died, whatever.
11184 }
11185 }
11186 r.stopFreezingScreenLocked(false);
11187
11188 return true;
11189 }
11190
11191 /**
11192 * Save the locale. You must be inside a synchronized (this) block.
11193 */
11194 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11195 if(isDiff) {
11196 SystemProperties.set("user.language", l.getLanguage());
11197 SystemProperties.set("user.region", l.getCountry());
11198 }
11199
11200 if(isPersist) {
11201 SystemProperties.set("persist.sys.language", l.getLanguage());
11202 SystemProperties.set("persist.sys.country", l.getCountry());
11203 SystemProperties.set("persist.sys.localevar", l.getVariant());
11204 }
11205 }
11206
11207 // =========================================================
11208 // LIFETIME MANAGEMENT
11209 // =========================================================
11210
11211 private final int computeOomAdjLocked(
11212 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11213 if (mAdjSeq == app.adjSeq) {
11214 // This adjustment has already been computed.
11215 return app.curAdj;
11216 }
11217
11218 if (app.thread == null) {
11219 app.adjSeq = mAdjSeq;
11220 return (app.curAdj=EMPTY_APP_ADJ);
11221 }
11222
11223 app.isForeground = false;
11224
The Android Open Source Project4df24232009-03-05 14:34:35 -080011225 // Determine the importance of the process, starting with most
11226 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227 int adj;
11228 int N;
11229 if (app == TOP_APP || app.instrumentationClass != null
11230 || app.persistentActivities > 0) {
11231 // The last app on the list is the foreground app.
11232 adj = FOREGROUND_APP_ADJ;
11233 app.isForeground = true;
11234 } else if (app.curReceiver != null ||
11235 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11236 // An app that is currently receiving a broadcast also
11237 // counts as being in the foreground.
11238 adj = FOREGROUND_APP_ADJ;
11239 } else if (app.executingServices.size() > 0) {
11240 // An app that is currently executing a service callback also
11241 // counts as being in the foreground.
11242 adj = FOREGROUND_APP_ADJ;
11243 } else if (app.foregroundServices || app.forcingToForeground != null) {
11244 // The user is aware of this app, so make it visible.
11245 adj = VISIBLE_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -080011246 } else if (app == mHomeProcess) {
11247 // This process is hosting what we currently consider to be the
11248 // home app, so we don't want to let it go into the background.
11249 adj = HOME_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011250 } else if ((N=app.activities.size()) != 0) {
11251 // This app is in the background with paused activities.
11252 adj = hiddenAdj;
11253 for (int j=0; j<N; j++) {
11254 if (((HistoryRecord)app.activities.get(j)).visible) {
11255 // This app has a visible activity!
11256 adj = VISIBLE_APP_ADJ;
11257 break;
11258 }
11259 }
11260 } else {
11261 // A very not-needed process.
11262 adj = EMPTY_APP_ADJ;
11263 }
11264
The Android Open Source Project4df24232009-03-05 14:34:35 -080011265 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 // there are applications dependent on our services or providers, but
11267 // this gives us a baseline and makes sure we don't get into an
11268 // infinite recursion.
11269 app.adjSeq = mAdjSeq;
11270 app.curRawAdj = adj;
11271 app.curAdj = adj <= app.maxAdj ? adj : app.maxAdj;
11272
11273 if (app.services.size() != 0 && adj > FOREGROUND_APP_ADJ) {
11274 // If this process has active services running in it, we would
11275 // like to avoid killing it unless it would prevent the current
11276 // application from running.
11277 if (adj > hiddenAdj) {
11278 adj = hiddenAdj;
11279 }
11280 final long now = SystemClock.uptimeMillis();
11281 // This process is more important if the top activity is
11282 // bound to the service.
11283 Iterator jt = app.services.iterator();
11284 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11285 ServiceRecord s = (ServiceRecord)jt.next();
11286 if (s.startRequested) {
11287 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11288 // This service has seen some activity within
11289 // recent memory, so we will keep its process ahead
11290 // of the background processes.
11291 if (adj > SECONDARY_SERVER_ADJ) {
11292 adj = SECONDARY_SERVER_ADJ;
11293 }
11294 } else {
11295 // This service has been inactive for too long, just
11296 // put it with the rest of the background processes.
11297 if (adj > hiddenAdj) {
11298 adj = hiddenAdj;
11299 }
11300 }
11301 }
11302 if (s.connections.size() > 0 && adj > FOREGROUND_APP_ADJ) {
11303 Iterator<ConnectionRecord> kt
11304 = s.connections.values().iterator();
11305 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11306 // XXX should compute this based on the max of
11307 // all connected clients.
11308 ConnectionRecord cr = kt.next();
11309 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11310 ProcessRecord client = cr.binding.client;
11311 int myHiddenAdj = hiddenAdj;
11312 if (myHiddenAdj > client.hiddenAdj) {
11313 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
11314 myHiddenAdj = client.hiddenAdj;
11315 } else {
11316 myHiddenAdj = VISIBLE_APP_ADJ;
11317 }
11318 }
11319 int clientAdj = computeOomAdjLocked(
11320 client, myHiddenAdj, TOP_APP);
11321 if (adj > clientAdj) {
11322 adj = clientAdj > VISIBLE_APP_ADJ
11323 ? clientAdj : VISIBLE_APP_ADJ;
11324 }
11325 }
11326 HistoryRecord a = cr.activity;
11327 //if (a != null) {
11328 // Log.i(TAG, "Connection to " + a ": state=" + a.state);
11329 //}
11330 if (a != null && adj > FOREGROUND_APP_ADJ &&
11331 (a.state == ActivityState.RESUMED
11332 || a.state == ActivityState.PAUSING)) {
11333 adj = FOREGROUND_APP_ADJ;
11334 }
11335 }
11336 }
11337 }
11338 }
11339
11340 if (app.pubProviders.size() != 0 && adj > FOREGROUND_APP_ADJ) {
11341 // If this process has published any content providers, then
11342 // its adjustment makes it at least as important as any of the
11343 // processes using those providers, and no less important than
11344 // CONTENT_PROVIDER_ADJ, which is just shy of EMPTY.
11345 if (adj > CONTENT_PROVIDER_ADJ) {
11346 adj = CONTENT_PROVIDER_ADJ;
11347 }
11348 Iterator jt = app.pubProviders.values().iterator();
11349 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11350 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
11351 if (cpr.clients.size() != 0) {
11352 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11353 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11354 ProcessRecord client = kt.next();
11355 int myHiddenAdj = hiddenAdj;
11356 if (myHiddenAdj > client.hiddenAdj) {
11357 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11358 myHiddenAdj = client.hiddenAdj;
11359 } else {
11360 myHiddenAdj = FOREGROUND_APP_ADJ;
11361 }
11362 }
11363 int clientAdj = computeOomAdjLocked(
11364 client, myHiddenAdj, TOP_APP);
11365 if (adj > clientAdj) {
11366 adj = clientAdj > FOREGROUND_APP_ADJ
11367 ? clientAdj : FOREGROUND_APP_ADJ;
11368 }
11369 }
11370 }
11371 // If the provider has external (non-framework) process
11372 // dependencies, ensure that its adjustment is at least
11373 // FOREGROUND_APP_ADJ.
11374 if (cpr.externals != 0) {
11375 if (adj > FOREGROUND_APP_ADJ) {
11376 adj = FOREGROUND_APP_ADJ;
11377 }
11378 }
11379 }
11380 }
11381
11382 app.curRawAdj = adj;
11383
11384 //Log.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
11385 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11386 if (adj > app.maxAdj) {
11387 adj = app.maxAdj;
11388 }
11389
11390 app.curAdj = adj;
11391
11392 return adj;
11393 }
11394
11395 /**
11396 * Ask a given process to GC right now.
11397 */
11398 final void performAppGcLocked(ProcessRecord app) {
11399 try {
11400 app.lastRequestedGc = SystemClock.uptimeMillis();
11401 if (app.thread != null) {
11402 app.thread.processInBackground();
11403 }
11404 } catch (Exception e) {
11405 // whatever.
11406 }
11407 }
11408
11409 /**
11410 * Returns true if things are idle enough to perform GCs.
11411 */
11412 private final boolean canGcNow() {
11413 return mParallelBroadcasts.size() == 0
11414 && mOrderedBroadcasts.size() == 0
11415 && (mSleeping || (mResumedActivity != null &&
11416 mResumedActivity.idle));
11417 }
11418
11419 /**
11420 * Perform GCs on all processes that are waiting for it, but only
11421 * if things are idle.
11422 */
11423 final void performAppGcsLocked() {
11424 final int N = mProcessesToGc.size();
11425 if (N <= 0) {
11426 return;
11427 }
11428 if (canGcNow()) {
11429 while (mProcessesToGc.size() > 0) {
11430 ProcessRecord proc = mProcessesToGc.remove(0);
11431 if (proc.curRawAdj > VISIBLE_APP_ADJ) {
11432 // To avoid spamming the system, we will GC processes one
11433 // at a time, waiting a few seconds between each.
11434 performAppGcLocked(proc);
11435 scheduleAppGcsLocked();
11436 return;
11437 }
11438 }
11439 }
11440 }
11441
11442 /**
11443 * If all looks good, perform GCs on all processes waiting for them.
11444 */
11445 final void performAppGcsIfAppropriateLocked() {
11446 if (canGcNow()) {
11447 performAppGcsLocked();
11448 return;
11449 }
11450 // Still not idle, wait some more.
11451 scheduleAppGcsLocked();
11452 }
11453
11454 /**
11455 * Schedule the execution of all pending app GCs.
11456 */
11457 final void scheduleAppGcsLocked() {
11458 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
11459 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11460 mHandler.sendMessageDelayed(msg, GC_TIMEOUT);
11461 }
11462
11463 /**
11464 * Set up to ask a process to GC itself. This will either do it
11465 * immediately, or put it on the list of processes to gc the next
11466 * time things are idle.
11467 */
11468 final void scheduleAppGcLocked(ProcessRecord app) {
11469 long now = SystemClock.uptimeMillis();
11470 if ((app.lastRequestedGc+5000) > now) {
11471 return;
11472 }
11473 if (!mProcessesToGc.contains(app)) {
11474 mProcessesToGc.add(app);
11475 scheduleAppGcsLocked();
11476 }
11477 }
11478
11479 private final boolean updateOomAdjLocked(
11480 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11481 app.hiddenAdj = hiddenAdj;
11482
11483 if (app.thread == null) {
11484 return true;
11485 }
11486
11487 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP);
11488
11489 //Log.i(TAG, "Computed adj " + adj + " for app " + app.processName);
11490 //Thread priority adjustment is disabled out to see
11491 //how the kernel scheduler performs.
11492 if (false) {
11493 if (app.pid != 0 && app.isForeground != app.setIsForeground) {
11494 app.setIsForeground = app.isForeground;
11495 if (app.pid != MY_PID) {
11496 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(TAG, "Setting priority of " + app
11497 + " to " + (app.isForeground
11498 ? Process.THREAD_PRIORITY_FOREGROUND
11499 : Process.THREAD_PRIORITY_DEFAULT));
11500 try {
11501 Process.setThreadPriority(app.pid, app.isForeground
11502 ? Process.THREAD_PRIORITY_FOREGROUND
11503 : Process.THREAD_PRIORITY_DEFAULT);
11504 } catch (RuntimeException e) {
11505 Log.w(TAG, "Exception trying to set priority of application thread "
11506 + app.pid, e);
11507 }
11508 }
11509 }
11510 }
11511 if (app.pid != 0 && app.pid != MY_PID) {
11512 if (app.curRawAdj != app.setRawAdj) {
11513 if (app.curRawAdj > FOREGROUND_APP_ADJ
11514 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11515 // If this app is transitioning from foreground to
11516 // non-foreground, have it do a gc.
11517 scheduleAppGcLocked(app);
11518 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11519 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11520 // Likewise do a gc when an app is moving in to the
11521 // background (such as a service stopping).
11522 scheduleAppGcLocked(app);
11523 }
11524 app.setRawAdj = app.curRawAdj;
11525 }
11526 if (adj != app.setAdj) {
11527 if (Process.setOomAdj(app.pid, adj)) {
11528 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(
11529 TAG, "Set app " + app.processName +
11530 " oom adj to " + adj);
11531 app.setAdj = adj;
11532 } else {
11533 return false;
11534 }
11535 }
11536 }
11537
11538 return true;
11539 }
11540
11541 private final HistoryRecord resumedAppLocked() {
11542 HistoryRecord resumedActivity = mResumedActivity;
11543 if (resumedActivity == null || resumedActivity.app == null) {
11544 resumedActivity = mPausingActivity;
11545 if (resumedActivity == null || resumedActivity.app == null) {
11546 resumedActivity = topRunningActivityLocked(null);
11547 }
11548 }
11549 return resumedActivity;
11550 }
11551
11552 private final boolean updateOomAdjLocked(ProcessRecord app) {
11553 final HistoryRecord TOP_ACT = resumedAppLocked();
11554 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11555 int curAdj = app.curAdj;
11556 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11557 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11558
11559 mAdjSeq++;
11560
11561 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11562 if (res) {
11563 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11564 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11565 if (nowHidden != wasHidden) {
11566 // Changed to/from hidden state, so apps after it in the LRU
11567 // list may also be changed.
11568 updateOomAdjLocked();
11569 }
11570 }
11571 return res;
11572 }
11573
11574 private final boolean updateOomAdjLocked() {
11575 boolean didOomAdj = true;
11576 final HistoryRecord TOP_ACT = resumedAppLocked();
11577 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11578
11579 if (false) {
11580 RuntimeException e = new RuntimeException();
11581 e.fillInStackTrace();
11582 Log.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
11583 }
11584
11585 mAdjSeq++;
11586
11587 // First try updating the OOM adjustment for each of the
11588 // application processes based on their current state.
11589 int i = mLRUProcesses.size();
11590 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11591 while (i > 0) {
11592 i--;
11593 ProcessRecord app = mLRUProcesses.get(i);
11594 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
11595 if (curHiddenAdj < HIDDEN_APP_MAX_ADJ
11596 && app.curAdj == curHiddenAdj) {
11597 curHiddenAdj++;
11598 }
11599 } else {
11600 didOomAdj = false;
11601 }
11602 }
11603
11604 // todo: for now pretend like OOM ADJ didn't work, because things
11605 // aren't behaving as expected on Linux -- it's not killing processes.
11606 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11607 }
11608
11609 private final void trimApplications() {
11610 synchronized (this) {
11611 int i;
11612
11613 // First remove any unused application processes whose package
11614 // has been removed.
11615 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11616 final ProcessRecord app = mRemovedProcesses.get(i);
11617 if (app.activities.size() == 0
11618 && app.curReceiver == null && app.services.size() == 0) {
11619 Log.i(
11620 TAG, "Exiting empty application process "
11621 + app.processName + " ("
11622 + (app.thread != null ? app.thread.asBinder() : null)
11623 + ")\n");
11624 if (app.pid > 0 && app.pid != MY_PID) {
11625 Process.killProcess(app.pid);
11626 } else {
11627 try {
11628 app.thread.scheduleExit();
11629 } catch (Exception e) {
11630 // Ignore exceptions.
11631 }
11632 }
11633 cleanUpApplicationRecordLocked(app, false, -1);
11634 mRemovedProcesses.remove(i);
11635
11636 if (app.persistent) {
11637 if (app.persistent) {
11638 addAppLocked(app.info);
11639 }
11640 }
11641 }
11642 }
11643
11644 // Now try updating the OOM adjustment for each of the
11645 // application processes based on their current state.
11646 // If the setOomAdj() API is not supported, then go with our
11647 // back-up plan...
11648 if (!updateOomAdjLocked()) {
11649
11650 // Count how many processes are running services.
11651 int numServiceProcs = 0;
11652 for (i=mLRUProcesses.size()-1; i>=0; i--) {
11653 final ProcessRecord app = mLRUProcesses.get(i);
11654
11655 if (app.persistent || app.services.size() != 0
11656 || app.curReceiver != null
11657 || app.persistentActivities > 0) {
11658 // Don't count processes holding services against our
11659 // maximum process count.
11660 if (localLOGV) Log.v(
11661 TAG, "Not trimming app " + app + " with services: "
11662 + app.services);
11663 numServiceProcs++;
11664 }
11665 }
11666
11667 int curMaxProcs = mProcessLimit;
11668 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11669 if (mAlwaysFinishActivities) {
11670 curMaxProcs = 1;
11671 }
11672 curMaxProcs += numServiceProcs;
11673
11674 // Quit as many processes as we can to get down to the desired
11675 // process count. First remove any processes that no longer
11676 // have activites running in them.
11677 for ( i=0;
11678 i<mLRUProcesses.size()
11679 && mLRUProcesses.size() > curMaxProcs;
11680 i++) {
11681 final ProcessRecord app = mLRUProcesses.get(i);
11682 // Quit an application only if it is not currently
11683 // running any activities.
11684 if (!app.persistent && app.activities.size() == 0
11685 && app.curReceiver == null && app.services.size() == 0) {
11686 Log.i(
11687 TAG, "Exiting empty application process "
11688 + app.processName + " ("
11689 + (app.thread != null ? app.thread.asBinder() : null)
11690 + ")\n");
11691 if (app.pid > 0 && app.pid != MY_PID) {
11692 Process.killProcess(app.pid);
11693 } else {
11694 try {
11695 app.thread.scheduleExit();
11696 } catch (Exception e) {
11697 // Ignore exceptions.
11698 }
11699 }
11700 // todo: For now we assume the application is not buggy
11701 // or evil, and will quit as a result of our request.
11702 // Eventually we need to drive this off of the death
11703 // notification, and kill the process if it takes too long.
11704 cleanUpApplicationRecordLocked(app, false, i);
11705 i--;
11706 }
11707 }
11708
11709 // If we still have too many processes, now from the least
11710 // recently used process we start finishing activities.
11711 if (Config.LOGV) Log.v(
11712 TAG, "*** NOW HAVE " + mLRUProcesses.size() +
11713 " of " + curMaxProcs + " processes");
11714 for ( i=0;
11715 i<mLRUProcesses.size()
11716 && mLRUProcesses.size() > curMaxProcs;
11717 i++) {
11718 final ProcessRecord app = mLRUProcesses.get(i);
11719 // Quit the application only if we have a state saved for
11720 // all of its activities.
11721 boolean canQuit = !app.persistent && app.curReceiver == null
11722 && app.services.size() == 0
11723 && app.persistentActivities == 0;
11724 int NUMA = app.activities.size();
11725 int j;
11726 if (Config.LOGV) Log.v(
11727 TAG, "Looking to quit " + app.processName);
11728 for (j=0; j<NUMA && canQuit; j++) {
11729 HistoryRecord r = (HistoryRecord)app.activities.get(j);
11730 if (Config.LOGV) Log.v(
11731 TAG, " " + r.intent.getComponent().flattenToShortString()
11732 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11733 canQuit = (r.haveState || !r.stateNotNeeded)
11734 && !r.visible && r.stopped;
11735 }
11736 if (canQuit) {
11737 // Finish all of the activities, and then the app itself.
11738 for (j=0; j<NUMA; j++) {
11739 HistoryRecord r = (HistoryRecord)app.activities.get(j);
11740 if (!r.finishing) {
11741 destroyActivityLocked(r, false);
11742 }
11743 r.resultTo = null;
11744 }
11745 Log.i(TAG, "Exiting application process "
11746 + app.processName + " ("
11747 + (app.thread != null ? app.thread.asBinder() : null)
11748 + ")\n");
11749 if (app.pid > 0 && app.pid != MY_PID) {
11750 Process.killProcess(app.pid);
11751 } else {
11752 try {
11753 app.thread.scheduleExit();
11754 } catch (Exception e) {
11755 // Ignore exceptions.
11756 }
11757 }
11758 // todo: For now we assume the application is not buggy
11759 // or evil, and will quit as a result of our request.
11760 // Eventually we need to drive this off of the death
11761 // notification, and kill the process if it takes too long.
11762 cleanUpApplicationRecordLocked(app, false, i);
11763 i--;
11764 //dump();
11765 }
11766 }
11767
11768 }
11769
11770 int curMaxActivities = MAX_ACTIVITIES;
11771 if (mAlwaysFinishActivities) {
11772 curMaxActivities = 1;
11773 }
11774
11775 // Finally, if there are too many activities now running, try to
11776 // finish as many as we can to get back down to the limit.
11777 for ( i=0;
11778 i<mLRUActivities.size()
11779 && mLRUActivities.size() > curMaxActivities;
11780 i++) {
11781 final HistoryRecord r
11782 = (HistoryRecord)mLRUActivities.get(i);
11783
11784 // We can finish this one if we have its icicle saved and
11785 // it is not persistent.
11786 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11787 && r.stopped && !r.persistent && !r.finishing) {
11788 final int origSize = mLRUActivities.size();
11789 destroyActivityLocked(r, true);
11790
11791 // This will remove it from the LRU list, so keep
11792 // our index at the same value. Note that this check to
11793 // see if the size changes is just paranoia -- if
11794 // something unexpected happens, we don't want to end up
11795 // in an infinite loop.
11796 if (origSize > mLRUActivities.size()) {
11797 i--;
11798 }
11799 }
11800 }
11801 }
11802 }
11803
11804 /** This method sends the specified signal to each of the persistent apps */
11805 public void signalPersistentProcesses(int sig) throws RemoteException {
11806 if (sig != Process.SIGNAL_USR1) {
11807 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11808 }
11809
11810 synchronized (this) {
11811 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11812 != PackageManager.PERMISSION_GRANTED) {
11813 throw new SecurityException("Requires permission "
11814 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11815 }
11816
11817 for (int i = mLRUProcesses.size() - 1 ; i >= 0 ; i--) {
11818 ProcessRecord r = mLRUProcesses.get(i);
11819 if (r.thread != null && r.persistent) {
11820 Process.sendSignal(r.pid, sig);
11821 }
11822 }
11823 }
11824 }
11825
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011826 public boolean profileControl(String process, boolean start,
11827 String path) throws RemoteException {
11828
11829 synchronized (this) {
11830 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11831 // its own permission.
11832 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11833 != PackageManager.PERMISSION_GRANTED) {
11834 throw new SecurityException("Requires permission "
11835 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
11836 }
11837
11838 ProcessRecord proc = null;
11839 try {
11840 int pid = Integer.parseInt(process);
11841 synchronized (mPidsSelfLocked) {
11842 proc = mPidsSelfLocked.get(pid);
11843 }
11844 } catch (NumberFormatException e) {
11845 }
11846
11847 if (proc == null) {
11848 HashMap<String, SparseArray<ProcessRecord>> all
11849 = mProcessNames.getMap();
11850 SparseArray<ProcessRecord> procs = all.get(process);
11851 if (procs != null && procs.size() > 0) {
11852 proc = procs.valueAt(0);
11853 }
11854 }
11855
11856 if (proc == null || proc.thread == null) {
11857 throw new IllegalArgumentException("Unknown process: " + process);
11858 }
11859
11860 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11861 if (isSecure) {
11862 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11863 throw new SecurityException("Process not debuggable: " + proc);
11864 }
11865 }
11866
11867 try {
11868 proc.thread.profilerControl(start, path);
11869 return true;
11870 } catch (RemoteException e) {
11871 throw new IllegalStateException("Process disappeared");
11872 }
11873 }
11874 }
11875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011876 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11877 public void monitor() {
11878 synchronized (this) { }
11879 }
11880}