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