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