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