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