diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
new file mode 100644
index 0000000..141569e
--- /dev/null
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -0,0 +1,11790 @@
+/*
+ * Copyright (C) 2006-2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.RuntimeInit;
+import com.android.server.IntentResolver;
+import com.android.server.ProcessMap;
+import com.android.server.ProcessStats;
+import com.android.server.SystemServer;
+import com.android.server.Watchdog;
+import com.android.server.WindowManagerService;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.ActivityThread;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.IActivityWatcher;
+import android.app.IApplicationThread;
+import android.app.IInstrumentationWatcher;
+import android.app.IIntentReceiver;
+import android.app.IIntentSender;
+import android.app.IServiceConnection;
+import android.app.IThumbnailReceiver;
+import android.app.Instrumentation;
+import android.app.PendingIntent;
+import android.app.ResultInfo;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.IPackageDataObserver;
+import android.content.pm.IPackageManager;
+import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.FileUtils;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IPermissionController;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.provider.Checkin;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Config;
+import android.util.EventLog;
+import android.util.Log;
+import android.util.PrintWriterPrinter;
+import android.util.SparseArray;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import dalvik.system.Zygote;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.lang.IllegalStateException;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
+    static final String TAG = "ActivityManager";
+    static final boolean DEBUG = false;
+    static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+    static final boolean DEBUG_SWITCH = localLOGV || false;
+    static final boolean DEBUG_TASKS = localLOGV || false;
+    static final boolean DEBUG_PAUSE = localLOGV || false;
+    static final boolean DEBUG_OOM_ADJ = localLOGV || false;
+    static final boolean DEBUG_TRANSITION = localLOGV || false;
+    static final boolean DEBUG_BROADCAST = localLOGV || false;
+    static final boolean DEBUG_SERVICE = localLOGV || false;
+    static final boolean DEBUG_VISBILITY = localLOGV || false;
+    static final boolean DEBUG_PROCESSES = localLOGV || false;
+    static final boolean DEBUG_USER_LEAVING = localLOGV || false;
+    static final boolean VALIDATE_TOKENS = false;
+    static final boolean SHOW_ACTIVITY_START_TIME = true;
+    
+    // Control over CPU and battery monitoring.
+    static final long BATTERY_STATS_TIME = 30*60*1000;      // write battery stats every 30 minutes.
+    static final boolean MONITOR_CPU_USAGE = true;
+    static final long MONITOR_CPU_MIN_TIME = 5*1000;        // don't sample cpu less than every 5 seconds.
+    static final long MONITOR_CPU_MAX_TIME = 0x0fffffff;    // wait possibly forever for next cpu sample.
+    static final boolean MONITOR_THREAD_CPU_USAGE = false;
+
+    // Event log tags
+    static final int LOG_CONFIGURATION_CHANGED = 2719;
+    static final int LOG_CPU = 2721;
+    static final int LOG_AM_FINISH_ACTIVITY = 30001;
+    static final int LOG_TASK_TO_FRONT = 30002;
+    static final int LOG_AM_NEW_INTENT = 30003;
+    static final int LOG_AM_CREATE_TASK = 30004;
+    static final int LOG_AM_CREATE_ACTIVITY = 30005;
+    static final int LOG_AM_RESTART_ACTIVITY = 30006;
+    static final int LOG_AM_RESUME_ACTIVITY = 30007;
+    static final int LOG_ANR = 30008;
+    static final int LOG_ACTIVITY_LAUNCH_TIME = 30009;
+    static final int LOG_AM_PROCESS_BOUND = 30010;
+    static final int LOG_AM_PROCESS_DIED = 30011;
+    static final int LOG_AM_FAILED_TO_PAUSE_ACTIVITY = 30012;
+    static final int LOG_AM_PAUSE_ACTIVITY = 30013;
+    static final int LOG_AM_PROCESS_START = 30014;
+    static final int LOG_AM_PROCESS_BAD = 30015;
+    static final int LOG_AM_PROCESS_GOOD = 30016;
+    static final int LOG_AM_LOW_MEMORY = 30017;
+    static final int LOG_AM_DESTROY_ACTIVITY = 30018;
+    static final int LOG_AM_RELAUNCH_RESUME_ACTIVITY = 30019;
+    static final int LOG_AM_RELAUNCH_ACTIVITY = 30020;
+    static final int LOG_AM_KILL_FOR_MEMORY = 30023;
+    static final int LOG_AM_BROADCAST_DISCARD_FILTER = 30024;
+    static final int LOG_AM_BROADCAST_DISCARD_APP = 30025;
+    static final int LOG_AM_CREATE_SERVICE = 30030;
+    static final int LOG_AM_DESTROY_SERVICE = 30031;
+    static final int LOG_AM_PROCESS_CRASHED_TOO_MUCH = 30032;
+    static final int LOG_AM_DROP_PROCESS = 30033;
+    static final int LOG_AM_SERVICE_CRASHED_TOO_MUCH = 30034;
+    static final int LOG_AM_SCHEDULE_SERVICE_RESTART = 30035;
+    static final int LOG_AM_PROVIDER_LOST_PROCESS = 30036;
+    
+    static final int LOG_BOOT_PROGRESS_AMS_READY = 3040;
+    static final int LOG_BOOT_PROGRESS_ENABLE_SCREEN = 3050;
+
+    private static final String SYSTEM_SECURE = "ro.secure";
+
+    // This is the maximum number of application processes we would like
+    // to have running.  Due to the asynchronous nature of things, we can
+    // temporarily go beyond this limit.
+    static final int MAX_PROCESSES = 2;
+
+    // Set to false to leave processes running indefinitely, relying on
+    // the kernel killing them as resources are required.
+    static final boolean ENFORCE_PROCESS_LIMIT = false;
+
+    // This is the maximum number of activities that we would like to have
+    // running at a given time.
+    static final int MAX_ACTIVITIES = 20;
+
+    // Maximum number of recent tasks that we can remember.
+    static final int MAX_RECENT_TASKS = 20;
+
+    // How long until we reset a task when the user returns to it.  Currently
+    // 30 minutes.
+    static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
+    
+    // Set to true to disable the icon that is shown while a new activity
+    // is being started.
+    static final boolean SHOW_APP_STARTING_ICON = true;
+
+    // How long we wait until giving up on the last activity to pause.  This
+    // is short because it directly impacts the responsiveness of starting the
+    // next activity.
+    static final int PAUSE_TIMEOUT = 500;
+
+    /**
+     * How long we can hold the launch wake lock before giving up.
+     */
+    static final int LAUNCH_TIMEOUT = 10*1000;
+
+    // How long we wait for a launched process to attach to the activity manager
+    // before we decide it's never going to come up for real.
+    static final int PROC_START_TIMEOUT = 10*1000;
+
+    // How long we wait until giving up on the last activity telling us it
+    // is idle.
+    static final int IDLE_TIMEOUT = 10*1000;
+
+    // How long to wait after going idle before forcing apps to GC.
+    static final int GC_TIMEOUT = 5*1000;
+
+    // How long we wait until giving up on an activity telling us it has
+    // finished destroying itself.
+    static final int DESTROY_TIMEOUT = 10*1000;
+    
+    // How long we allow a receiver to run before giving up on it.
+    static final int BROADCAST_TIMEOUT = 10*1000;
+
+    // How long we wait for a service to finish executing.
+    static final int SERVICE_TIMEOUT = 20*1000;
+
+    // How long a service needs to be running until restarting its process
+    // is no longer considered to be a relaunch of the service.
+    static final int SERVICE_RESTART_DURATION = 5*1000;
+
+    // Maximum amount of time for there to be no activity on a service before
+    // we consider it non-essential and allow its process to go on the
+    // LRU background list.
+    static final int MAX_SERVICE_INACTIVITY = 10*60*1000;
+    
+    // How long we wait until we timeout on key dispatching.
+    static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
+
+    // The minimum time we allow between crashes, for us to consider this
+    // application to be bad and stop and its services and reject broadcasts.
+    static final int MIN_CRASH_INTERVAL = 60*1000;
+
+    // How long we wait until we timeout on key dispatching during instrumentation.
+    static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
+
+    // OOM adjustments for processes in various states:
+
+    // This is a process without anything currently running in it.  Definitely
+    // the first to go! Value set in system/rootdir/init.rc on startup.
+    // This value is initalized in the constructor, careful when refering to
+    // this static variable externally.
+    static int EMPTY_APP_ADJ;
+
+    // This is a process with a content provider that does not have any clients
+    // attached to it.  If it did have any clients, its adjustment would be the
+    // one for the highest-priority of those processes.
+    static int CONTENT_PROVIDER_ADJ;
+
+    // This is a process only hosting activities that are not visible,
+    // so it can be killed without any disruption. Value set in
+    // system/rootdir/init.rc on startup.
+    final int HIDDEN_APP_MAX_ADJ;
+    static int HIDDEN_APP_MIN_ADJ;
+
+    // This is a process holding a secondary server -- killing it will not
+    // have much of an impact as far as the user is concerned. Value set in
+    // system/rootdir/init.rc on startup.
+    final int SECONDARY_SERVER_ADJ;
+
+    // This is a process only hosting activities that are visible to the
+    // user, so we'd prefer they don't disappear. Value set in
+    // system/rootdir/init.rc on startup.
+    final int VISIBLE_APP_ADJ;
+
+    // This is the process running the current foreground app.  We'd really
+    // rather not kill it! Value set in system/rootdir/init.rc on startup.
+    final int FOREGROUND_APP_ADJ;
+
+    // This is a process running a core server, such as telephony.  Definitely
+    // don't want to kill it, but doing so is not completely fatal.
+    static final int CORE_SERVER_ADJ = -12;
+
+    // The system process runs at the default adjustment.
+    static final int SYSTEM_ADJ = -16;
+
+    // Memory pages are 4K.
+    static final int PAGE_SIZE = 4*1024;
+    
+    // Corresponding memory levels for above adjustments.
+    final int EMPTY_APP_MEM;
+    final int HIDDEN_APP_MEM;
+    final int SECONDARY_SERVER_MEM;
+    final int VISIBLE_APP_MEM;
+    final int FOREGROUND_APP_MEM;
+    
+    final int MY_PID;
+    
+    static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+    enum ActivityState {
+        INITIALIZING,
+        RESUMED,
+        PAUSING,
+        PAUSED,
+        STOPPING,
+        STOPPED,
+        FINISHING,
+        DESTROYING,
+        DESTROYED
+    }
+
+    /**
+     * The back history of all previous (and possibly still
+     * running) activities.  It contains HistoryRecord objects.
+     */
+    final ArrayList mHistory = new ArrayList();
+
+    /**
+     * List of all active broadcasts that are to be executed immediately
+     * (without waiting for another broadcast to finish).  Currently this only
+     * contains broadcasts to registered receivers, to avoid spinning up
+     * a bunch of processes to execute IntentReceiver components.
+     */
+    final ArrayList<BroadcastRecord> mParallelBroadcasts
+            = new ArrayList<BroadcastRecord>();
+
+    /**
+     * List of all active broadcasts that are to be executed one at a time.
+     * The object at the top of the list is the currently activity broadcasts;
+     * those after it are waiting for the top to finish..
+     */
+    final ArrayList<BroadcastRecord> mOrderedBroadcasts
+            = new ArrayList<BroadcastRecord>();
+
+    /**
+     * Set when we current have a BROADCAST_INTENT_MSG in flight.
+     */
+    boolean mBroadcastsScheduled = false;
+
+    /**
+     * Set to indicate whether to issue an onUserLeaving callback when a
+     * newly launched activity is being brought in front of us.
+     */
+    boolean mUserLeaving = false;
+
+    /**
+     * When we are in the process of pausing an activity, before starting the
+     * next one, this variable holds the activity that is currently being paused.
+     */
+    HistoryRecord mPausingActivity = null;
+
+    /**
+     * Current activity that is resumed, or null if there is none.
+     */
+    HistoryRecord mResumedActivity = null;
+
+    /**
+     * Activity we have told the window manager to have key focus.
+     */
+    HistoryRecord mFocusedActivity = null;
+
+    /**
+     * This is the last activity that we put into the paused state.  This is
+     * used to determine if we need to do an activity transition while sleeping,
+     * when we normally hold the top activity paused.
+     */
+    HistoryRecord mLastPausedActivity = null;
+
+    /**
+     * List of activities that are waiting for a new activity
+     * to become visible before completing whatever operation they are
+     * supposed to do.
+     */
+    final ArrayList mWaitingVisibleActivities = new ArrayList();
+
+    /**
+     * List of activities that are ready to be stopped, but waiting
+     * for the next activity to settle down before doing so.  It contains
+     * HistoryRecord objects.
+     */
+    final ArrayList<HistoryRecord> mStoppingActivities
+            = new ArrayList<HistoryRecord>();
+
+    /**
+     * List of intents that were used to start the most recent tasks.
+     */
+    final ArrayList<TaskRecord> mRecentTasks
+            = new ArrayList<TaskRecord>();
+
+    /**
+     * List of activities that are ready to be finished, but waiting
+     * for the previous activity to settle down before doing so.  It contains
+     * HistoryRecord objects.
+     */
+    final ArrayList mFinishingActivities = new ArrayList();
+
+    /**
+     * All of the applications we currently have running organized by name.
+     * The keys are strings of the application package name (as
+     * returned by the package manager), and the keys are ApplicationRecord
+     * objects.
+     */
+    final ProcessMap<ProcessRecord> mProcessNames
+            = new ProcessMap<ProcessRecord>();
+
+    /**
+     * The last time that various processes have crashed.
+     */
+    final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
+
+    /**
+     * Set of applications that we consider to be bad, and will reject
+     * incoming broadcasts from (which the user has no control over).
+     * Processes are added to this set when they have crashed twice within
+     * a minimum amount of time; they are removed from it when they are
+     * later restarted (hopefully due to some user action).  The value is the
+     * time it was added to the list.
+     */
+    final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
+
+    /**
+     * All of the processes we currently have running organized by pid.
+     * The keys are the pid running the application.
+     *
+     * <p>NOTE: This object is protected by its own lock, NOT the global
+     * activity manager lock!
+     */
+    final SparseArray<ProcessRecord> mPidsSelfLocked
+            = new SparseArray<ProcessRecord>();
+
+    /**
+     * All of the processes that have been forced to be foreground.  The key
+     * is the pid of the caller who requested it (we hold a death
+     * link on it).
+     */
+    abstract class ForegroundToken implements IBinder.DeathRecipient {
+        int pid;
+        IBinder token;
+    }
+    final SparseArray<ForegroundToken> mForegroundProcesses
+            = new SparseArray<ForegroundToken>();
+    
+    /**
+     * List of records for processes that someone had tried to start before the
+     * system was ready.  We don't start them at that point, but ensure they
+     * are started by the time booting is complete.
+     */
+    final ArrayList<ProcessRecord> mProcessesOnHold
+            = new ArrayList<ProcessRecord>();
+
+    /**
+     * List of records for processes that we have started and are waiting
+     * for them to call back.  This is really only needed when running in
+     * single processes mode, in which case we do not have a unique pid for
+     * each process.
+     */
+    final ArrayList<ProcessRecord> mStartingProcesses
+            = new ArrayList<ProcessRecord>();
+
+    /**
+     * List of persistent applications that are in the process
+     * of being started.
+     */
+    final ArrayList<ProcessRecord> mPersistentStartingProcesses
+            = new ArrayList<ProcessRecord>();
+
+    /**
+     * Processes that are being forcibly torn down.
+     */
+    final ArrayList<ProcessRecord> mRemovedProcesses
+            = new ArrayList<ProcessRecord>();
+
+    /**
+     * List of running applications, sorted by recent usage.
+     * The first entry in the list is the least recently used.
+     * It contains ApplicationRecord objects.  This list does NOT include
+     * any persistent application records (since we never want to exit them).
+     */
+    final ArrayList<ProcessRecord> mLRUProcesses
+            = new ArrayList<ProcessRecord>();
+
+    /**
+     * List of processes that should gc as soon as things are idle.
+     */
+    final ArrayList<ProcessRecord> mProcessesToGc
+            = new ArrayList<ProcessRecord>();
+
+    /**
+     * List of running activities, sorted by recent usage.
+     * The first entry in the list is the least recently used.
+     * It contains HistoryRecord objects.
+     */
+    private final ArrayList mLRUActivities = new ArrayList();
+
+    /**
+     * Set of PendingResultRecord objects that are currently active.
+     */
+    final HashSet mPendingResultRecords = new HashSet();
+
+    /**
+     * Set of IntentSenderRecord objects that are currently active.
+     */
+    final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
+            = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
+
+    /**
+     * Intent broadcast that we have tried to start, but are
+     * waiting for its application's process to be created.  We only
+     * need one (instead of a list) because we always process broadcasts
+     * one at a time, so no others can be started while waiting for this
+     * one.
+     */
+    BroadcastRecord mPendingBroadcast = null;
+
+    /**
+     * Keeps track of all IIntentReceivers that have been registered for
+     * broadcasts.  Hash keys are the receiver IBinder, hash value is
+     * a ReceiverList.
+     */
+    final HashMap mRegisteredReceivers = new HashMap();
+
+    /**
+     * Resolver for broadcast intents to registered receivers.
+     * Holds BroadcastFilter (subclass of IntentFilter).
+     */
+    final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
+            = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
+        @Override
+        protected boolean allowFilterResult(
+                BroadcastFilter filter, List<BroadcastFilter> dest) {
+            IBinder target = filter.receiverList.receiver.asBinder();
+            for (int i=dest.size()-1; i>=0; i--) {
+                if (dest.get(i).receiverList.receiver.asBinder() == target) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    };
+
+    /**
+     * State of all active sticky broadcasts.  Keys are the action of the
+     * sticky Intent, values are an ArrayList of all broadcasted intents with
+     * that action (which should usually be one).
+     */
+    final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
+            new HashMap<String, ArrayList<Intent>>();
+
+    /**
+     * All currently running services.
+     */
+    final HashMap<ComponentName, ServiceRecord> mServices =
+        new HashMap<ComponentName, ServiceRecord>();
+
+    /**
+     * All currently running services indexed by the Intent used to start them.
+     */
+    final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
+        new HashMap<Intent.FilterComparison, ServiceRecord>();
+
+    /**
+     * All currently bound service connections.  Keys are the IBinder of
+     * the client's IServiceConnection.
+     */
+    final HashMap<IBinder, ConnectionRecord> mServiceConnections
+            = new HashMap<IBinder, ConnectionRecord>();
+
+    /**
+     * List of services that we have been asked to start,
+     * but haven't yet been able to.  It is used to hold start requests
+     * while waiting for their corresponding application thread to get
+     * going.
+     */
+    final ArrayList<ServiceRecord> mPendingServices
+            = new ArrayList<ServiceRecord>();
+
+    /**
+     * List of services that are scheduled to restart following a crash.
+     */
+    final ArrayList<ServiceRecord> mRestartingServices
+            = new ArrayList<ServiceRecord>();
+
+    /**
+     * List of services that are in the process of being stopped.
+     */
+    final ArrayList<ServiceRecord> mStoppingServices
+            = new ArrayList<ServiceRecord>();
+
+    /**
+     * List of PendingThumbnailsRecord objects of clients who are still
+     * waiting to receive all of the thumbnails for a task.
+     */
+    final ArrayList mPendingThumbnails = new ArrayList();
+
+    /**
+     * List of HistoryRecord objects that have been finished and must
+     * still report back to a pending thumbnail receiver.
+     */
+    final ArrayList mCancelledThumbnails = new ArrayList();
+
+    /**
+     * All of the currently running global content providers.  Keys are a
+     * string containing the provider name and values are a
+     * ContentProviderRecord object containing the data about it.  Note
+     * that a single provider may be published under multiple names, so
+     * there may be multiple entries here for a single one in mProvidersByClass.
+     */
+    final HashMap mProvidersByName = new HashMap();
+
+    /**
+     * All of the currently running global content providers.  Keys are a
+     * string containing the provider's implementation class and values are a
+     * ContentProviderRecord object containing the data about it.
+     */
+    final HashMap mProvidersByClass = new HashMap();
+
+    /**
+     * List of content providers who have clients waiting for them.  The
+     * application is currently being launched and the provider will be
+     * removed from this list once it is published.
+     */
+    final ArrayList mLaunchingProviders = new ArrayList();
+
+    /**
+     * Global set of specific Uri permissions that have been granted.
+     */
+    final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
+            = new SparseArray<HashMap<Uri, UriPermission>>();
+
+    /**
+     * Thread-local storage used to carry caller permissions over through
+     * indirect content-provider access.
+     * @see #ActivityManagerService.openContentUri()
+     */
+    private class Identity {
+        public int pid;
+        public int uid;
+
+        Identity(int _pid, int _uid) {
+            pid = _pid;
+            uid = _uid;
+        }
+    }
+    private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
+
+    /**
+     * All information we have collected about the runtime performance of
+     * any user id that can impact battery performance.
+     */
+    final BatteryStatsService mBatteryStatsService;
+    
+    /**
+     * information about component usage
+     */
+    final UsageStatsService mUsageStatsService;
+
+    /**
+     * Current configuration information.  HistoryRecord objects are given
+     * a reference to this object to indicate which configuration they are
+     * currently running in, so this object must be kept immutable.
+     */
+    Configuration mConfiguration = new Configuration();
+
+    /**
+     * List of initialization arguments to pass to all processes when binding applications to them.
+     * For example, references to the commonly used services.
+     */
+    HashMap<String, IBinder> mAppBindArgs;
+
+    /**
+     * Used to control how we initialize the service.
+     */
+    boolean mStartRunning = false;
+    ComponentName mTopComponent;
+    String mTopAction;
+    String mTopData;
+    boolean mSystemReady = false;
+    boolean mBooting = false;
+
+    Context mContext;
+
+    int mFactoryTest;
+
+    /**
+     * Set while we are wanting to sleep, to prevent any
+     * activities from being started/resumed.
+     */
+    boolean mSleeping = false;
+
+    /**
+     * Set when the system is going to sleep, until we have
+     * successfully paused the current activity and released our wake lock.
+     * At that point the system is allowed to actually sleep.
+     */
+    PowerManager.WakeLock mGoingToSleep;
+
+    /**
+     * We don't want to allow the device to go to sleep while in the process
+     * of launching an activity.  This is primarily to allow alarm intent
+     * receivers to launch an activity and get that to run before the device
+     * goes back to sleep.
+     */
+    PowerManager.WakeLock mLaunchingActivity;
+
+    /**
+     * Task identifier that activities are currently being started
+     * in.  Incremented each time a new task is created.
+     * todo: Replace this with a TokenSpace class that generates non-repeating
+     * integers that won't wrap.
+     */
+    int mCurTask = 1;
+
+    /**
+     * Current sequence id for oom_adj computation traversal.
+     */
+    int mAdjSeq = 0;
+
+    /**
+     * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
+     * is set, indicating the user wants processes started in such a way
+     * that they can use ANDROID_PROCESS_WRAPPER and know what will be
+     * running in each process (thus no pre-initialized process, etc).
+     */
+    boolean mSimpleProcessManagement = false;
+
+    /**
+     * System monitoring: number of processes that died since the last
+     * N procs were started.
+     */
+    int[] mProcDeaths = new int[20];
+    
+    String mDebugApp = null;
+    boolean mWaitForDebugger = false;
+    boolean mDebugTransient = false;
+    String mOrigDebugApp = null;
+    boolean mOrigWaitForDebugger = false;
+    boolean mAlwaysFinishActivities = false;
+    IActivityWatcher mWatcher = null;
+
+    /**
+     * Callback of last caller to {@link #requestPss}.
+     */
+    Runnable mRequestPssCallback;
+
+    /**
+     * Remaining processes for which we are waiting results from the last
+     * call to {@link #requestPss}.
+     */
+    final ArrayList<ProcessRecord> mRequestPssList
+            = new ArrayList<ProcessRecord>();
+    
+    /**
+     * Runtime statistics collection thread.  This object's lock is used to
+     * protect all related state.
+     */
+    final Thread mProcessStatsThread;
+    
+    /**
+     * Used to collect process stats when showing not responding dialog.
+     * Protected by mProcessStatsThread.
+     */
+    final ProcessStats mProcessStats = new ProcessStats(
+            MONITOR_THREAD_CPU_USAGE);
+    long mLastCpuTime = 0;
+    long mLastWriteTime = 0;
+
+    /**
+     * Set to true after the system has finished booting.
+     */
+    boolean mBooted = false;
+
+    int mProcessLimit = 0;
+
+    WindowManagerService mWindowManager;
+
+    static ActivityManagerService mSelf;
+    static ActivityThread mSystemThread;
+
+    private final class AppDeathRecipient implements IBinder.DeathRecipient {
+        final ProcessRecord mApp;
+        final int mPid;
+        final IApplicationThread mAppThread;
+
+        AppDeathRecipient(ProcessRecord app, int pid,
+                IApplicationThread thread) {
+            if (localLOGV) Log.v(
+                TAG, "New death recipient " + this
+                + " for thread " + thread.asBinder());
+            mApp = app;
+            mPid = pid;
+            mAppThread = thread;
+        }
+
+        public void binderDied() {
+            if (localLOGV) Log.v(
+                TAG, "Death received in " + this
+                + " for thread " + mAppThread.asBinder());
+            removeRequestedPss(mApp);
+            synchronized(ActivityManagerService.this) {
+                appDiedLocked(mApp, mPid, mAppThread);
+            }
+        }
+    }
+
+    static final int SHOW_ERROR_MSG = 1;
+    static final int SHOW_NOT_RESPONDING_MSG = 2;
+    static final int SHOW_FACTORY_ERROR_MSG = 3;
+    static final int UPDATE_CONFIGURATION_MSG = 4;
+    static final int GC_BACKGROUND_PROCESSES_MSG = 5;
+    static final int WAIT_FOR_DEBUGGER_MSG = 6;
+    static final int BROADCAST_INTENT_MSG = 7;
+    static final int BROADCAST_TIMEOUT_MSG = 8;
+    static final int PAUSE_TIMEOUT_MSG = 9;
+    static final int IDLE_TIMEOUT_MSG = 10;
+    static final int IDLE_NOW_MSG = 11;
+    static final int SERVICE_TIMEOUT_MSG = 12;
+    static final int UPDATE_TIME_ZONE = 13;
+    static final int SHOW_UID_ERROR_MSG = 14;
+    static final int IM_FEELING_LUCKY_MSG = 15;
+    static final int LAUNCH_TIMEOUT_MSG = 16;
+    static final int DESTROY_TIMEOUT_MSG = 17;
+    static final int SERVICE_ERROR_MSG = 18;
+    static final int RESUME_TOP_ACTIVITY_MSG = 19;
+    static final int PROC_START_TIMEOUT_MSG = 20;
+
+    AlertDialog mUidAlert;
+
+    final Handler mHandler = new Handler() {
+        //public Handler() {
+        //    if (localLOGV) Log.v(TAG, "Handler started!");
+        //}
+
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case SHOW_ERROR_MSG: {
+                HashMap data = (HashMap) msg.obj;
+                byte[] crashData = (byte[])data.get("crashData");
+                if (crashData != null) {
+                    // This needs to be *un*synchronized to avoid deadlock.
+                    ContentResolver resolver = mContext.getContentResolver();
+                    Checkin.reportCrash(resolver, crashData);
+                }
+                synchronized (ActivityManagerService.this) {
+                    ProcessRecord proc = (ProcessRecord)data.get("app");
+                    if (proc != null && proc.crashDialog != null) {
+                        Log.e(TAG, "App already has crash dialog: " + proc);
+                        return;
+                    }
+                    AppErrorResult res = (AppErrorResult) data.get("result");
+                    if (!mSleeping) {
+                        Dialog d = new AppErrorDialog(
+                                mContext, res, proc,
+                                (Integer)data.get("flags"),
+                                (String)data.get("shortMsg"),
+                                (String)data.get("longMsg"));
+                        d.show();
+                        proc.crashDialog = d;
+                    } else {
+                        // The device is asleep, so just pretend that the user
+                        // saw a crash dialog and hit "force quit".
+                        res.set(0);
+                    }
+                }
+            } break;
+            case SHOW_NOT_RESPONDING_MSG: {
+                synchronized (ActivityManagerService.this) {
+                    HashMap data = (HashMap) msg.obj;
+                    ProcessRecord proc = (ProcessRecord)data.get("app");
+                    if (proc != null && proc.anrDialog != null) {
+                        Log.e(TAG, "App already has anr dialog: " + proc);
+                        return;
+                    }
+                    Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
+                            mContext, proc, (HistoryRecord)data.get("activity"));
+                    d.show();
+                    proc.anrDialog = d;
+                }
+            } break;
+            case SHOW_FACTORY_ERROR_MSG: {
+                Dialog d = new FactoryErrorDialog(
+                    mContext, msg.getData().getCharSequence("msg"));
+                d.show();
+                enableScreenAfterBoot();
+            } break;
+            case UPDATE_CONFIGURATION_MSG: {
+                final ContentResolver resolver = mContext.getContentResolver();
+                Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
+            } break;
+            case GC_BACKGROUND_PROCESSES_MSG: {
+                synchronized (ActivityManagerService.this) {
+                    performAppGcsIfAppropriateLocked();
+                }
+            } break;
+            case WAIT_FOR_DEBUGGER_MSG: {
+                synchronized (ActivityManagerService.this) {
+                    ProcessRecord app = (ProcessRecord)msg.obj;
+                    if (msg.arg1 != 0) {
+                        if (!app.waitedForDebugger) {
+                            Dialog d = new AppWaitingForDebuggerDialog(
+                                    ActivityManagerService.this,
+                                    mContext, app);
+                            app.waitDialog = d;
+                            app.waitedForDebugger = true;
+                            d.show();
+                        }
+                    } else {
+                        if (app.waitDialog != null) {
+                            app.waitDialog.dismiss();
+                            app.waitDialog = null;
+                        }
+                    }
+                }
+            } break;
+            case BROADCAST_INTENT_MSG: {
+                if (DEBUG_BROADCAST) Log.v(
+                        TAG, "Received BROADCAST_INTENT_MSG");
+                processNextBroadcast(true);
+            } break;
+            case BROADCAST_TIMEOUT_MSG: {
+                broadcastTimeout();
+            } break;
+            case PAUSE_TIMEOUT_MSG: {
+                IBinder token = (IBinder)msg.obj;
+                // We don't at this point know if the activity is fullscreen,
+                // so we need to be conservative and assume it isn't.
+                Log.w(TAG, "Activity pause timeout for " + token);
+                activityPaused(token, null, true);
+            } break;
+            case IDLE_TIMEOUT_MSG: {
+                IBinder token = (IBinder)msg.obj;
+                // We don't at this point know if the activity is fullscreen,
+                // so we need to be conservative and assume it isn't.
+                Log.w(TAG, "Activity idle timeout for " + token);
+                activityIdleInternal(token, true);
+            } break;
+            case DESTROY_TIMEOUT_MSG: {
+                IBinder token = (IBinder)msg.obj;
+                // We don't at this point know if the activity is fullscreen,
+                // so we need to be conservative and assume it isn't.
+                Log.w(TAG, "Activity destroy timeout for " + token);
+                activityDestroyed(token);
+            } break;
+            case IDLE_NOW_MSG: {
+                IBinder token = (IBinder)msg.obj;
+                activityIdle(token);
+            } break;
+            case SERVICE_TIMEOUT_MSG: {
+                serviceTimeout((ProcessRecord)msg.obj);
+            } break;
+            case UPDATE_TIME_ZONE: {
+                synchronized (ActivityManagerService.this) {
+                    for (int i = mLRUProcesses.size() - 1 ; i >= 0 ; i--) {
+                        ProcessRecord r = mLRUProcesses.get(i);
+                        if (r.thread != null) {
+                            try {
+                                r.thread.updateTimeZone();
+                            } catch (RemoteException ex) {
+                                Log.w(TAG, "Failed to update time zone for: " + r.info.processName);
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+            case SHOW_UID_ERROR_MSG: {
+                // XXX This is a temporary dialog, no need to localize.
+                AlertDialog d = new BaseErrorDialog(mContext);
+                d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+                d.setCancelable(false);
+                d.setTitle("System UIDs Inconsistent");
+                d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
+                d.setButton("I'm Feeling Lucky",
+                        mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
+                mUidAlert = d;
+                d.show();
+            } break;
+            case IM_FEELING_LUCKY_MSG: {
+                if (mUidAlert != null) {
+                    mUidAlert.dismiss();
+                    mUidAlert = null;
+                }
+            } break;
+            case LAUNCH_TIMEOUT_MSG: {
+                synchronized (ActivityManagerService.this) {
+                    if (mLaunchingActivity.isHeld()) {
+                        Log.w(TAG, "Launch timeout has expired, giving up wake lock!");
+                        mLaunchingActivity.release();
+                    }
+                }
+            } break;
+            case SERVICE_ERROR_MSG: {
+                ServiceRecord srv = (ServiceRecord)msg.obj;
+                // This needs to be *un*synchronized to avoid deadlock.
+                Checkin.logEvent(mContext.getContentResolver(),
+                        Checkin.Events.Tag.SYSTEM_SERVICE_LOOPING,
+                        srv.name.toShortString());
+            } break;
+            case RESUME_TOP_ACTIVITY_MSG: {
+                synchronized (ActivityManagerService.this) {
+                    resumeTopActivityLocked(null);
+                }
+            }
+            case PROC_START_TIMEOUT_MSG: {
+                ProcessRecord app = (ProcessRecord)msg.obj;
+                synchronized (ActivityManagerService.this) {
+                    processStartTimedOutLocked(app);
+                }
+            }
+            }
+        }
+    };
+
+    public static void setSystemProcess() {
+        try {
+            ActivityManagerService m = mSelf;
+            
+            ServiceManager.addService("activity", m);
+            ServiceManager.addService("meminfo", new MemBinder(m));
+            if (MONITOR_CPU_USAGE) {
+                ServiceManager.addService("cpuinfo", new CpuBinder(m));
+            }
+            ServiceManager.addService("activity.broadcasts", new BroadcastsBinder(m));
+            ServiceManager.addService("activity.services", new ServicesBinder(m));
+            ServiceManager.addService("activity.senders", new SendersBinder(m));
+            ServiceManager.addService("activity.providers", new ProvidersBinder(m));
+            ServiceManager.addService("permission", new PermissionController(m));
+
+            ApplicationInfo info =
+                mSelf.mContext.getPackageManager().getApplicationInfo(
+                        "android", PackageManager.GET_SHARED_LIBRARY_FILES);
+            synchronized (mSelf) {
+                ProcessRecord app = mSelf.newProcessRecordLocked(
+                        mSystemThread.getApplicationThread(), info,
+                        info.processName);
+                app.persistent = true;
+                app.pid = Process.myPid();
+                app.maxAdj = SYSTEM_ADJ;
+                mSelf.mProcessNames.put(app.processName, app.info.uid, app);
+                synchronized (mSelf.mPidsSelfLocked) {
+                    mSelf.mPidsSelfLocked.put(app.pid, app);
+                }
+                mSelf.updateLRUListLocked(app, true);
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new RuntimeException(
+                    "Unable to find android system package", e);
+        }
+    }
+
+    public void setWindowManager(WindowManagerService wm) {
+        mWindowManager = wm;
+    }
+
+    public static final Context main(int factoryTest) {
+        AThread thr = new AThread();
+        thr.start();
+
+        synchronized (thr) {
+            while (thr.mService == null) {
+                try {
+                    thr.wait();
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+
+        ActivityManagerService m = thr.mService;
+        mSelf = m;
+        ActivityThread at = ActivityThread.systemMain();
+        mSystemThread = at;
+        Context context = at.getSystemContext();
+        m.mContext = context;
+        m.mFactoryTest = factoryTest;
+        PowerManager pm =
+            (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
+        m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
+        m.mLaunchingActivity.setReferenceCounted(false);
+        
+        m.mBatteryStatsService.publish(context);
+        m.mUsageStatsService.publish(context);
+        
+        synchronized (thr) {
+            thr.mReady = true;
+            thr.notifyAll();
+        }
+
+        m.startRunning(null, null, null, null);
+        
+        return context;
+    }
+
+    public static ActivityManagerService self() {
+        return mSelf;
+    }
+    
+    static class AThread extends Thread {
+        ActivityManagerService mService;
+        boolean mReady = false;
+
+        public AThread() {
+            super("ActivityManager");
+        }
+
+        public void run() {
+            Looper.prepare();
+
+            android.os.Process.setThreadPriority(
+                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
+
+            ActivityManagerService m = new ActivityManagerService();
+
+            synchronized (this) {
+                mService = m;
+                notifyAll();
+            }
+
+            synchronized (this) {
+                while (!mReady) {
+                    try {
+                        wait();
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+
+            Looper.loop();
+        }
+    }
+
+    static class BroadcastsBinder extends Binder {
+        ActivityManagerService mActivityManagerService;
+        BroadcastsBinder(ActivityManagerService activityManagerService) {
+            mActivityManagerService = activityManagerService;
+        }
+
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            mActivityManagerService.dumpBroadcasts(pw);
+        }
+    }
+
+    static class ServicesBinder extends Binder {
+        ActivityManagerService mActivityManagerService;
+        ServicesBinder(ActivityManagerService activityManagerService) {
+            mActivityManagerService = activityManagerService;
+        }
+
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            mActivityManagerService.dumpServices(pw);
+        }
+    }
+
+    static class SendersBinder extends Binder {
+        ActivityManagerService mActivityManagerService;
+        SendersBinder(ActivityManagerService activityManagerService) {
+            mActivityManagerService = activityManagerService;
+        }
+
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            mActivityManagerService.dumpSenders(pw);
+        }
+    }
+
+    static class ProvidersBinder extends Binder {
+        ActivityManagerService mActivityManagerService;
+        ProvidersBinder(ActivityManagerService activityManagerService) {
+            mActivityManagerService = activityManagerService;
+        }
+
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            mActivityManagerService.dumpProviders(pw);
+        }
+    }
+
+    static class MemBinder extends Binder {
+        ActivityManagerService mActivityManagerService;
+        MemBinder(ActivityManagerService activityManagerService) {
+            mActivityManagerService = activityManagerService;
+        }
+
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            ActivityManagerService service = mActivityManagerService;
+            ArrayList<ProcessRecord> procs;
+            synchronized (mActivityManagerService) {
+                if (args != null && args.length > 0
+                        && args[0].charAt(0) != '-') {
+                    procs = new ArrayList<ProcessRecord>();
+                    int pid = -1;
+                    try {
+                        pid = Integer.parseInt(args[0]);
+                    } catch (NumberFormatException e) {
+                        
+                    }
+                    for (int i=0; i<service.mLRUProcesses.size(); i++) {
+                        ProcessRecord proc = service.mLRUProcesses.get(i);
+                        if (proc.pid == pid) {
+                            procs.add(proc);
+                        } else if (proc.processName.equals(args[0])) {
+                            procs.add(proc);
+                        }
+                    }
+                    if (procs.size() <= 0) {
+                        pw.println("No process found for: " + args[0]);
+                        return;
+                    }
+                } else {
+                    procs = service.mLRUProcesses;
+                }
+            }
+            dumpApplicationMemoryUsage(fd, pw, procs, "  ", args);
+        }
+    }
+
+    static class CpuBinder extends Binder {
+        ActivityManagerService mActivityManagerService;
+        CpuBinder(ActivityManagerService activityManagerService) {
+            mActivityManagerService = activityManagerService;
+        }
+
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            synchronized (mActivityManagerService.mProcessStatsThread) {
+                pw.print(mActivityManagerService.mProcessStats.printCurrentState());
+            }
+        }
+    }
+
+    private ActivityManagerService() {
+        String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
+        if (v != null && Integer.getInteger(v) != 0) {
+            mSimpleProcessManagement = true;
+        }
+        v = System.getenv("ANDROID_DEBUG_APP");
+        if (v != null) {
+            mSimpleProcessManagement = true;
+        }
+
+        MY_PID = Process.myPid();
+        
+        File dataDir = Environment.getDataDirectory();
+        File systemDir = new File(dataDir, "system");
+        systemDir.mkdirs();
+        mBatteryStatsService = new BatteryStatsService(new File(
+                systemDir, "batterystats.bin").toString());
+        mBatteryStatsService.getActiveStatistics().readLocked();
+        mBatteryStatsService.getActiveStatistics().writeLocked();
+        
+        mUsageStatsService = new UsageStatsService( new File(
+                systemDir, "usagestats.bin").toString());
+
+        mConfiguration.makeDefault();
+        mProcessStats.init();
+        
+        // Add ourself to the Watchdog monitors.
+        Watchdog.getInstance().addMonitor(this);
+
+        // These values are set in system/rootdir/init.rc on startup.
+        FOREGROUND_APP_ADJ =
+            Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
+        VISIBLE_APP_ADJ =
+            Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
+        SECONDARY_SERVER_ADJ =
+            Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
+        HIDDEN_APP_MIN_ADJ =
+            Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
+        CONTENT_PROVIDER_ADJ =
+            Integer.valueOf(SystemProperties.get("ro.CONTENT_PROVIDER_ADJ"));
+        HIDDEN_APP_MAX_ADJ = CONTENT_PROVIDER_ADJ-1;
+        EMPTY_APP_ADJ =
+            Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
+        FOREGROUND_APP_MEM =
+            Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
+        VISIBLE_APP_MEM =
+            Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
+        SECONDARY_SERVER_MEM =
+            Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
+        HIDDEN_APP_MEM =
+            Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
+        EMPTY_APP_MEM =
+            Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
+
+        mProcessStatsThread = new Thread("ProcessStats") {
+            public void run() {
+                while (true) {
+                    try {
+                        try {
+                            synchronized(this) {
+                                final long now = SystemClock.uptimeMillis();
+                                long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
+                                long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
+                                //Log.i(TAG, "Cpu delay=" + nextCpuDelay
+                                //        + ", write delay=" + nextWriteDelay);
+                                if (nextWriteDelay < nextCpuDelay) {
+                                    nextCpuDelay = nextWriteDelay;
+                                }
+                                if (nextCpuDelay > 0) {
+                                    this.wait(nextCpuDelay);
+                                }
+                            }
+                        } catch (InterruptedException e) {
+                        }
+                        
+                        updateCpuStatsNow();
+                    } catch (Exception e) {
+                        Log.e(TAG, "Unexpected exception collecting process stats", e);
+                    }
+                }
+            }
+        };
+        mProcessStatsThread.start();
+    }
+
+    @Override
+    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+            throws RemoteException {
+        try {
+            return super.onTransact(code, data, reply, flags);
+        } catch (RuntimeException e) {
+            // The activity manager only throws security exceptions, so let's
+            // log all others.
+            if (!(e instanceof SecurityException)) {
+                Log.e(TAG, "Activity Manager Crash", e);
+            }
+            throw e;
+        }
+    }
+
+    void updateCpuStats() {
+        synchronized (mProcessStatsThread) {
+            final long now = SystemClock.uptimeMillis();
+            if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
+                mProcessStatsThread.notify();
+            }
+        }
+    }
+    
+    void updateCpuStatsNow() {
+        synchronized (mProcessStatsThread) {
+            final long now = SystemClock.uptimeMillis();
+            boolean haveNewCpuStats = false;
+            
+            if (MONITOR_CPU_USAGE &&
+                    mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
+                mLastCpuTime = now;
+                haveNewCpuStats = true;
+                mProcessStats.update();
+                //Log.i(TAG, mProcessStats.printCurrentState());
+                //Log.i(TAG, "Total CPU usage: "
+                //        + mProcessStats.getTotalCpuPercent() + "%");
+
+                // Log the cpu usage if the property is set.
+                if ("true".equals(SystemProperties.get("events.cpu"))) {
+                    int user = mProcessStats.getLastUserTime();
+                    int system = mProcessStats.getLastSystemTime();
+                    int iowait = mProcessStats.getLastIoWaitTime();
+                    int irq = mProcessStats.getLastIrqTime();
+                    int softIrq = mProcessStats.getLastSoftIrqTime();
+                    int idle = mProcessStats.getLastIdleTime();
+
+                    int total = user + system + iowait + irq + softIrq + idle;
+                    if (total == 0) total = 1;
+
+                    EventLog.writeEvent(LOG_CPU,
+                            ((user+system+iowait+irq+softIrq) * 100) / total,
+                            (user * 100) / total,
+                            (system * 100) / total,
+                            (iowait * 100) / total,
+                            (irq * 100) / total,
+                            (softIrq * 100) / total);
+                }
+            }
+            
+            synchronized(mBatteryStatsService.getActiveStatistics()) {
+                synchronized(mPidsSelfLocked) {
+                    if (haveNewCpuStats) {
+                        if (mBatteryStatsService.isOnBattery()) {
+                            final int N = mProcessStats.countWorkingStats();
+                            for (int i=0; i<N; i++) {
+                                ProcessStats.Stats st
+                                        = mProcessStats.getWorkingStats(i);
+                                ProcessRecord pr = mPidsSelfLocked.get(st.pid);
+                                if (pr != null) {
+                                    BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
+                                    ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
+                                }
+                            }
+                        }
+                    }
+                }
+        
+                if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
+                    mLastWriteTime = now;
+                    mBatteryStatsService.getActiveStatistics().writeLocked();
+                }
+            }
+        }
+    }
+    
+    /**
+     * Initialize the application bind args. These are passed to each
+     * process when the bindApplication() IPC is sent to the process. They're
+     * lazily setup to make sure the services are running when they're asked for.
+     */
+    private HashMap<String, IBinder> getCommonServicesLocked() {
+        if (mAppBindArgs == null) {
+            mAppBindArgs = new HashMap<String, IBinder>();
+
+            // Setup the application init args
+            mAppBindArgs.put("package", ServiceManager.getService("package"));
+            mAppBindArgs.put("window", ServiceManager.getService("window"));
+            mAppBindArgs.put(Context.ALARM_SERVICE,
+                    ServiceManager.getService(Context.ALARM_SERVICE));
+        }
+        return mAppBindArgs;
+    }
+
+    private final void setFocusedActivityLocked(HistoryRecord r) {
+        if (mFocusedActivity != r) {
+            mFocusedActivity = r;
+            mWindowManager.setFocusedApp(r, true);
+        }
+    }
+
+    private final void updateLRUListLocked(ProcessRecord app,
+            boolean oomAdj) {
+        // put it on the LRU to keep track of when it should be exited.
+        int lrui = mLRUProcesses.indexOf(app);
+        if (lrui >= 0) mLRUProcesses.remove(lrui);
+        mLRUProcesses.add(app);
+        //Log.i(TAG, "Putting proc to front: " + app.processName);
+        if (oomAdj) {
+            updateOomAdjLocked();
+        }
+    }
+
+    private final boolean updateLRUListLocked(HistoryRecord r) {
+        final boolean hadit = mLRUActivities.remove(r);
+        mLRUActivities.add(r);
+        return hadit;
+    }
+
+    private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
+        int i = mHistory.size()-1;
+        while (i >= 0) {
+            HistoryRecord r = (HistoryRecord)mHistory.get(i);
+            if (!r.finishing && r != notTop) {
+                return r;
+            }
+            i--;
+        }
+        return null;
+    }
+
+    /**
+     * This is a simplified version of topRunningActivityLocked that provides a number of
+     * optional skip-over modes.  It is intended for use with the ActivityWatcher hook only.
+     * 
+     * @param token If non-null, any history records matching this token will be skipped.
+     * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
+     * 
+     * @return Returns the HistoryRecord of the next activity on the stack.
+     */
+    private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
+        int i = mHistory.size()-1;
+        while (i >= 0) {
+            HistoryRecord r = (HistoryRecord)mHistory.get(i);
+            // Note: the taskId check depends on real taskId fields being non-zero
+            if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
+                return r;
+            }
+            i--;
+        }
+        return null;
+    }
+
+    private final ProcessRecord getProcessRecordLocked(
+            String processName, int uid) {
+        if (uid == Process.SYSTEM_UID) {
+            // The system gets to run in any process.  If there are multiple
+            // processes with the same uid, just pick the first (this
+            // should never happen).
+            SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
+                    processName);
+            return procs != null ? procs.valueAt(0) : null;
+        }
+        ProcessRecord proc = mProcessNames.get(processName, uid);
+        return proc;
+    }
+
+    private boolean isNextTransitionForward() {
+        int transit = mWindowManager.getPendingAppTransition();
+        return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
+                || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
+                || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
+    }
+    
+    private final boolean realStartActivityLocked(HistoryRecord r,
+            ProcessRecord app, boolean andResume, boolean checkConfig)
+            throws RemoteException {
+
+        r.startFreezingScreenLocked(app, 0);
+        mWindowManager.setAppVisibility(r, true);
+
+        // Have the window manager re-evaluate the orientation of
+        // the screen based on the new activity order.  Note that
+        // as a result of this, it can call back into the activity
+        // manager with a new orientation.  We don't care about that,
+        // because the activity is not currently running so we are
+        // just restarting it anyway.
+        if (checkConfig) {
+            Configuration config = mWindowManager.updateOrientationFromAppTokens(
+                    r.mayFreezeScreenLocked(app) ? r : null);
+            updateConfigurationLocked(config, r);
+        }
+
+        r.app = app;
+
+        if (localLOGV) Log.v(TAG, "Launching: " + r);
+
+        int idx = app.activities.indexOf(r);
+        if (idx < 0) {
+            app.activities.add(r);
+        }
+        updateLRUListLocked(app, true);
+
+        try {
+            if (app.thread == null) {
+                throw new RemoteException();
+            }
+            List<ResultInfo> results = null;
+            List<Intent> newIntents = null;
+            if (andResume) {
+                results = r.results;
+                newIntents = r.newIntents;
+            }
+            if (DEBUG_SWITCH) Log.v(TAG, "Launching: " + r
+                    + " icicle=" + r.icicle
+                    + " with results=" + results + " newIntents=" + newIntents
+                    + " andResume=" + andResume);
+            if (andResume) {
+                EventLog.writeEvent(LOG_AM_RESTART_ACTIVITY,
+                        System.identityHashCode(r),
+                        r.task.taskId, r.shortComponentName);
+            }
+            app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
+                    r.info, r.icicle, results, newIntents, !andResume,
+                    isNextTransitionForward());
+            // Update usage stats for launched activity
+            updateUsageStats(r, true);
+        } catch (RemoteException e) {
+            if (r.launchFailed) {
+                // This is the second time we failed -- finish activity
+                // and give up.
+                Log.e(TAG, "Second failure launching "
+                      + r.intent.getComponent().flattenToShortString()
+                      + ", giving up", e);
+                appDiedLocked(app, app.pid, app.thread);
+                requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
+                        "2nd-crash");
+                return false;
+            }
+
+            // This is the first time we failed -- restart process and
+            // retry.
+            app.activities.remove(r);
+            throw e;
+        }
+
+        r.launchFailed = false;
+        if (updateLRUListLocked(r)) {
+            Log.w(TAG, "Activity " + r
+                  + " being launched, but already in LRU list");
+        }
+
+        if (andResume) {
+            // As part of the process of launching, ActivityThread also performs
+            // a resume.
+            r.state = ActivityState.RESUMED;
+            r.icicle = null;
+            r.haveState = false;
+            r.stopped = false;
+            mResumedActivity = r;
+            r.task.touchActiveTime();
+            completeResumeLocked(r);
+            pauseIfSleepingLocked();                
+        } else {
+            // This activity is not starting in the resumed state... which
+            // should look like we asked it to pause+stop (but remain visible),
+            // and it has done so and reported back the current icicle and
+            // other state.
+            r.state = ActivityState.STOPPED;
+            r.stopped = true;
+        }
+
+        return true;
+    }
+
+    private final void startSpecificActivityLocked(HistoryRecord r,
+            boolean andResume, boolean checkConfig) {
+        // Is this activity's application already running?
+        ProcessRecord app = getProcessRecordLocked(r.processName,
+                r.info.applicationInfo.uid);
+        
+        if (r.startTime == 0) {
+            r.startTime = SystemClock.uptimeMillis();
+        }
+        
+        if (app != null && app.thread != null) {
+            try {
+                realStartActivityLocked(r, app, andResume, checkConfig);
+                return;
+            } catch (RemoteException e) {
+                Log.w(TAG, "Exception when starting activity "
+                        + r.intent.getComponent().flattenToShortString(), e);
+            }
+
+            // If a dead object exception was thrown -- fall through to
+            // restart the application.
+        }
+
+        startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
+                "activity", r.intent.getComponent());
+    }
+
+    private final ProcessRecord startProcessLocked(String processName,
+            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
+            String hostingType, ComponentName hostingName) {
+        ProcessRecord app = getProcessRecordLocked(processName, info.uid);
+        // We don't have to do anything more if:
+        // (1) There is an existing application record; and
+        // (2) The caller doesn't think it is dead, OR there is no thread
+        //     object attached to it so we know it couldn't have crashed; and
+        // (3) There is a pid assigned to it, so it is either starting or
+        //     already running.
+        if (DEBUG_PROCESSES) Log.v(TAG, "startProcess: name=" + processName
+                + " app=" + app + " knownToBeDead=" + knownToBeDead
+                + " thread=" + (app != null ? app.thread : null)
+                + " pid=" + (app != null ? app.pid : -1));
+        if (app != null &&
+                (!knownToBeDead || app.thread == null) && app.pid > 0) {
+            return app;
+        }
+        
+        String hostingNameStr = hostingName != null
+                ? hostingName.flattenToShortString() : null;
+        
+        if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
+            // If we are in the background, then check to see if this process
+            // is bad.  If so, we will just silently fail.
+            if (mBadProcesses.get(info.processName, info.uid) != null) {
+                return null;
+            }
+        } else {
+            // When the user is explicitly starting a process, then clear its
+            // crash count so that we won't make it bad until they see at
+            // least one crash dialog again, and make the process good again
+            // if it had been bad.
+            mProcessCrashTimes.remove(info.processName, info.uid);
+            if (mBadProcesses.get(info.processName, info.uid) != null) {
+                EventLog.writeEvent(LOG_AM_PROCESS_GOOD, info.uid,
+                        info.processName);
+                mBadProcesses.remove(info.processName, info.uid);
+                if (app != null) {
+                    app.bad = false;
+                }
+            }
+        }
+        
+        if (app == null) {
+            app = newProcessRecordLocked(null, info, processName);
+            mProcessNames.put(processName, info.uid, app);
+        } else {
+            // If this is a new package in the process, add the package to the list
+            app.addPackage(info.packageName);
+        }
+
+        // If the system is not ready yet, then hold off on starting this
+        // process until it is.
+        if (!mSystemReady
+                && (info.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
+            if (!mProcessesOnHold.contains(app)) {
+                mProcessesOnHold.add(app);
+            }
+            return app;
+        }
+
+        startProcessLocked(app, hostingType, hostingNameStr);
+        return (app.pid != 0) ? app : null;
+    }
+
+    private final void startProcessLocked(ProcessRecord app,
+            String hostingType, String hostingNameStr) {
+        if (app.pid > 0 && app.pid != MY_PID) {
+            synchronized (mPidsSelfLocked) {
+                mPidsSelfLocked.remove(app.pid);
+                mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
+            }
+            app.pid = 0;
+        }
+
+        mProcessesOnHold.remove(app);
+
+        updateCpuStats();
+        
+        System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
+        mProcDeaths[0] = 0;
+        
+        try {
+            int uid = app.info.uid;
+            int[] gids = null;
+            try {
+                gids = mContext.getPackageManager().getPackageGids(
+                        app.info.packageName);
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.w(TAG, "Unable to retrieve gids", e);
+            }
+            if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
+                if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
+                        && mTopComponent != null
+                        && app.processName.equals(mTopComponent.getPackageName())) {
+                    uid = 0;
+                }
+                if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
+                        && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
+                    uid = 0;
+                }
+            }
+            int debugFlags = 0;
+            if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+                debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
+            }
+            if ("1".equals(SystemProperties.get("debug.checkjni"))) {
+                debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
+            }
+            if ("1".equals(SystemProperties.get("debug.assert"))) {
+                debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
+            }
+            int pid = Process.start("android.app.ActivityThread",
+                    mSimpleProcessManagement ? app.processName : null, uid, uid,
+                    gids, debugFlags, null);
+            BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
+            synchronized (bs) {
+                if (bs.isOnBattery()) {
+                    app.batteryStats.incStartsLocked();
+                }
+            }
+            
+            EventLog.writeEvent(LOG_AM_PROCESS_START, pid, uid,
+                    app.processName, hostingType,
+                    hostingNameStr != null ? hostingNameStr : "");
+            
+            if (app.persistent) {
+                Watchdog.getInstance().processStarted(app, app.processName, pid);
+            }
+            
+            StringBuilder buf = new StringBuilder(128);
+            buf.append("Start proc ");
+            buf.append(app.processName);
+            buf.append(" for ");
+            buf.append(hostingType);
+            if (hostingNameStr != null) {
+                buf.append(" ");
+                buf.append(hostingNameStr);
+            }
+            buf.append(": pid=");
+            buf.append(pid);
+            buf.append(" uid=");
+            buf.append(uid);
+            buf.append(" gids={");
+            if (gids != null) {
+                for (int gi=0; gi<gids.length; gi++) {
+                    if (gi != 0) buf.append(", ");
+                    buf.append(gids[gi]);
+
+                }
+            }
+            buf.append("}");
+            Log.i(TAG, buf.toString());
+            if (pid == 0 || pid == MY_PID) {
+                // Processes are being emulated with threads.
+                app.pid = MY_PID;
+                app.removed = false;
+                mStartingProcesses.add(app);
+            } else if (pid > 0) {
+                app.pid = pid;
+                app.removed = false;
+                synchronized (mPidsSelfLocked) {
+                    this.mPidsSelfLocked.put(pid, app);
+                    Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
+                    msg.obj = app;
+                    mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
+                }
+            } else {
+                app.pid = 0;
+                RuntimeException e = new RuntimeException(
+                        "Failure starting process " + app.processName
+                        + ": returned pid=" + pid);
+                Log.e(TAG, e.getMessage(), e);
+            }
+        } catch (RuntimeException e) {
+            // XXX do better error recovery.
+            app.pid = 0;
+            Log.e(TAG, "Failure starting process " + app.processName, e);
+        }
+    }
+
+    private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
+        if (mPausingActivity != null) {
+            RuntimeException e = new RuntimeException();
+            Log.e(TAG, "Trying to pause when pause is already pending for "
+                  + mPausingActivity, e);
+        }
+        HistoryRecord prev = mResumedActivity;
+        if (prev == null) {
+            RuntimeException e = new RuntimeException();
+            Log.e(TAG, "Trying to pause when nothing is resumed", e);
+            resumeTopActivityLocked(null);
+            return;
+        }
+        if (DEBUG_PAUSE) Log.v(TAG, "Start pausing: " + prev);
+        mResumedActivity = null;
+        mPausingActivity = prev;
+        mLastPausedActivity = prev;
+        prev.state = ActivityState.PAUSING;
+        prev.task.touchActiveTime();
+
+        updateCpuStats();
+        
+        if (prev.app != null && prev.app.thread != null) {
+            if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending pause: " + prev);
+            try {
+                EventLog.writeEvent(LOG_AM_PAUSE_ACTIVITY,
+                        System.identityHashCode(prev),
+                        prev.shortComponentName);
+                prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
+                        prev.configChangeFlags);
+                updateUsageStats(prev, false);
+            } catch (Exception e) {
+                // Ignore exception, if process died other code will cleanup.
+                Log.w(TAG, "Exception thrown during pause", e);
+                mPausingActivity = null;
+                mLastPausedActivity = null;
+            }
+        } else {
+            mPausingActivity = null;
+            mLastPausedActivity = null;
+        }
+
+        // If we are not going to sleep, we want to ensure the device is
+        // awake until the next activity is started.
+        if (!mSleeping) {
+            mLaunchingActivity.acquire();
+            if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
+                // To be safe, don't allow the wake lock to be held for too long.
+                Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
+                mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
+            }
+        }
+
+
+        if (mPausingActivity != null) {
+            // Have the window manager pause its key dispatching until the new
+            // activity has started.  If we're pausing the activity just because
+            // the screen is being turned off and the UI is sleeping, don't interrupt
+            // key dispatch; the same activity will pick it up again on wakeup.
+            if (!uiSleeping) {
+                prev.pauseKeyDispatchingLocked();
+            } else {
+                if (DEBUG_PAUSE) Log.v(TAG, "Key dispatch not paused for screen off");
+            }
+
+            // Schedule a pause timeout in case the app doesn't respond.
+            // We don't give it much time because this directly impacts the
+            // responsiveness seen by the user.
+            Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
+            msg.obj = prev;
+            mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
+            if (DEBUG_PAUSE) Log.v(TAG, "Waiting for pause to complete...");
+        } else {
+            // This activity failed to schedule the
+            // pause, so just treat it as being paused now.
+            if (DEBUG_PAUSE) Log.v(TAG, "Activity not running, resuming next.");
+            resumeTopActivityLocked(null);
+        }
+    }
+
+    private final void completePauseLocked() {
+        HistoryRecord prev = mPausingActivity;
+        if (DEBUG_PAUSE) Log.v(TAG, "Complete pause: " + prev);
+        
+        if (prev != null) {
+            if (prev.finishing) {
+                if (DEBUG_PAUSE) Log.v(TAG, "Executing finish of activity: " + prev);
+                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
+            } else if (prev.app != null) {
+                if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending stop: " + prev);
+                if (prev.waitingVisible) {
+                    prev.waitingVisible = false;
+                    mWaitingVisibleActivities.remove(prev);
+                    if (DEBUG_SWITCH || DEBUG_PAUSE) Log.v(
+                            TAG, "Complete pause, no longer waiting: " + prev);
+                }
+                if (prev.configDestroy) {
+                    // The previous is being paused because the configuration
+                    // is changing, which means it is actually stopping...
+                    // To juggle the fact that we are also starting a new
+                    // instance right now, we need to first completely stop
+                    // the current instance before starting the new one.
+                    if (DEBUG_PAUSE) Log.v(TAG, "Destroying after pause: " + prev);
+                    destroyActivityLocked(prev, true);
+                } else {
+                    mStoppingActivities.add(prev);
+                    if (mStoppingActivities.size() > 3) {
+                        // If we already have a few activities waiting to stop,
+                        // then give up on things going idle and start clearing
+                        // them out.
+                        if (DEBUG_PAUSE) Log.v(TAG, "To many pending stops, forcing idle");
+                        Message msg = Message.obtain();
+                        msg.what = ActivityManagerService.IDLE_NOW_MSG;
+                        mHandler.sendMessage(msg);
+                    }
+                }
+            } else {
+                if (DEBUG_PAUSE) Log.v(TAG, "App died during pause, not stopping: " + prev);
+                prev = null;
+            }
+            mPausingActivity = null;
+        }
+
+        if (!mSleeping) {
+            resumeTopActivityLocked(prev);
+        } else {
+            if (mGoingToSleep.isHeld()) {
+                mGoingToSleep.release();
+            }
+        }
+        
+        if (prev != null) {
+            prev.resumeKeyDispatchingLocked();
+        }
+    }
+
+    /**
+     * Once we know that we have asked an application to put an activity in
+     * the resumed state (either by launching it or explicitly telling it),
+     * this function updates the rest of our state to match that fact.
+     */
+    private final void completeResumeLocked(HistoryRecord next) {
+        next.idle = false;
+        next.results = null;
+        next.newIntents = null;
+
+        // schedule an idle timeout in case the app doesn't do it for us.
+        Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
+        msg.obj = next;
+        mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
+
+        if (false) {
+            // The activity was never told to pause, so just keep
+            // things going as-is.  To maintain our own state,
+            // we need to emulate it coming back and saying it is
+            // idle.
+            msg = mHandler.obtainMessage(IDLE_NOW_MSG);
+            msg.obj = next;
+            mHandler.sendMessage(msg);
+        }
+
+        next.thumbnail = null;
+        setFocusedActivityLocked(next);
+        next.resumeKeyDispatchingLocked();
+        ensureActivitiesVisibleLocked(null, 0);
+        mWindowManager.executeAppTransition();
+    }
+
+    /**
+     * Make sure that all activities that need to be visible (that is, they
+     * currently can be seen by the user) actually are.
+     */
+    private final void ensureActivitiesVisibleLocked(HistoryRecord top,
+            HistoryRecord starting, String onlyThisProcess, int configChanges) {
+        if (DEBUG_VISBILITY) Log.v(
+                TAG, "ensureActivitiesVisible behind " + top
+                + " configChanges=0x" + Integer.toHexString(configChanges));
+
+        // If the top activity is not fullscreen, then we need to
+        // make sure any activities under it are now visible.
+        final int count = mHistory.size();
+        int i = count-1;
+        while (mHistory.get(i) != top) {
+            i--;
+        }
+        HistoryRecord r;
+        boolean behindFullscreen = false;
+        for (; i>=0; i--) {
+            r = (HistoryRecord)mHistory.get(i);
+            if (DEBUG_VISBILITY) Log.v(
+                    TAG, "Make visible? " + r + " finishing=" + r.finishing
+                    + " state=" + r.state);
+            if (r.finishing) {
+                continue;
+            }
+            
+            final boolean doThisProcess = onlyThisProcess == null
+                    || onlyThisProcess.equals(r.processName);
+            
+            // First: if this is not the current activity being started, make
+            // sure it matches the current configuration.
+            if (r != starting && doThisProcess) {
+                ensureActivityConfigurationLocked(r, 0);
+            }
+            
+            if (r.app == null || r.app.thread == null) {
+                if (onlyThisProcess == null
+                        || onlyThisProcess.equals(r.processName)) {
+                    // This activity needs to be visible, but isn't even
+                    // running...  get it started, but don't resume it
+                    // at this point.
+                    if (DEBUG_VISBILITY) Log.v(
+                            TAG, "Start and freeze screen for " + r);
+                    if (r != starting) {
+                        r.startFreezingScreenLocked(r.app, configChanges);
+                    }
+                    if (!r.visible) {
+                        if (DEBUG_VISBILITY) Log.v(
+                                TAG, "Starting and making visible: " + r);
+                        mWindowManager.setAppVisibility(r, true);
+                    }
+                    if (r != starting) {
+                        startSpecificActivityLocked(r, false, false);
+                    }
+                }
+
+            } else if (r.visible) {
+                // If this activity is already visible, then there is nothing
+                // else to do here.
+                if (DEBUG_VISBILITY) Log.v(
+                        TAG, "Skipping: already visible at " + r);
+                r.stopFreezingScreenLocked(false);
+
+            } else if (onlyThisProcess == null) {
+                // This activity is not currently visible, but is running.
+                // Tell it to become visible.
+                r.visible = true;
+                if (r.state != ActivityState.RESUMED && r != starting) {
+                    // If this activity is paused, tell it
+                    // to now show its window.
+                    if (DEBUG_VISBILITY) Log.v(
+                            TAG, "Making visible and scheduling visibility: " + r);
+                    try {
+                        mWindowManager.setAppVisibility(r, true);
+                        r.app.thread.scheduleWindowVisibility(r, true);
+                        r.stopFreezingScreenLocked(false);
+                    } catch (Exception e) {
+                        // Just skip on any failure; we'll make it
+                        // visible when it next restarts.
+                        Log.w(TAG, "Exception thrown making visibile: "
+                                + r.intent.getComponent(), e);
+                    }
+                }
+            }
+
+            // Aggregate current change flags.
+            configChanges |= r.configChangeFlags;
+
+            if (r.fullscreen) {
+                // At this point, nothing else needs to be shown
+                if (DEBUG_VISBILITY) Log.v(
+                        TAG, "Stopping: fullscreen at " + r);
+                behindFullscreen = true;
+                i--;
+                break;
+            }
+        }
+
+        // Now for any activities that aren't visible to the user, make
+        // sure they no longer are keeping the screen frozen.
+        while (i >= 0) {
+            r = (HistoryRecord)mHistory.get(i);
+            if (DEBUG_VISBILITY) Log.v(
+                    TAG, "Make invisible? " + r + " finishing=" + r.finishing
+                    + " state=" + r.state
+                    + " behindFullscreen=" + behindFullscreen);
+            if (!r.finishing) {
+                if (behindFullscreen) {
+                    if (r.visible) {
+                        if (DEBUG_VISBILITY) Log.v(
+                                TAG, "Making invisible: " + r);
+                        r.visible = false;
+                        try {
+                            mWindowManager.setAppVisibility(r, false);
+                            if ((r.state == ActivityState.STOPPING
+                                    || r.state == ActivityState.STOPPED)
+                                    && r.app != null && r.app.thread != null) {
+                                if (DEBUG_VISBILITY) Log.v(
+                                        TAG, "Scheduling invisibility: " + r);
+                                r.app.thread.scheduleWindowVisibility(r, false);
+                            }
+                        } catch (Exception e) {
+                            // Just skip on any failure; we'll make it
+                            // visible when it next restarts.
+                            Log.w(TAG, "Exception thrown making hidden: "
+                                    + r.intent.getComponent(), e);
+                        }
+                    } else {
+                        if (DEBUG_VISBILITY) Log.v(
+                                TAG, "Already invisible: " + r);
+                    }
+                } else if (r.fullscreen) {
+                    if (DEBUG_VISBILITY) Log.v(
+                            TAG, "Now behindFullscreen: " + r);
+                    behindFullscreen = true;
+                }
+            }
+            i--;
+        }
+    }
+
+    /**
+     * Version of ensureActivitiesVisible that can easily be called anywhere.
+     */
+    private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
+            int configChanges) {
+        HistoryRecord r = topRunningActivityLocked(null);
+        if (r != null) {
+            ensureActivitiesVisibleLocked(r, starting, null, configChanges);
+        }
+    }
+    
+    private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
+        if (resumed) {
+            mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
+        } else {
+            mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
+        }
+    }
+
+    /**
+     * Ensure that the top activity in the stack is resumed.
+     *
+     * @param prev The previously resumed activity, for when in the process
+     * of pausing; can be null to call from elsewhere.
+     *
+     * @return Returns true if something is being resumed, or false if
+     * nothing happened.
+     */
+    private final boolean resumeTopActivityLocked(HistoryRecord prev) {
+        // Find the first activity that is not finishing.
+        HistoryRecord next = topRunningActivityLocked(null);
+
+        // Remember how we'll process this pause/resume situation, and ensure
+        // that the state is reset however we wind up proceeding.
+        final boolean userLeaving = mUserLeaving;
+        mUserLeaving = false;
+
+        if (next == null) {
+            // There are no more activities!  Let's just start up the
+            // Launcher...
+            if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
+                    && mTopAction == null) {
+                // We are running in factory test mode, but unable to find
+                // the factory test app, so just sit around displaying the
+                // error message and don't try to start anything.
+                return false;
+            }
+            Intent intent = new Intent(
+                mTopAction,
+                mTopData != null ? Uri.parse(mTopData) : null);
+            intent.setComponent(mTopComponent);
+            if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+                intent.addCategory(Intent.CATEGORY_HOME);
+            }
+            ActivityInfo aInfo =
+                intent.resolveActivityInfo(mContext.getPackageManager(),
+                        PackageManager.GET_SHARED_LIBRARY_FILES);
+            if (aInfo != null) {
+                intent.setComponent(new ComponentName(
+                        aInfo.applicationInfo.packageName, aInfo.name));
+                // Don't do this if the home app is currently being
+                // instrumented.
+                ProcessRecord app = getProcessRecordLocked(aInfo.processName,
+                        aInfo.applicationInfo.uid);
+                if (app == null || app.instrumentationClass == null) {
+                    intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
+                    startActivityLocked(null, intent, null, null, 0, aInfo,
+                            null, null, 0, 0, 0, false);
+                }
+            }
+            return true;
+        }
+
+        // If the top activity is the resumed one, nothing to do.
+        if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
+            // Make sure we have executed any pending transitions, since there
+            // should be nothing left to do at this point.
+            mWindowManager.executeAppTransition();
+            return false;
+        }
+
+        // If we are sleeping, and there is no resumed activity, and the top
+        // activity is paused, well that is the state we want.
+        if (mSleeping && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
+            // Make sure we have executed any pending transitions, since there
+            // should be nothing left to do at this point.
+            mWindowManager.executeAppTransition();
+            return false;
+        }
+        
+        // The activity may be waiting for stop, but that is no longer
+        // appropriate for it.
+        mStoppingActivities.remove(next);
+        mWaitingVisibleActivities.remove(next);
+
+        if (DEBUG_SWITCH) Log.v(TAG, "Resuming " + next);
+
+        // If we are currently pausing an activity, then don't do anything
+        // until that is done.
+        if (mPausingActivity != null) {
+            if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: pausing=" + mPausingActivity);
+            return false;
+        }
+
+        // We need to start pausing the current activity so the top one
+        // can be resumed...
+        if (mResumedActivity != null) {
+            if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: need to start pausing");
+            startPausingLocked(userLeaving, false);
+            return true;
+        }
+
+        if (prev != null && prev != next) {
+            if (!prev.waitingVisible && next != null && !next.nowVisible) {
+                prev.waitingVisible = true;
+                mWaitingVisibleActivities.add(prev);
+                if (DEBUG_SWITCH) Log.v(
+                        TAG, "Resuming top, waiting visible to hide: " + prev);
+            } else {
+                // The next activity is already visible, so hide the previous
+                // activity's windows right now so we can show the new one ASAP.
+                // We only do this if the previous is finishing, which should mean
+                // it is on top of the one being resumed so hiding it quickly
+                // is good.  Otherwise, we want to do the normal route of allowing
+                // the resumed activity to be shown so we can decide if the
+                // previous should actually be hidden depending on whether the
+                // new one is found to be full-screen or not.
+                if (prev.finishing) {
+                    mWindowManager.setAppVisibility(prev, false);
+                    if (DEBUG_SWITCH) Log.v(TAG, "Not waiting for visible to hide: "
+                            + prev + ", waitingVisible="
+                            + (prev != null ? prev.waitingVisible : null)
+                            + ", nowVisible=" + next.nowVisible);
+                } else {
+                    if (DEBUG_SWITCH) Log.v(TAG, "Previous already visible but still waiting to hide: "
+                        + prev + ", waitingVisible="
+                        + (prev != null ? prev.waitingVisible : null)
+                        + ", nowVisible=" + next.nowVisible);
+                }
+            }
+        }
+
+        // We are starting up the next activity, so tell the window manager
+        // that the previous one will be hidden soon.  This way it can know
+        // to ignore it when computing the desired screen orientation.
+        if (prev != null) {
+            if (prev.finishing) {
+                if (DEBUG_TRANSITION) Log.v(TAG,
+                        "Prepare close transition: prev=" + prev);
+                mWindowManager.prepareAppTransition(prev.task == next.task
+                        ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
+                        : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
+                mWindowManager.setAppWillBeHidden(prev);
+                mWindowManager.setAppVisibility(prev, false);
+            } else {
+                if (DEBUG_TRANSITION) Log.v(TAG,
+                        "Prepare open transition: prev=" + prev);
+                mWindowManager.prepareAppTransition(prev.task == next.task
+                        ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
+                        : WindowManagerPolicy.TRANSIT_TASK_OPEN);
+            }
+            if (false) {
+                mWindowManager.setAppWillBeHidden(prev);
+                mWindowManager.setAppVisibility(prev, false);
+            }
+        } else if (mHistory.size() > 1) {
+            if (DEBUG_TRANSITION) Log.v(TAG,
+                    "Prepare open transition: no previous");
+            mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
+        }
+
+        if (next.app != null && next.app.thread != null) {
+            if (DEBUG_SWITCH) Log.v(TAG, "Resume running: " + next);
+
+            // This activity is now becoming visible.
+            mWindowManager.setAppVisibility(next, true);
+
+            HistoryRecord lastResumedActivity = mResumedActivity;
+            ActivityState lastState = next.state;
+
+            updateCpuStats();
+            
+            next.state = ActivityState.RESUMED;
+            mResumedActivity = next;
+            next.task.touchActiveTime();
+            updateLRUListLocked(next.app, true);
+            updateLRUListLocked(next);
+
+            // Have the window manager re-evaluate the orientation of
+            // the screen based on the new activity order.
+            Configuration config = mWindowManager.updateOrientationFromAppTokens(
+                    next.mayFreezeScreenLocked(next.app) ? next : null);
+            if (config != null) {
+                next.frozenBeforeDestroy = true;
+            }
+            if (!updateConfigurationLocked(config, next)) {
+                // The configuration update wasn't able to keep the existing
+                // instance of the activity, and instead started a new one.
+                // We should be all done, but let's just make sure our activity
+                // is still at the top and schedule another run if something
+                // weird happened.
+                HistoryRecord nextNext = topRunningActivityLocked(null);
+                if (DEBUG_SWITCH) Log.i(TAG,
+                        "Activity config changed during resume: " + next
+                        + ", new next: " + nextNext);
+                if (nextNext != next) {
+                    // Do over!
+                    mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
+                }
+                mWindowManager.executeAppTransition();
+                return true;
+            }
+            
+            try {
+                // Deliver all pending results.
+                ArrayList a = next.results;
+                if (a != null) {
+                    final int N = a.size();
+                    if (!next.finishing && N > 0) {
+                        if (localLOGV) Log.v(
+                                TAG, "Delivering results to " + next
+                                + ": " + a);
+                        next.app.thread.scheduleSendResult(next, a);
+                    }
+                }
+
+                if (next.newIntents != null) {
+                    next.app.thread.scheduleNewIntent(next.newIntents, next);
+                }
+
+                EventLog.writeEvent(LOG_AM_RESUME_ACTIVITY,
+                        System.identityHashCode(next),
+                        next.task.taskId, next.shortComponentName);
+                updateUsageStats(next, true);
+                
+                next.app.thread.scheduleResumeActivity(next,
+                        isNextTransitionForward());
+                pauseIfSleepingLocked();
+
+            } catch (Exception e) {
+                // Whoops, need to restart this activity!
+                next.state = lastState;
+                mResumedActivity = lastResumedActivity;
+                if (Config.LOGD) Log.d(TAG,
+                        "Restarting because process died: " + next);
+                if (!next.hasBeenLaunched) {
+                    next.hasBeenLaunched = true;
+                } else {
+                    if (SHOW_APP_STARTING_ICON) {
+                        mWindowManager.setAppStartingWindow(
+                                next, next.packageName, next.theme,
+                                next.nonLocalizedLabel,
+                                next.labelRes, next.icon, null, true);
+                    }
+                }
+                startSpecificActivityLocked(next, true, false);
+                return true;
+            }
+
+            // From this point on, if something goes wrong there is no way
+            // to recover the activity.
+            try {
+                next.visible = true;
+                completeResumeLocked(next);
+            } catch (Exception e) {
+                // If any exception gets thrown, toss away this
+                // activity and try the next one.
+                Log.w(TAG, "Exception thrown during resume of " + next, e);
+                requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
+                        "resume-exception");
+                return true;
+            }
+
+            // Didn't need to use the icicle, and it is now out of date.
+            next.icicle = null;
+            next.haveState = false;
+            next.stopped = false;
+
+        } else {
+            // Whoops, need to restart this activity!
+            if (!next.hasBeenLaunched) {
+                next.hasBeenLaunched = true;
+            } else {
+                if (SHOW_APP_STARTING_ICON) {
+                    mWindowManager.setAppStartingWindow(
+                            next, next.packageName, next.theme,
+                            next.nonLocalizedLabel,
+                            next.labelRes, next.icon, null, true);
+                }
+                if (DEBUG_SWITCH) Log.v(TAG, "Restarting: " + next);
+            }
+            startSpecificActivityLocked(next, true, true);
+        }
+
+        return true;
+    }
+
+    private final void startActivityLocked(HistoryRecord r, boolean newTask) {
+        final int NH = mHistory.size();
+
+        int addPos = -1;
+        
+        if (!newTask) {
+            // If starting in an existing task, find where that is...
+            HistoryRecord next = null;
+            boolean startIt = true;
+            for (int i = NH-1; i >= 0; i--) {
+                HistoryRecord p = (HistoryRecord)mHistory.get(i);
+                if (p.finishing) {
+                    continue;
+                }
+                if (p.task == r.task) {
+                    // Here it is!  Now, if this is not yet visible to the
+                    // user, then just add it without starting; it will
+                    // get started when the user navigates back to it.
+                    addPos = i+1;
+                    if (!startIt) {
+                        mHistory.add(addPos, r);
+                        r.inHistory = true;
+                        r.task.numActivities++;
+                        mWindowManager.addAppToken(addPos, r, r.task.taskId,
+                                r.info.screenOrientation, r.fullscreen);
+                        if (VALIDATE_TOKENS) {
+                            mWindowManager.validateAppTokens(mHistory);
+                        }
+                        return;
+                    }
+                    break;
+                }
+                if (p.fullscreen) {
+                    startIt = false;
+                }
+                next = p;
+            }
+        }
+
+        // Place a new activity at top of stack, so it is next to interact
+        // with the user.
+        if (addPos < 0) {
+            addPos = mHistory.size();
+        }
+        
+        // If we are not placing the new activity frontmost, we do not want
+        // to deliver the onUserLeaving callback to the actual frontmost
+        // activity
+        if (addPos < NH) {
+            mUserLeaving = false;
+            if (DEBUG_USER_LEAVING) Log.v(TAG, "startActivity() behind front, mUserLeaving=false");
+        }
+        
+        // Slot the activity into the history stack and proceed
+        mHistory.add(addPos, r);
+        r.inHistory = true;
+        r.frontOfTask = newTask;
+        r.task.numActivities++;
+        if (NH > 0) {
+            // We want to show the starting preview window if we are
+            // switching to a new task, or the next activity's process is
+            // not currently running.
+            boolean showStartingIcon = newTask;
+            ProcessRecord proc = r.app;
+            if (proc == null) {
+                proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
+            }
+            if (proc == null || proc.thread == null) {
+                showStartingIcon = true;
+            }
+            if (DEBUG_TRANSITION) Log.v(TAG,
+                    "Prepare open transition: starting " + r);
+            mWindowManager.prepareAppTransition(newTask
+                    ? WindowManagerPolicy.TRANSIT_TASK_OPEN
+                    : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
+            mWindowManager.addAppToken(
+                    addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
+            boolean doShow = true;
+            if (newTask) {
+                // Even though this activity is starting fresh, we still need
+                // to reset it to make sure we apply affinities to move any
+                // existing activities from other tasks in to it.
+                // If the caller has requested that the target task be
+                // reset, then do so.
+                if ((r.intent.getFlags()
+                        &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
+                    resetTaskIfNeededLocked(r, r);
+                    doShow = topRunningActivityLocked(null) == r;
+                }
+            }
+            if (SHOW_APP_STARTING_ICON && doShow) {
+                // Figure out if we are transitioning from another activity that is
+                // "has the same starting icon" as the next one.  This allows the
+                // window manager to keep the previous window it had previously
+                // created, if it still had one.
+                HistoryRecord prev = mResumedActivity;
+                if (prev != null) {
+                    // We don't want to reuse the previous starting preview if:
+                    // (1) The current activity is in a different task.
+                    if (prev.task != r.task) prev = null;
+                    // (2) The current activity is already displayed.
+                    else if (prev.nowVisible) prev = null;
+                }
+                mWindowManager.setAppStartingWindow(
+                        r, r.packageName, r.theme, r.nonLocalizedLabel,
+                        r.labelRes, r.icon, prev, showStartingIcon);
+            }
+        } else {
+            // If this is the first activity, don't do any fancy animations,
+            // because there is nothing for it to animate on top of.
+            mWindowManager.addAppToken(addPos, r, r.task.taskId,
+                    r.info.screenOrientation, r.fullscreen);
+        }
+        if (VALIDATE_TOKENS) {
+            mWindowManager.validateAppTokens(mHistory);
+        }
+
+        resumeTopActivityLocked(null);
+    }
+
+    /**
+     * Perform clear operation as requested by
+     * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: assuming the top task on the
+     * stack is the one that the new activity is being launched in, look for
+     * an instance of that activity in the stack and, if found, finish all
+     * activities on top of it and return the instance.
+     *
+     * @param newR Description of the new activity being started.
+     * @return Returns the old activity that should be continue to be used,
+     * or null if none was found.
+     */
+    private final HistoryRecord performClearTopTaskLocked(int taskId,
+            HistoryRecord newR, boolean doClear) {
+        int i = mHistory.size();
+        while (i > 0) {
+            i--;
+            HistoryRecord r = (HistoryRecord)mHistory.get(i);
+            if (r.finishing) {
+                continue;
+            }
+            if (r.task.taskId != taskId) {
+                return null;
+            }
+            if (r.realActivity.equals(newR.realActivity)) {
+                // Here it is!  Now finish everything in front...
+                HistoryRecord ret = r;
+                if (doClear) {
+                    while (i < (mHistory.size()-1)) {
+                        i++;
+                        r = (HistoryRecord)mHistory.get(i);
+                        if (r.finishing) {
+                            continue;
+                        }
+                        if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
+                                null, "clear")) {
+                            i--;
+                        }
+                    }
+                }
+                
+                // Finally, if this is a normal launch mode (that is, not
+                // expecting onNewIntent()), then we will finish the current
+                // instance of the activity so a new fresh one can be started.
+                if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE) {
+                    if (!ret.finishing) {
+                        int index = indexOfTokenLocked(ret, false);
+                        if (index >= 0) {
+                            finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
+                                    null, "clear");
+                        }
+                        return null;
+                    }
+                }
+                
+                return ret;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Find the activity in the history stack within the given task.  Returns
+     * the index within the history at which it's found, or < 0 if not found.
+     */
+    private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
+        int i = mHistory.size();
+        while (i > 0) {
+            i--;
+            HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
+            if (candidate.task.taskId != task) {
+                break;
+            }
+            if (candidate.realActivity.equals(r.realActivity)) {
+                return i;
+            }
+        }
+
+        return -1;
+    }
+
+    /**
+     * Reorder the history stack so that the activity at the given index is
+     * brought to the front.
+     */
+    private final HistoryRecord moveActivityToFrontLocked(int where) {
+        HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
+        int top = mHistory.size();
+        HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
+        mHistory.add(top, newTop);
+        oldTop.frontOfTask = false;
+        newTop.frontOfTask = true;
+        return newTop;
+    }
+
+    /**
+     * Deliver a new Intent to an existing activity, so that its onNewIntent()
+     * method will be called at the proper time.
+     */
+    private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
+        boolean sent = false;
+        if (r.state == ActivityState.RESUMED
+                && r.app != null && r.app.thread != null) {
+            try {
+                ArrayList<Intent> ar = new ArrayList<Intent>();
+                ar.add(new Intent(intent));
+                r.app.thread.scheduleNewIntent(ar, r);
+                sent = true;
+            } catch (Exception e) {
+                Log.w(TAG, "Exception thrown sending new intent to " + r, e);
+            }
+        }
+        if (!sent) {
+            r.addNewIntentLocked(new Intent(intent));
+        }
+    }
+
+    private final void logStartActivity(int tag, HistoryRecord r,
+            TaskRecord task) {
+        EventLog.writeEvent(tag,
+                System.identityHashCode(r), task.taskId,
+                r.shortComponentName, r.intent.getAction(),
+                r.intent.getType(), r.intent.getDataString(),
+                r.intent.getFlags());
+    }
+
+    private final int startActivityLocked(IApplicationThread caller,
+            Intent intent, String resolvedType,
+            Uri[] grantedUriPermissions,
+            int grantedMode, ActivityInfo aInfo, IBinder resultTo,
+            String resultWho, int requestCode,
+            int callingPid, int callingUid, boolean onlyIfNeeded) {
+        Log.i(TAG, "Starting activity: " + intent);
+
+        HistoryRecord sourceRecord = null;
+        HistoryRecord resultRecord = null;
+        if (resultTo != null) {
+            int index = indexOfTokenLocked(resultTo, false);
+            if (localLOGV) Log.v(
+                TAG, "Sending result to " + resultTo + " (index " + index + ")");
+            if (index >= 0) {
+                sourceRecord = (HistoryRecord)mHistory.get(index);
+                if (requestCode >= 0 && !sourceRecord.finishing) {
+                    resultRecord = sourceRecord;
+                }
+            }
+        }
+
+        int launchFlags = intent.getFlags();
+
+        if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
+                && sourceRecord != null) {
+            // Transfer the result target from the source activity to the new
+            // one being started, including any failures.
+            if (requestCode >= 0) {
+                return START_FORWARD_AND_REQUEST_CONFLICT;
+            }
+            resultRecord = sourceRecord.resultTo;
+            resultWho = sourceRecord.resultWho;
+            requestCode = sourceRecord.requestCode;
+            sourceRecord.resultTo = null;
+            if (resultRecord != null) {
+                resultRecord.removeResultsLocked(
+                    sourceRecord, resultWho, requestCode);
+            }
+        }
+
+        int err = START_SUCCESS;
+
+        if (intent.getComponent() == null) {
+            // We couldn't find a class that can handle the given Intent.
+            // That's the end of that!
+            err = START_INTENT_NOT_RESOLVED;
+        }
+
+        if (err == START_SUCCESS && aInfo == null) {
+            // We couldn't find the specific class specified in the Intent.
+            // Also the end of the line.
+            err = START_CLASS_NOT_FOUND;
+        }
+
+        ProcessRecord callerApp = null;
+        if (err == START_SUCCESS && caller != null) {
+            callerApp = getRecordForAppLocked(caller);
+            if (callerApp != null) {
+                callingPid = callerApp.pid;
+                callingUid = callerApp.info.uid;
+            } else {
+                Log.w(TAG, "Unable to find app for caller " + caller
+                      + " (pid=" + callingPid + ") when starting: "
+                      + intent.toString());
+                err = START_PERMISSION_DENIED;
+            }
+        }
+
+        if (err != START_SUCCESS) {
+            if (resultRecord != null) {
+                sendActivityResultLocked(-1,
+                    resultRecord, resultWho, requestCode,
+                    Activity.RESULT_CANCELED, null);
+            }
+            return err;
+        }
+
+        final int perm = checkComponentPermission(aInfo.permission, callingPid,
+                callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
+        if (perm != PackageManager.PERMISSION_GRANTED) {
+            if (resultRecord != null) {
+                sendActivityResultLocked(-1,
+                    resultRecord, resultWho, requestCode,
+                    Activity.RESULT_CANCELED, null);
+            }
+            String msg = "Permission Denial: starting " + intent.toString()
+                    + " from " + callerApp + " (pid=" + callingPid
+                    + ", uid=" + callingUid + ")"
+                    + " requires " + aInfo.permission;
+            Log.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+
+        if (mWatcher != null) {
+            boolean abort = false;
+            try {
+                // The Intent we give to the watcher has the extra data
+                // stripped off, since it can contain private information.
+                Intent watchIntent = intent.cloneFilter();
+                abort = !mWatcher.activityStarting(watchIntent,
+                        aInfo.applicationInfo.packageName);
+            } catch (RemoteException e) {
+                mWatcher = null;
+            }
+
+            if (abort) {
+                if (resultRecord != null) {
+                    sendActivityResultLocked(-1,
+                        resultRecord, resultWho, requestCode,
+                        Activity.RESULT_CANCELED, null);
+                }
+                // We pretend to the caller that it was really started, but
+                // they will just get a cancel result.
+                return START_SUCCESS;
+            }
+        }
+
+        HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
+                intent, resolvedType, aInfo, mConfiguration,
+                resultRecord, resultWho, requestCode);
+        r.startTime = SystemClock.uptimeMillis();
+
+        HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
+                != 0 ? r : null;
+
+        // We'll invoke onUserLeaving before onPause only if the launching
+        // activity did not explicitly state that this is an automated launch.
+        mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
+        if (DEBUG_USER_LEAVING) Log.v(TAG,
+                "startActivity() => mUserLeaving=" + mUserLeaving);
+        
+        // If the onlyIfNeeded flag is set, then we can do this if the activity
+        // being launched is the same as the one making the call...  or, as
+        // a special case, if we do not know the caller then we count the
+        // current top activity as the caller.
+        if (onlyIfNeeded) {
+            HistoryRecord checkedCaller = sourceRecord;
+            if (checkedCaller == null) {
+                checkedCaller = topRunningActivityLocked(notTop);
+            }
+            if (!checkedCaller.realActivity.equals(r.realActivity)) {
+                // Caller is not the same as launcher, so always needed.
+                onlyIfNeeded = false;
+            }
+        }
+
+        if (grantedUriPermissions != null && callingUid > 0) {
+            for (int i=0; i<grantedUriPermissions.length; i++) {
+                grantUriPermissionLocked(callingUid, r.packageName,
+                        grantedUriPermissions[i], grantedMode, r);
+            }
+        }
+
+        grantUriPermissionFromIntentLocked(callingUid, r.packageName,
+                intent, r);
+
+        if (sourceRecord == null) {
+            // This activity is not being started from another...  in this
+            // case we -always- start a new task.
+            if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
+                Log.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
+                      + intent);
+                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+            }
+        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
+            // The original activity who is starting us is running as a single
+            // instance...  this new activity it is starting must go on its
+            // own task.
+            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+        } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
+                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
+            // The activity being started is a single instance...  it always
+            // gets launched into its own task.
+            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+        }
+
+        if (resultRecord != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+            // For whatever reason this activity is being launched into a new
+            // task...  yet the caller has requested a result back.  Well, that
+            // is pretty messed up, so instead immediately send back a cancel
+            // and let the new task continue launched as normal without a
+            // dependency on its originator.
+            Log.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
+            sendActivityResultLocked(-1,
+                resultRecord, resultWho, requestCode,
+                Activity.RESULT_CANCELED, null);
+            r.resultTo = null;
+            resultRecord = null;
+        }
+
+        boolean addingToTask = false;
+        if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
+                (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
+                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
+                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
+            // If bring to front is requested, and no result is requested, and
+            // we can find a task that was started with this same
+            // component, then instead of launching bring that one to the front.
+            if (resultRecord == null) {
+                // See if there is a task to bring to the front.  If this is
+                // a SINGLE_INSTANCE activity, there can be one and only one
+                // instance of it in the history, and it is always in its own
+                // unique task, so we do a special search.
+                HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
+                        ? findTaskLocked(intent, r.info)
+                        : findActivityLocked(intent, r.info);
+                if (taskTop != null) {
+                    if (taskTop.task.intent == null) {
+                        // This task was started because of movement of
+                        // the activity based on affinity...  now that we
+                        // are actually launching it, we can assign the
+                        // base intent.
+                        taskTop.task.setIntent(intent, r.info);
+                    }
+                    // If the target task is not in the front, then we need
+                    // to bring it to the front...  except...  well, with
+                    // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
+                    // to have the same behavior as if a new instance was
+                    // being started, which means not bringing it to the front
+                    // if the caller is not itself in the front.
+                    HistoryRecord curTop = topRunningActivityLocked(notTop);
+                    if (curTop.task != taskTop.task) {
+                        r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
+                        boolean callerAtFront = sourceRecord == null
+                                || curTop.task == sourceRecord.task;
+                        if (callerAtFront) {
+                            // We really do want to push this one into the
+                            // user's face, right now.
+                            moveTaskToFrontLocked(taskTop.task);
+                        }
+                    }
+                    // If the caller has requested that the target task be
+                    // reset, then do so.
+                    if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
+                        taskTop = resetTaskIfNeededLocked(taskTop, r);
+                    }
+                    if (onlyIfNeeded) {
+                        // We don't need to start a new activity, and
+                        // the client said not to do anything if that
+                        // is the case, so this is it!  And for paranoia, make
+                        // sure we have correctly resumed the top activity.
+                        resumeTopActivityLocked(null);
+                        return START_RETURN_INTENT_TO_CALLER;
+                    }
+                    if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
+                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
+                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
+                        // In this situation we want to remove all activities
+                        // from the task up to the one being started.  In most
+                        // cases this means we are resetting the task to its
+                        // initial state.
+                        HistoryRecord top = performClearTopTaskLocked(
+                                taskTop.task.taskId, r, true);
+                        if (top != null) {
+                            if (top.frontOfTask) {
+                                // Activity aliases may mean we use different
+                                // intents for the top activity, so make sure
+                                // the task now has the identity of the new
+                                // intent.
+                                top.task.setIntent(r.intent, r.info);
+                            }
+                            logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
+                            deliverNewIntentLocked(top, r.intent);
+                        } else {
+                            // A special case: we need to
+                            // start the activity because it is not currently
+                            // running, and the caller has asked to clear the
+                            // current task to have this activity at the top.
+                            addingToTask = true;
+                            // Now pretend like this activity is being started
+                            // by the top of its task, so it is put in the
+                            // right place.
+                            sourceRecord = taskTop;
+                        }
+                    } else if (r.realActivity.equals(taskTop.task.realActivity)) {
+                        // In this case the top activity on the task is the
+                        // same as the one being launched, so we take that
+                        // as a request to bring the task to the foreground.
+                        // If the top activity in the task is the root
+                        // activity, deliver this new intent to it if it
+                        // desires.
+                        if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
+                                && taskTop.realActivity.equals(r.realActivity)) {
+                            logStartActivity(LOG_AM_NEW_INTENT, r, taskTop.task);
+                            if (taskTop.frontOfTask) {
+                                taskTop.task.setIntent(r.intent, r.info);
+                            }
+                            deliverNewIntentLocked(taskTop, r.intent);
+                        } else if (!r.intent.filterEquals(taskTop.task.intent)) {
+                            // In this case we are launching the root activity
+                            // of the task, but with a different intent.  We
+                            // should start a new instance on top.
+                            addingToTask = true;
+                            sourceRecord = taskTop;
+                        }
+                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
+                        // In this case an activity is being launched in to an
+                        // existing task, without resetting that task.  This
+                        // is typically the situation of launching an activity
+                        // from a notification or shortcut.  We want to place
+                        // the new activity on top of the current task.
+                        addingToTask = true;
+                        sourceRecord = taskTop;
+                    } else if (!taskTop.task.rootWasReset) {
+                        // In this case we are launching in to an existing task
+                        // that has not yet been started from its front door.
+                        // The current task has been brought to the front.
+                        // Ideally, we'd probably like to place this new task
+                        // at the bottom of its stack, but that's a little hard
+                        // to do with the current organization of the code so
+                        // for now we'll just drop it.
+                        taskTop.task.setIntent(r.intent, r.info);
+                    }
+                    if (!addingToTask) {
+                        // We didn't do anything...  but it was needed (a.k.a., client
+                        // don't use that intent!)  And for paranoia, make
+                        // sure we have correctly resumed the top activity.
+                        resumeTopActivityLocked(null);
+                        return START_TASK_TO_FRONT;
+                    }
+                }
+            }
+        }
+
+        //String uri = r.intent.toURI();
+        //Intent intent2 = new Intent(uri);
+        //Log.i(TAG, "Given intent: " + r.intent);
+        //Log.i(TAG, "URI is: " + uri);
+        //Log.i(TAG, "To intent: " + intent2);
+
+        if (r.packageName != null) {
+            // If the activity being launched is the same as the one currently
+            // at the top, then we need to check if it should only be launched
+            // once.
+            HistoryRecord top = topRunningActivityLocked(notTop);
+            if (top != null && resultRecord == null) {
+                if (top.realActivity.equals(r.realActivity)) {
+                    if (top.app != null && top.app.thread != null) {
+                        if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
+                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
+                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
+                            logStartActivity(LOG_AM_NEW_INTENT, top, top.task);
+                            // For paranoia, make sure we have correctly
+                            // resumed the top activity.
+                            resumeTopActivityLocked(null);
+                            if (onlyIfNeeded) {
+                                // We don't need to start a new activity, and
+                                // the client said not to do anything if that
+                                // is the case, so this is it!
+                                return START_RETURN_INTENT_TO_CALLER;
+                            }
+                            deliverNewIntentLocked(top, r.intent);
+                            return START_DELIVERED_TO_TOP;
+                        }
+                    }
+                }
+            }
+
+        } else {
+            if (resultRecord != null) {
+                sendActivityResultLocked(-1,
+                    resultRecord, resultWho, requestCode,
+                    Activity.RESULT_CANCELED, null);
+            }
+            return START_CLASS_NOT_FOUND;
+        }
+
+        boolean newTask = false;
+
+        // Should this be considered a new task?
+        if (resultRecord == null && !addingToTask
+                && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+            // todo: should do better management of integers.
+            mCurTask++;
+            if (mCurTask <= 0) {
+                mCurTask = 1;
+            }
+            r.task = new TaskRecord(mCurTask, r.info, intent,
+                    (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
+            if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
+                    + " in new task " + r.task);
+            newTask = true;
+            addRecentTask(r.task);
+            
+        } else if (sourceRecord != null) {
+            if (!addingToTask &&
+                    (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
+                // In this case, we are adding the activity to an existing
+                // task, but the caller has asked to clear that task if the
+                // activity is already running.
+                HistoryRecord top = performClearTopTaskLocked(
+                        sourceRecord.task.taskId, r, true);
+                if (top != null) {
+                    logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
+                    deliverNewIntentLocked(top, r.intent);
+                    // For paranoia, make sure we have correctly
+                    // resumed the top activity.
+                    resumeTopActivityLocked(null);
+                    return START_DELIVERED_TO_TOP;
+                }
+            } else if (!addingToTask &&
+                    (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
+                // In this case, we are launching an activity in our own task
+                // that may already be running somewhere in the history, and
+                // we want to shuffle it to the front of the stack if so.
+                int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
+                if (where >= 0) {
+                    HistoryRecord top = moveActivityToFrontLocked(where);
+                    logStartActivity(LOG_AM_NEW_INTENT, r, top.task);
+                    deliverNewIntentLocked(top, r.intent);
+                    resumeTopActivityLocked(null);
+                    return START_DELIVERED_TO_TOP;
+                }
+            }
+            // An existing activity is starting this new activity, so we want
+            // to keep the new one in the same task as the one that is starting
+            // it.
+            r.task = sourceRecord.task;
+            if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
+                    + " in existing task " + r.task);
+
+        } else {
+            // This not being started from an existing activity, and not part
+            // of a new task...  just put it in the top task, though these days
+            // this case should never happen.
+            final int N = mHistory.size();
+            HistoryRecord prev =
+                N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
+            r.task = prev != null
+                ? prev.task
+                : new TaskRecord(mCurTask, r.info, intent,
+                        (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
+            if (DEBUG_TASKS) Log.v(TAG, "Starting new activity " + r
+                    + " in new guessed " + r.task);
+        }
+        if (newTask) {
+            EventLog.writeEvent(LOG_AM_CREATE_TASK, r.task.taskId);
+        }
+        logStartActivity(LOG_AM_CREATE_ACTIVITY, r, r.task);
+        startActivityLocked(r, newTask);
+        return START_SUCCESS;
+    }
+
+    public final int startActivity(IApplicationThread caller,
+            Intent intent, String resolvedType, Uri[] grantedUriPermissions,
+            int grantedMode, IBinder resultTo,
+            String resultWho, int requestCode, boolean onlyIfNeeded,
+            boolean debug) {
+        // Refuse possible leaked file descriptors
+        if (intent != null && intent.hasFileDescriptors()) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        // Don't modify the client's object!
+        intent = new Intent(intent);
+
+        // Collect information about the target of the Intent.
+        // Must do this before locking, because resolving the intent
+        // may require launching a process to run its content provider.
+        ActivityInfo aInfo;
+        try {
+            ResolveInfo rInfo =
+                ActivityThread.getPackageManager().resolveIntent(
+                        intent, resolvedType,
+                        PackageManager.MATCH_DEFAULT_ONLY
+                        | PackageManager.GET_SHARED_LIBRARY_FILES);
+            aInfo = rInfo != null ? rInfo.activityInfo : null;
+        } catch (RemoteException e) {
+            aInfo = null;
+        }
+
+        if (aInfo != null) {
+            // Store the found target back into the intent, because now that
+            // we have it we never want to do this again.  For example, if the
+            // user navigates back to this point in the history, we should
+            // always restart the exact same activity.
+            intent.setComponent(new ComponentName(
+                    aInfo.applicationInfo.packageName, aInfo.name));
+
+            // Don't debug things in the system process
+            if (debug) {
+                if (!aInfo.processName.equals("system")) {
+                    setDebugApp(aInfo.processName, true, false);
+                }
+            }
+        }
+
+        synchronized(this) {
+            final long origId = Binder.clearCallingIdentity();
+            int res = startActivityLocked(caller, intent, resolvedType,
+                    grantedUriPermissions, grantedMode, aInfo,
+                    resultTo, resultWho, requestCode, -1, -1,
+                    onlyIfNeeded);
+            Binder.restoreCallingIdentity(origId);
+            return res;
+        }
+    }
+
+    public boolean startNextMatchingActivity(IBinder callingActivity,
+            Intent intent) {
+        // Refuse possible leaked file descriptors
+        if (intent != null && intent.hasFileDescriptors() == true) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        synchronized (this) {
+            int index = indexOfTokenLocked(callingActivity, false);
+            if (index < 0) {
+                return false;
+            }
+            HistoryRecord r = (HistoryRecord)mHistory.get(index);
+            if (r.app == null || r.app.thread == null) {
+                // The caller is not running...  d'oh!
+                return false;
+            }
+            intent = new Intent(intent);
+            // The caller is not allowed to change the data.
+            intent.setDataAndType(r.intent.getData(), r.intent.getType());
+            // And we are resetting to find the next component...
+            intent.setComponent(null);
+
+            ActivityInfo aInfo = null;
+            try {
+                List<ResolveInfo> resolves =
+                    ActivityThread.getPackageManager().queryIntentActivities(
+                            intent, r.resolvedType,
+                            PackageManager.MATCH_DEFAULT_ONLY
+                            | PackageManager.GET_SHARED_LIBRARY_FILES);
+
+                // Look for the original activity in the list...
+                final int N = resolves != null ? resolves.size() : 0;
+                for (int i=0; i<N; i++) {
+                    ResolveInfo rInfo = resolves.get(i);
+                    if (rInfo.activityInfo.packageName.equals(r.packageName)
+                            && rInfo.activityInfo.name.equals(r.info.name)) {
+                        // We found the current one...  the next matching is
+                        // after it.
+                        i++;
+                        if (i<N) {
+                            aInfo = resolves.get(i).activityInfo;
+                        }
+                        break;
+                    }
+                }
+            } catch (RemoteException e) {
+            }
+
+            if (aInfo == null) {
+                // Nobody who is next!
+                return false;
+            }
+
+            intent.setComponent(new ComponentName(
+                    aInfo.applicationInfo.packageName, aInfo.name));
+            intent.setFlags(intent.getFlags()&~(
+                    Intent.FLAG_ACTIVITY_FORWARD_RESULT|
+                    Intent.FLAG_ACTIVITY_CLEAR_TOP|
+                    Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
+                    Intent.FLAG_ACTIVITY_NEW_TASK));
+
+            // Okay now we need to start the new activity, replacing the
+            // currently running activity.  This is a little tricky because
+            // we want to start the new one as if the current one is finished,
+            // but not finish the current one first so that there is no flicker.
+            // And thus...
+            final boolean wasFinishing = r.finishing;
+            r.finishing = true;
+
+            // Propagate reply information over to the new activity.
+            final HistoryRecord resultTo = r.resultTo;
+            final String resultWho = r.resultWho;
+            final int requestCode = r.requestCode;
+            r.resultTo = null;
+            if (resultTo != null) {
+                resultTo.removeResultsLocked(r, resultWho, requestCode);
+            }
+
+            final long origId = Binder.clearCallingIdentity();
+            // XXX we are not dealing with propagating grantedUriPermissions...
+            // those are not yet exposed to user code, so there is no need.
+            int res = startActivityLocked(r.app.thread, intent,
+                    r.resolvedType, null, 0, aInfo, resultTo, resultWho,
+                    requestCode, -1, r.launchedFromUid, false);
+            Binder.restoreCallingIdentity(origId);
+
+            r.finishing = wasFinishing;
+            if (res != START_SUCCESS) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    final int startActivityInPackage(int uid,
+            Intent intent, String resolvedType, IBinder resultTo,
+            String resultWho, int requestCode, boolean onlyIfNeeded) {
+        // Don't modify the client's object!
+        intent = new Intent(intent);
+
+        // Collect information about the target of the Intent.
+        // Must do this before locking, because resolving the intent
+        // may require launching a process to run its content provider.
+        ActivityInfo aInfo;
+        try {
+            ResolveInfo rInfo =
+                ActivityThread.getPackageManager().resolveIntent(
+                        intent, resolvedType,
+                        PackageManager.MATCH_DEFAULT_ONLY
+                        | PackageManager.GET_SHARED_LIBRARY_FILES);
+            aInfo = rInfo != null ? rInfo.activityInfo : null;
+        } catch (RemoteException e) {
+            aInfo = null;
+        }
+
+        if (aInfo != null) {
+            // Store the found target back into the intent, because now that
+            // we have it we never want to do this again.  For example, if the
+            // user navigates back to this point in the history, we should
+            // always restart the exact same activity.
+            intent.setComponent(new ComponentName(
+                    aInfo.applicationInfo.packageName, aInfo.name));
+        }
+
+        synchronized(this) {
+            return startActivityLocked(null, intent, resolvedType,
+                    null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
+                    onlyIfNeeded);
+        }
+    }
+
+    private final void addRecentTask(TaskRecord task) {
+        // Remove any existing entries that are the same kind of task.
+        int N = mRecentTasks.size();
+        for (int i=0; i<N; i++) {
+            TaskRecord tr = mRecentTasks.get(i);
+            if ((task.affinity != null && task.affinity.equals(tr.affinity))
+                    || (task.intent != null && task.intent.filterEquals(tr.intent))) {
+                mRecentTasks.remove(i);
+                i--;
+                N--;
+                if (task.intent == null) {
+                    // If the new recent task we are adding is not fully
+                    // specified, then replace it with the existing recent task.
+                    task = tr;
+                }
+            }
+        }
+        if (N >= MAX_RECENT_TASKS) {
+            mRecentTasks.remove(N-1);
+        }
+        mRecentTasks.add(0, task);
+    }
+
+    public void setRequestedOrientation(IBinder token,
+            int requestedOrientation) {
+        synchronized (this) {
+            int index = indexOfTokenLocked(token, false);
+            if (index < 0) {
+                return;
+            }
+            HistoryRecord r = (HistoryRecord)mHistory.get(index);
+            final long origId = Binder.clearCallingIdentity();
+            mWindowManager.setAppOrientation(r, requestedOrientation);
+            Configuration config = mWindowManager.updateOrientationFromAppTokens(
+                    r.mayFreezeScreenLocked(r.app) ? r : null);
+            if (config != null) {
+                r.frozenBeforeDestroy = true;
+                if (!updateConfigurationLocked(config, r)) {
+                    resumeTopActivityLocked(null);
+                }
+            }
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    public int getRequestedOrientation(IBinder token) {
+        synchronized (this) {
+            int index = indexOfTokenLocked(token, false);
+            if (index < 0) {
+                return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+            }
+            HistoryRecord r = (HistoryRecord)mHistory.get(index);
+            return mWindowManager.getAppOrientation(r);
+        }
+    }
+
+    private final void stopActivityLocked(HistoryRecord r) {
+        if (DEBUG_SWITCH) Log.d(TAG, "Stopping: " + r);
+        if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
+                || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
+            if (!r.finishing) {
+                requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
+                        "no-history");
+            }
+        } else if (r.app != null && r.app.thread != null) {
+            if (mFocusedActivity == r) {
+                setFocusedActivityLocked(topRunningActivityLocked(null));
+            }
+            r.resumeKeyDispatchingLocked();
+            try {
+                r.stopped = false;
+                r.state = ActivityState.STOPPING;
+                if (DEBUG_VISBILITY) Log.v(
+                        TAG, "Stopping visible=" + r.visible + " for " + r);
+                if (!r.visible) {
+                    mWindowManager.setAppVisibility(r, false);
+                }
+                r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
+            } catch (Exception e) {
+                // Maybe just ignore exceptions here...  if the process
+                // has crashed, our death notification will clean things
+                // up.
+                Log.w(TAG, "Exception thrown during pause", e);
+                // Just in case, assume it to be stopped.
+                r.stopped = true;
+                r.state = ActivityState.STOPPED;
+                if (r.configDestroy) {
+                    destroyActivityLocked(r, true);
+                }
+            }
+        }
+    }
+
+    /**
+     * @return Returns true if the activity is being finished, false if for
+     * some reason it is being left as-is.
+     */
+    private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
+            Intent resultData, String reason) {
+        if (localLOGV) Log.v(
+            TAG, "Finishing activity: token=" + token
+            + ", result=" + resultCode + ", data=" + resultData);
+
+        int index = indexOfTokenLocked(token, false);
+        if (index < 0) {
+            return false;
+        }
+        HistoryRecord r = (HistoryRecord)mHistory.get(index);
+
+        // Is this the last activity left?
+        boolean lastActivity = true;
+        for (int i=mHistory.size()-1; i>=0; i--) {
+            HistoryRecord p = (HistoryRecord)mHistory.get(i);
+            if (!p.finishing && p != r) {
+                lastActivity = false;
+                break;
+            }
+        }
+        
+        // If this is the last activity, but it is the home activity, then
+        // just don't finish it.
+        if (lastActivity) {
+            if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
+                return false;
+            }
+        }
+        
+        finishActivityLocked(r, index, resultCode, resultData, reason);
+        return true;
+    }
+
+    /**
+     * @return Returns true if this activity has been removed from the history
+     * list, or false if it is still in the list and will be removed later.
+     */
+    private final boolean finishActivityLocked(HistoryRecord r, int index,
+            int resultCode, Intent resultData, String reason) {
+        if (r.finishing) {
+            Log.w(TAG, "Duplicate finish request for " + r);
+            return false;
+        }
+
+        r.finishing = true;
+        EventLog.writeEvent(LOG_AM_FINISH_ACTIVITY,
+                System.identityHashCode(r),
+                r.task.taskId, r.shortComponentName, reason);
+        r.task.numActivities--;
+        if (r.frontOfTask && index < (mHistory.size()-1)) {
+            HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
+            if (next.task == r.task) {
+                next.frontOfTask = true;
+            }
+        }
+
+        r.pauseKeyDispatchingLocked();
+        if (mFocusedActivity == r) {
+            setFocusedActivityLocked(topRunningActivityLocked(null));
+        }
+
+        // send the result
+        HistoryRecord resultTo = r.resultTo;
+        if (resultTo != null) {
+            if (localLOGV) Log.v(TAG, "Adding result to " + resultTo);
+            if (r.info.applicationInfo.uid > 0) {
+                grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
+                        r.packageName, resultData, r);
+            }
+            resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
+                                     resultData);
+            r.resultTo = null;
+        }
+
+        // Make sure this HistoryRecord is not holding on to other resources,
+        // because clients have remote IPC references to this object so we
+        // can't assume that will go away and want to avoid circular IPC refs.
+        r.results = null;
+        r.pendingResults = null;
+        r.newIntents = null;
+        r.icicle = null;
+        
+        if (mPendingThumbnails.size() > 0) {
+            // There are clients waiting to receive thumbnails so, in case
+            // this is an activity that someone is waiting for, add it
+            // to the pending list so we can correctly update the clients.
+            mCancelledThumbnails.add(r);
+        }
+
+        if (mResumedActivity == r) {
+            boolean endTask = index <= 0
+                    || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
+            if (DEBUG_TRANSITION) Log.v(TAG,
+                    "Prepare close transition: finishing " + r);
+            mWindowManager.prepareAppTransition(endTask
+                    ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
+                    : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
+    
+            // Tell window manager to prepare for this one to be removed.
+            mWindowManager.setAppVisibility(r, false);
+                
+            if (mPausingActivity == null) {
+                if (DEBUG_PAUSE) Log.v(TAG, "Finish needs to pause: " + r);
+                if (DEBUG_USER_LEAVING) Log.v(TAG, "finish() => pause with userLeaving=false");
+                startPausingLocked(false, false);
+            }
+
+        } else if (r.state != ActivityState.PAUSING) {
+            // If the activity is PAUSING, we will complete the finish once
+            // it is done pausing; else we can just directly finish it here.
+            if (DEBUG_PAUSE) Log.v(TAG, "Finish not pausing: " + r);
+            return finishCurrentActivityLocked(r, index,
+                    FINISH_AFTER_PAUSE) == null;
+        } else {
+            if (DEBUG_PAUSE) Log.v(TAG, "Finish waiting for pause of: " + r);
+        }
+
+        return false;
+    }
+
+    private static final int FINISH_IMMEDIATELY = 0;
+    private static final int FINISH_AFTER_PAUSE = 1;
+    private static final int FINISH_AFTER_VISIBLE = 2;
+
+    private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
+            int mode) {
+        final int index = indexOfTokenLocked(r, false);
+        if (index < 0) {
+            return null;
+        }
+
+        return finishCurrentActivityLocked(r, index, mode);
+    }
+
+    private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
+            int index, int mode) {
+        // First things first: if this activity is currently visible,
+        // and the resumed activity is not yet visible, then hold off on
+        // finishing until the resumed one becomes visible.
+        if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
+            if (!mStoppingActivities.contains(r)) {
+                mStoppingActivities.add(r);
+                if (mStoppingActivities.size() > 3) {
+                    // If we already have a few activities waiting to stop,
+                    // then give up on things going idle and start clearing
+                    // them out.
+                    Message msg = Message.obtain();
+                    msg.what = ActivityManagerService.IDLE_NOW_MSG;
+                    mHandler.sendMessage(msg);
+                }
+            }
+            r.state = ActivityState.STOPPING;
+            updateOomAdjLocked();
+            return r;
+        }
+
+        // make sure the record is cleaned out of other places.
+        mStoppingActivities.remove(r);
+        mWaitingVisibleActivities.remove(r);
+        if (mResumedActivity == r) {
+            mResumedActivity = null;
+        }
+        final ActivityState prevState = r.state;
+        r.state = ActivityState.FINISHING;
+
+        if (mode == FINISH_IMMEDIATELY
+                || prevState == ActivityState.STOPPED
+                || prevState == ActivityState.INITIALIZING) {
+            // If this activity is already stopped, we can just finish
+            // it right now.
+            return destroyActivityLocked(r, true) ? null : r;
+        } else {
+            // Need to go through the full pause cycle to get this
+            // activity into the stopped state and then finish it.
+            if (localLOGV) Log.v(TAG, "Enqueueing pending finish: " + r);
+            mFinishingActivities.add(r);
+            resumeTopActivityLocked(null);
+        }
+        return r;
+    }
+
+    /**
+     * This is the internal entry point for handling Activity.finish().
+     * 
+     * @param token The Binder token referencing the Activity we want to finish.
+     * @param resultCode Result code, if any, from this Activity.
+     * @param resultData Result data (Intent), if any, from this Activity.
+     * 
+     * @result Returns true if the activity successfully finished, or false if it is still running.
+     */
+    public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
+        // Refuse possible leaked file descriptors
+        if (resultData != null && resultData.hasFileDescriptors() == true) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        synchronized(this) {
+            if (mWatcher != null) {
+                // Find the first activity that is not finishing.
+                HistoryRecord next = topRunningActivityLocked(token, 0);
+                if (next != null) {
+                    // ask watcher if this is allowed
+                    boolean resumeOK = true;
+                    try {
+                        resumeOK = mWatcher.activityResuming(next.packageName);
+                    } catch (RemoteException e) {
+                        mWatcher = null;
+                    }
+    
+                    if (!resumeOK) {
+                        return false;
+                    }
+                }
+            }
+            final long origId = Binder.clearCallingIdentity();
+            boolean res = requestFinishActivityLocked(token, resultCode,
+                    resultData, "app-request");
+            Binder.restoreCallingIdentity(origId);
+            return res;
+        }
+    }
+
+    void sendActivityResultLocked(int callingUid, HistoryRecord r,
+            String resultWho, int requestCode, int resultCode, Intent data) {
+
+        if (callingUid > 0) {
+            grantUriPermissionFromIntentLocked(callingUid, r.packageName,
+                    data, r);
+        }
+
+        if (mResumedActivity == r && r.app != null && r.app.thread != null) {
+            try {
+                ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
+                list.add(new ResultInfo(resultWho, requestCode,
+                        resultCode, data));
+                r.app.thread.scheduleSendResult(r, list);
+                return;
+            } catch (Exception e) {
+                Log.w(TAG, "Exception thrown sending result to " + r, e);
+            }
+        }
+
+        r.addResultLocked(null, resultWho, requestCode, resultCode, data);
+    }
+
+    public final void finishSubActivity(IBinder token, String resultWho,
+            int requestCode) {
+        synchronized(this) {
+            int index = indexOfTokenLocked(token, false);
+            if (index < 0) {
+                return;
+            }
+            HistoryRecord self = (HistoryRecord)mHistory.get(index);
+
+            final long origId = Binder.clearCallingIdentity();
+
+            int i;
+            for (i=mHistory.size()-1; i>=0; i--) {
+                HistoryRecord r = (HistoryRecord)mHistory.get(i);
+                if (r.resultTo == self && r.requestCode == requestCode) {
+                    if ((r.resultWho == null && resultWho == null) ||
+                        (r.resultWho != null && r.resultWho.equals(resultWho))) {
+                        finishActivityLocked(r, i,
+                                Activity.RESULT_CANCELED, null, "request-sub");
+                    }
+                }
+            }
+
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    /**
+     * Perform clean-up of service connections in an activity record.
+     */
+    private final void cleanUpActivityServicesLocked(HistoryRecord r) {
+        // Throw away any services that have been bound by this activity.
+        if (r.connections != null) {
+            Iterator<ConnectionRecord> it = r.connections.iterator();
+            while (it.hasNext()) {
+                ConnectionRecord c = it.next();
+                removeConnectionLocked(c, null, r);
+            }
+            r.connections = null;
+        }
+    }
+    
+    /**
+     * Perform the common clean-up of an activity record.  This is called both
+     * as part of destroyActivityLocked() (when destroying the client-side
+     * representation) and cleaning things up as a result of its hosting
+     * processing going away, in which case there is no remaining client-side
+     * state to destroy so only the cleanup here is needed.
+     */
+    private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
+        if (mResumedActivity == r) {
+            mResumedActivity = null;
+        }
+        if (mFocusedActivity == r) {
+            mFocusedActivity = null;
+        }
+
+        r.configDestroy = false;
+        r.frozenBeforeDestroy = false;
+
+        // Make sure this record is no longer in the pending finishes list.
+        // This could happen, for example, if we are trimming activities
+        // down to the max limit while they are still waiting to finish.
+        mFinishingActivities.remove(r);
+        mWaitingVisibleActivities.remove(r);
+        
+        // Remove any pending results.
+        if (r.finishing && r.pendingResults != null) {
+            for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
+                PendingIntentRecord rec = apr.get();
+                if (rec != null) {
+                    cancelIntentSenderLocked(rec, false);
+                }
+            }
+            r.pendingResults = null;
+        }
+
+        if (cleanServices) {
+            cleanUpActivityServicesLocked(r);            
+        }
+
+        if (mPendingThumbnails.size() > 0) {
+            // There are clients waiting to receive thumbnails so, in case
+            // this is an activity that someone is waiting for, add it
+            // to the pending list so we can correctly update the clients.
+            mCancelledThumbnails.add(r);
+        }
+
+        // Get rid of any pending idle timeouts.
+        mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
+        mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
+    }
+
+    private final void removeActivityFromHistoryLocked(HistoryRecord r) {
+        if (r.state != ActivityState.DESTROYED) {
+            mHistory.remove(r);
+            r.inHistory = false;
+            r.state = ActivityState.DESTROYED;
+            mWindowManager.removeAppToken(r);
+            if (VALIDATE_TOKENS) {
+                mWindowManager.validateAppTokens(mHistory);
+            }
+            cleanUpActivityServicesLocked(r);
+            removeActivityUriPermissionsLocked(r);
+        }
+    }
+    
+    /**
+     * Destroy the current CLIENT SIDE instance of an activity.  This may be
+     * called both when actually finishing an activity, or when performing
+     * a configuration switch where we destroy the current client-side object
+     * but then create a new client-side object for this same HistoryRecord.
+     */
+    private final boolean destroyActivityLocked(HistoryRecord r,
+            boolean removeFromApp) {
+        if (DEBUG_SWITCH) Log.v(
+            TAG, "Removing activity: token=" + r
+              + ", app=" + (r.app != null ? r.app.processName : "(null)"));
+        EventLog.writeEvent(LOG_AM_DESTROY_ACTIVITY,
+                System.identityHashCode(r),
+                r.task.taskId, r.shortComponentName);
+
+        boolean removedFromHistory = false;
+        
+        cleanUpActivityLocked(r, false);
+
+        if (r.app != null) {
+            if (removeFromApp) {
+                int idx = r.app.activities.indexOf(r);
+                if (idx >= 0) {
+                    r.app.activities.remove(idx);
+                }
+                if (r.persistent) {
+                    decPersistentCountLocked(r.app);
+                }
+            }
+
+            boolean skipDestroy = false;
+            
+            try {
+                if (DEBUG_SWITCH) Log.i(TAG, "Destroying: " + r);
+                r.app.thread.scheduleDestroyActivity(r, r.finishing,
+                        r.configChangeFlags);
+            } catch (Exception e) {
+                // We can just ignore exceptions here...  if the process
+                // has crashed, our death notification will clean things
+                // up.
+                //Log.w(TAG, "Exception thrown during finish", e);
+                if (r.finishing) {
+                    removeActivityFromHistoryLocked(r);
+                    removedFromHistory = true;
+                    skipDestroy = true;
+                }
+            }
+
+            r.app = null;
+            r.nowVisible = false;
+            
+            if (r.finishing && !skipDestroy) {
+                r.state = ActivityState.DESTROYING;
+                Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
+                msg.obj = r;
+                mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
+            } else {
+                r.state = ActivityState.DESTROYED;
+            }
+        } else {
+            // remove this record from the history.
+            if (r.finishing) {
+                removeActivityFromHistoryLocked(r);
+                removedFromHistory = true;
+            } else {
+                r.state = ActivityState.DESTROYED;
+            }
+        }
+
+        r.configChangeFlags = 0;
+        
+        if (!mLRUActivities.remove(r)) {
+            Log.w(TAG, "Activity " + r + " being finished, but not in LRU list");
+        }
+        
+        return removedFromHistory;
+    }
+
+    private static void removeHistoryRecordsForAppLocked(ArrayList list,
+                                                         ProcessRecord app)
+    {
+        int i = list.size();
+        if (localLOGV) Log.v(
+            TAG, "Removing app " + app + " from list " + list
+            + " with " + i + " entries");
+        while (i > 0) {
+            i--;
+            HistoryRecord r = (HistoryRecord)list.get(i);
+            if (localLOGV) Log.v(
+                TAG, "Record #" + i + " " + r + ": app=" + r.app);
+            if (r.app == app) {
+                if (localLOGV) Log.v(TAG, "Removing this entry!");
+                list.remove(i);
+            }
+        }
+    }
+
+    /**
+     * Main function for removing an existing process from the activity manager
+     * as a result of that process going away.  Clears out all connections
+     * to the process.
+     */
+    private final void handleAppDiedLocked(ProcessRecord app,
+            boolean restarting) {
+        cleanUpApplicationRecordLocked(app, restarting, -1);
+        if (!restarting) {
+            mLRUProcesses.remove(app);
+        }
+
+        // Just in case...
+        if (mPausingActivity != null && mPausingActivity.app == app) {
+            if (DEBUG_PAUSE) Log.v(TAG, "App died while pausing: " + mPausingActivity);
+            mPausingActivity = null;
+        }
+        if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
+            mLastPausedActivity = null;
+        }
+
+        // Remove this application's activities from active lists.
+        removeHistoryRecordsForAppLocked(mLRUActivities, app);
+        removeHistoryRecordsForAppLocked(mStoppingActivities, app);
+        removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
+        removeHistoryRecordsForAppLocked(mFinishingActivities, app);
+
+        boolean atTop = true;
+        boolean hasVisibleActivities = false;
+
+        // Clean out the history list.
+        int i = mHistory.size();
+        if (localLOGV) Log.v(
+            TAG, "Removing app " + app + " from history with " + i + " entries");
+        while (i > 0) {
+            i--;
+            HistoryRecord r = (HistoryRecord)mHistory.get(i);
+            if (localLOGV) Log.v(
+                TAG, "Record #" + i + " " + r + ": app=" + r.app);
+            if (r.app == app) {
+                if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
+                    if (localLOGV) Log.v(
+                        TAG, "Removing this entry!  frozen=" + r.haveState
+                        + " finishing=" + r.finishing);
+                    mHistory.remove(i);
+
+                    r.inHistory = false;
+                    mWindowManager.removeAppToken(r);
+                    if (VALIDATE_TOKENS) {
+                        mWindowManager.validateAppTokens(mHistory);
+                    }
+                    removeActivityUriPermissionsLocked(r);
+
+                } else {
+                    // We have the current state for this activity, so
+                    // it can be restarted later when needed.
+                    if (localLOGV) Log.v(
+                        TAG, "Keeping entry, setting app to null");
+                    if (r.visible) {
+                        hasVisibleActivities = true;
+                    }
+                    r.app = null;
+                    r.nowVisible = false;
+                    if (!r.haveState) {
+                        r.icicle = null;
+                    }
+                }
+
+                cleanUpActivityLocked(r, true);
+                r.state = ActivityState.STOPPED;
+            }
+            atTop = false;
+        }
+
+        app.activities.clear();
+        
+        if (app.instrumentationClass != null) {
+            Log.w(TAG, "Crash of app " + app.processName
+                  + " running instrumentation " + app.instrumentationClass);
+            Bundle info = new Bundle();
+            info.putString("shortMsg", "Process crashed.");
+            finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
+        }
+
+        if (!restarting) {
+            if (!resumeTopActivityLocked(null)) {
+                // If there was nothing to resume, and we are not already
+                // restarting this process, but there is a visible activity that
+                // is hosted by the process...  then make sure all visible
+                // activities are running, taking care of restarting this
+                // process.
+                if (hasVisibleActivities) {
+                    ensureActivitiesVisibleLocked(null, 0);
+                }
+            }
+        }
+    }
+
+    private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
+        IBinder threadBinder = thread.asBinder();
+
+        // Find the application record.
+        int count = mLRUProcesses.size();
+        int i;
+        for (i=0; i<count; i++) {
+            ProcessRecord rec = mLRUProcesses.get(i);
+            if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private final ProcessRecord getRecordForAppLocked(
+            IApplicationThread thread) {
+        if (thread == null) {
+            return null;
+        }
+
+        int appIndex = getLRURecordIndexForAppLocked(thread);
+        return appIndex >= 0 ? mLRUProcesses.get(appIndex) : null;
+    }
+
+    private final void appDiedLocked(ProcessRecord app, int pid,
+            IApplicationThread thread) {
+
+        mProcDeaths[0]++;
+        
+        if (app.thread != null && app.thread.asBinder() == thread.asBinder()) {
+            Log.i(TAG, "Process " + app.processName + " (pid " + pid
+                    + ") has died.");
+            EventLog.writeEvent(LOG_AM_PROCESS_DIED, app.pid, app.processName);
+            if (localLOGV) Log.v(
+                TAG, "Dying app: " + app + ", pid: " + pid
+                + ", thread: " + thread.asBinder());
+            boolean doLowMem = app.instrumentationClass == null;
+            handleAppDiedLocked(app, false);
+
+            if (doLowMem) {
+                // If there are no longer any background processes running,
+                // and the app that died was not running instrumentation,
+                // then tell everyone we are now low on memory.
+                boolean haveBg = false;
+                int count = mLRUProcesses.size();
+                int i;
+                for (i=0; i<count; i++) {
+                    ProcessRecord rec = mLRUProcesses.get(i);
+                    if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
+                        haveBg = true;
+                        break;
+                    }
+                }
+                
+                if (!haveBg) {
+                    Log.i(TAG, "Low Memory: No more background processes.");
+                    EventLog.writeEvent(LOG_AM_LOW_MEMORY, mLRUProcesses.size());
+                    for (i=0; i<count; i++) {
+                        ProcessRecord rec = mLRUProcesses.get(i);
+                        if (rec.thread != null) {
+                            rec.lastRequestedGc = SystemClock.uptimeMillis();
+                            try {
+                                rec.thread.scheduleLowMemory();
+                            } catch (RemoteException e) {
+                                // Don't care if the process is gone.
+                            }
+                        }
+                    }
+                }
+            }
+        } else if (Config.LOGD) {
+            Log.d(TAG, "Received spurious death notification for thread "
+                    + thread.asBinder());
+        }
+    }
+
+    final String readFile(String filename) {
+        try {
+            FileInputStream fs = new FileInputStream(filename);
+            byte[] inp = new byte[8192];
+            int size = fs.read(inp);
+            fs.close();
+            return new String(inp, 0, 0, size);
+        } catch (java.io.IOException e) {
+        }
+        return "";
+    }
+
+    final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity, 
+            final String annotation) {
+        if (app.notResponding || app.crashing) {
+            return;
+        }
+        
+        // Log the ANR to the event log.
+        EventLog.writeEvent(LOG_ANR, app.pid, app.processName, annotation);
+        
+        // If we are on a secure build and the application is not interesting to the user (it is
+        // not visible or in the background), just kill it instead of displaying a dialog.
+        boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
+        if (isSecure && !app.isInterestingToUserLocked() && Process.myPid() != app.pid) {
+            Process.killProcess(app.pid);
+            return;
+        }
+        
+        // DeviceMonitor.start();
+
+        String processInfo = null;
+        if (MONITOR_CPU_USAGE) {
+            updateCpuStatsNow();
+            synchronized (mProcessStatsThread) {
+                processInfo = mProcessStats.printCurrentState();
+            }
+        }
+
+        StringBuilder info = new StringBuilder();
+        info.append("ANR (application not responding) in process: ");
+        info.append(app.processName);
+        if (annotation != null) {
+            info.append("\nAnnotation: ");
+            info.append(annotation);
+        }
+        if (MONITOR_CPU_USAGE) {
+            info.append("\nCPU usage:\n");
+            info.append(processInfo);
+        }
+        Log.i(TAG, info.toString());
+
+        // The application is not responding. Dump as many thread traces as we can.
+        boolean fileDump = prepareTraceFile(true);
+        if (!fileDump) {
+            // Dumping traces to the log, just dump the process that isn't responding so
+            // we don't overflow the log
+            Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
+        } else {
+            // Dumping traces to a file so dump all active processes we know about
+            synchronized (this) {
+                for (int i = mLRUProcesses.size() - 1 ; i >= 0 ; i--) {
+                    ProcessRecord r = mLRUProcesses.get(i);
+                    if (r.thread != null) {
+                        Process.sendSignal(r.pid, Process.SIGNAL_QUIT);
+                    }
+                }
+            }
+        }
+
+        if (mWatcher != null) {
+            try {
+                int res = mWatcher.appNotResponding(app.processName,
+                        app.pid, info.toString());
+                if (res != 0) {
+                    if (res < 0) {
+                        // wait until the SIGQUIT has had a chance to process before killing the
+                        // process.
+                        try {
+                            wait(2000);
+                        } catch (InterruptedException e) {
+                        }
+
+                        Process.killProcess(app.pid);
+                        return;
+                    }
+                }
+            } catch (RemoteException e) {
+                mWatcher = null;
+            }
+        }
+
+        makeAppNotRespondingLocked(app,
+                activity != null ? activity.shortComponentName : null,
+                annotation != null ? "ANR " + annotation : "ANR",
+                info.toString(), null);
+        Message msg = Message.obtain();
+        HashMap map = new HashMap();
+        msg.what = SHOW_NOT_RESPONDING_MSG;
+        msg.obj = map;
+        map.put("app", app);
+        if (activity != null) {
+            map.put("activity", activity);
+        }
+
+        mHandler.sendMessage(msg);
+        return;
+    }
+
+    /**
+     * If a stack trace file has been configured, prepare the filesystem
+     * by creating the directory if it doesn't exist and optionally
+     * removing the old trace file.
+     *
+     * @param removeExisting If set, the existing trace file will be removed.
+     * @return Returns true if the trace file preparations succeeded
+     */
+    public static boolean prepareTraceFile(boolean removeExisting) {
+        String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
+        boolean fileReady = false;
+        if (!TextUtils.isEmpty(tracesPath)) {
+            File f = new File(tracesPath);
+            if (!f.exists()) {
+                // Ensure the enclosing directory exists
+                File dir = f.getParentFile();
+                if (!dir.exists()) {
+                    fileReady = dir.mkdirs();
+                    FileUtils.setPermissions(dir.getAbsolutePath(),
+                            FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO, -1, -1);
+                } else if (dir.isDirectory()) {
+                    fileReady = true;
+                }
+            } else if (removeExisting) {
+                // Remove the previous traces file, so we don't fill the disk.
+                // The VM will recreate it
+                Log.i(TAG, "Removing old ANR trace file from " + tracesPath);
+                fileReady = f.delete();
+            }
+        }
+
+        return fileReady;
+    }
+
+
+    private final void decPersistentCountLocked(ProcessRecord app)
+    {
+        app.persistentActivities--;
+        if (app.persistentActivities > 0) {
+            // Still more of 'em...
+            return;
+        }
+        if (app.persistent) {
+            // Ah, but the application itself is persistent.  Whatever!
+            return;
+        }
+
+        // App is no longer persistent...  make sure it and the ones
+        // following it in the LRU list have the correc oom_adj.
+        updateOomAdjLocked();
+    }
+
+    public void setPersistent(IBinder token, boolean isPersistent) {
+        if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: setPersistent() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
+            Log.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+
+        synchronized(this) {
+            int index = indexOfTokenLocked(token, true);
+            if (index < 0) {
+                return;
+            }
+            HistoryRecord r = (HistoryRecord)mHistory.get(index);
+            ProcessRecord app = r.app;
+
+            if (localLOGV) Log.v(
+                TAG, "Setting persistence " + isPersistent + ": " + r);
+
+            if (isPersistent) {
+                if (r.persistent) {
+                    // Okay okay, I heard you already!
+                    if (localLOGV) Log.v(TAG, "Already persistent!");
+                    return;
+                }
+                r.persistent = true;
+                app.persistentActivities++;
+                if (localLOGV) Log.v(TAG, "Num persistent now: " + app.persistentActivities);
+                if (app.persistentActivities > 1) {
+                    // We aren't the first...
+                    if (localLOGV) Log.v(TAG, "Not the first!");
+                    return;
+                }
+                if (app.persistent) {
+                    // This would be redundant.
+                    if (localLOGV) Log.v(TAG, "App is persistent!");
+                    return;
+                }
+
+                // App is now persistent...  make sure it and the ones
+                // following it now have the correct oom_adj.
+                final long origId = Binder.clearCallingIdentity();
+                updateOomAdjLocked();
+                Binder.restoreCallingIdentity(origId);
+
+            } else {
+                if (!r.persistent) {
+                    // Okay okay, I heard you already!
+                    return;
+                }
+                r.persistent = false;
+                final long origId = Binder.clearCallingIdentity();
+                decPersistentCountLocked(app);
+                Binder.restoreCallingIdentity(origId);
+
+            }
+        }
+    }
+    
+    public boolean clearApplicationUserData(final String packageName,
+            final IPackageDataObserver observer) {
+        int uid = Binder.getCallingUid();
+        int pid = Binder.getCallingPid();
+        long callingId = Binder.clearCallingIdentity();
+        try {
+            IPackageManager pm = ActivityThread.getPackageManager();
+            int pkgUid = -1;
+            synchronized(this) {
+                try {
+                    pkgUid = pm.getPackageUid(packageName);
+                } catch (RemoteException e) {
+                }
+                if (pkgUid == -1) {
+                    Log.w(TAG, "Invalid packageName:" + packageName);
+                    return false;
+                }
+                if (uid == pkgUid || checkComponentPermission(
+                        android.Manifest.permission.CLEAR_APP_USER_DATA,
+                        pid, uid, -1)
+                        == PackageManager.PERMISSION_GRANTED) {
+                    restartPackageLocked(packageName, pkgUid);
+                } else {
+                    throw new SecurityException(pid+" does not have permission:"+
+                            android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
+                                    "for process:"+packageName);
+                }
+            }
+            
+            try {
+                //clear application user data
+                pm.clearApplicationUserData(packageName, observer);
+                Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
+                        Uri.fromParts("package", packageName, null));
+                intent.putExtra(Intent.EXTRA_UID, pkgUid);
+                broadcastIntentLocked(null, null, intent,
+                        null, null, 0, null, null, null,
+                        false, false, MY_PID, Process.SYSTEM_UID);
+            } catch (RemoteException e) {
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+        return true;
+    }
+
+    public void restartPackage(final String packageName) {
+        if (checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: restartPackage() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.RESTART_PACKAGES;
+            Log.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        
+        long callingId = Binder.clearCallingIdentity();
+        try {
+            IPackageManager pm = ActivityThread.getPackageManager();
+            int pkgUid = -1;
+            synchronized(this) {
+                try {
+                    pkgUid = pm.getPackageUid(packageName);
+                } catch (RemoteException e) {
+                }
+                if (pkgUid == -1) {
+                    Log.w(TAG, "Invalid packageName: " + packageName);
+                    return;
+                }
+                restartPackageLocked(packageName, pkgUid);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+    }
+    
+    private void restartPackageLocked(final String packageName, int uid) {
+        uninstallPackageLocked(packageName, uid, false);
+        Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
+                Uri.fromParts("package", packageName, null));
+        intent.putExtra(Intent.EXTRA_UID, uid);
+        broadcastIntentLocked(null, null, intent,
+                null, null, 0, null, null, null,
+                false, false, MY_PID, Process.SYSTEM_UID);
+    }
+    
+    private final void uninstallPackageLocked(String name, int uid,
+            boolean callerWillRestart) {
+        if (Config.LOGD) Log.d(TAG, "Uninstalling process " + name);
+
+        int i, N;
+
+        final String procNamePrefix = name + ":";
+        if (uid < 0) {
+            try {
+                uid = ActivityThread.getPackageManager().getPackageUid(name);
+            } catch (RemoteException e) {
+            }
+        }
+
+        Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
+        while (badApps.hasNext()) {
+            SparseArray<Long> ba = badApps.next();
+            if (ba.get(uid) != null) {
+                badApps.remove();
+            }
+        }
+
+        ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
+
+        // Remove all processes this package may have touched: all with the
+        // same UID (except for the system or root user), and all whose name
+        // matches the package name.
+        for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
+            final int NA = apps.size();
+            for (int ia=0; ia<NA; ia++) {
+                ProcessRecord app = apps.valueAt(ia);
+                if (app.removed) {
+                    procs.add(app);
+                } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
+                        || app.processName.equals(name)
+                        || app.processName.startsWith(procNamePrefix)) {
+                    app.removed = true;
+                    procs.add(app);
+                }
+            }
+        }
+
+        N = procs.size();
+        for (i=0; i<N; i++) {
+            removeProcessLocked(procs.get(i), callerWillRestart);
+        }
+        
+        for (i=mHistory.size()-1; i>=0; i--) {
+            HistoryRecord r = (HistoryRecord)mHistory.get(i);
+            if (r.packageName.equals(name)) {
+                if (Config.LOGD) Log.d(
+                    TAG, "  Force finishing activity "
+                    + r.intent.getComponent().flattenToShortString());
+                if (r.app != null) {
+                    r.app.removed = true;
+                }
+                r.app = null;
+                finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
+            }
+        }
+
+        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
+        for (ServiceRecord service : mServices.values()) {
+            if (service.packageName.equals(name)) {
+                if (service.app != null) {
+                    service.app.removed = true;
+                }
+                service.app = null;
+                services.add(service);
+            }
+        }
+
+        N = services.size();
+        for (i=0; i<N; i++) {
+            bringDownServiceLocked(services.get(i), true);
+        }
+        
+        resumeTopActivityLocked(null);
+    }
+
+    private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
+        final String name = app.processName;
+        final int uid = app.info.uid;
+        if (Config.LOGD) Log.d(
+            TAG, "Force removing process " + app + " (" + name
+            + "/" + uid + ")");
+
+        mProcessNames.remove(name, uid);
+        boolean needRestart = false;
+        if (app.pid > 0 && app.pid != MY_PID) {
+            int pid = app.pid;
+            synchronized (mPidsSelfLocked) {
+                mPidsSelfLocked.remove(pid);
+                mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
+            }
+            handleAppDiedLocked(app, true);
+            mLRUProcesses.remove(app);
+            Process.killProcess(pid);
+            
+            if (app.persistent) {
+                if (!callerWillRestart) {
+                    addAppLocked(app.info);
+                } else {
+                    needRestart = true;
+                }
+            }
+        } else {
+            mRemovedProcesses.add(app);
+        }
+        
+        return needRestart;
+    }
+
+    private final void processStartTimedOutLocked(ProcessRecord app) {
+        final int pid = app.pid;
+        boolean gone = false;
+        synchronized (mPidsSelfLocked) {
+            ProcessRecord knownApp = mPidsSelfLocked.get(pid);
+            if (knownApp != null && knownApp.thread == null) {
+                mPidsSelfLocked.remove(pid);
+                gone = true;
+            }        
+        }
+        
+        if (gone) {
+            Log.w(TAG, "Process " + app + " failed to attach");
+            mProcessNames.remove(app.processName, app.info.uid);
+            Process.killProcess(pid);
+            if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
+                Log.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
+                mPendingBroadcast = null;
+                scheduleBroadcastsLocked();
+            }
+        } else {
+            Log.w(TAG, "Spurious process start timeout - pid not known for " + app);
+        }
+    }
+
+    private final boolean attachApplicationLocked(IApplicationThread thread,
+            int pid) {
+
+        // Find the application record that is being attached...  either via
+        // the pid if we are running in multiple processes, or just pull the
+        // next app record if we are emulating process with anonymous threads.
+        ProcessRecord app;
+        if (pid != MY_PID && pid >= 0) {
+            synchronized (mPidsSelfLocked) {
+                app = mPidsSelfLocked.get(pid);
+            }
+        } else if (mStartingProcesses.size() > 0) {
+            app = mStartingProcesses.remove(0);
+            app.pid = pid;
+        } else {
+            app = null;
+        }
+
+        if (app == null) {
+            Log.w(TAG, "No pending application record for pid " + pid
+                    + " (IApplicationThread " + thread + "); dropping process");
+            EventLog.writeEvent(LOG_AM_DROP_PROCESS, pid);
+            if (pid > 0 && pid != MY_PID) {
+                Process.killProcess(pid);
+            } else {
+                try {
+                    thread.scheduleExit();
+                } catch (Exception e) {
+                    // Ignore exceptions.
+                }
+            }
+            return false;
+        }
+
+        // If this application record is still attached to a previous
+        // process, clean it up now.
+        if (app.thread != null) {
+            handleAppDiedLocked(app, true);
+        }
+
+        // Tell the process all about itself.
+
+        if (localLOGV) Log.v(
+                TAG, "Binding process pid " + pid + " to record " + app);
+
+        String processName = app.processName;
+        try {
+            thread.asBinder().linkToDeath(new AppDeathRecipient(
+                    app, pid, thread), 0);
+        } catch (RemoteException e) {
+            app.resetPackageList();
+            startProcessLocked(app, "link fail", processName);
+            return false;
+        }
+
+        EventLog.writeEvent(LOG_AM_PROCESS_BOUND, app.pid, app.processName);
+        
+        app.thread = thread;
+        app.curAdj = app.setAdj = -100;
+        app.forcingToForeground = null;
+        app.foregroundServices = false;
+        app.debugging = false;
+
+        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
+
+        List providers = generateApplicationProvidersLocked(app);
+
+        if (localLOGV) Log.v(
+            TAG, "New app record " + app
+            + " thread=" + thread.asBinder() + " pid=" + pid);
+        try {
+            int testMode = IApplicationThread.DEBUG_OFF;
+            if (mDebugApp != null && mDebugApp.equals(processName)) {
+                testMode = mWaitForDebugger
+                    ? IApplicationThread.DEBUG_WAIT
+                    : IApplicationThread.DEBUG_ON;
+                app.debugging = true;
+                if (mDebugTransient) {
+                    mDebugApp = mOrigDebugApp;
+                    mWaitForDebugger = mOrigWaitForDebugger;
+                }
+            }
+            thread.bindApplication(processName, app.info, providers,
+                    app.instrumentationClass, app.instrumentationProfileFile,
+                    app.instrumentationArguments, app.instrumentationWatcher, testMode, 
+                    mConfiguration, getCommonServicesLocked());
+            updateLRUListLocked(app, false);
+            app.lastRequestedGc = SystemClock.uptimeMillis();
+        } catch (Exception e) {
+            // todo: Yikes!  What should we do?  For now we will try to
+            // start another process, but that could easily get us in
+            // an infinite loop of restarting processes...
+            Log.w(TAG, "Exception thrown during bind!", e);
+
+            app.resetPackageList();
+            startProcessLocked(app, "bind fail", processName);
+            return false;
+        }
+
+        // Remove this record from the list of starting applications.
+        mPersistentStartingProcesses.remove(app);
+        mProcessesOnHold.remove(app);
+
+        boolean badApp = false;
+        boolean didSomething = false;
+
+        // See if the top visible activity is waiting to run in this process...
+        HistoryRecord hr = topRunningActivityLocked(null);
+        if (hr != null) {
+            if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
+                    && processName.equals(hr.processName)) {
+                try {
+                    if (realStartActivityLocked(hr, app, true, true)) {
+                        didSomething = true;
+                    }
+                } catch (Exception e) {
+                    Log.w(TAG, "Exception in new application when starting activity "
+                          + hr.intent.getComponent().flattenToShortString(), e);
+                    badApp = true;
+                }
+            } else {
+                ensureActivitiesVisibleLocked(hr, null, processName, 0);
+            }
+        }
+
+        // Find any services that should be running in this process...
+        if (!badApp && mPendingServices.size() > 0) {
+            ServiceRecord sr = null;
+            try {
+                for (int i=0; i<mPendingServices.size(); i++) {
+                    sr = mPendingServices.get(i);
+                    if (app.info.uid != sr.appInfo.uid
+                            || !processName.equals(sr.processName)) {
+                        continue;
+                    }
+
+                    mPendingServices.remove(i);
+                    i--;
+                    realStartServiceLocked(sr, app);
+                    didSomething = true;
+                }
+            } catch (Exception e) {
+                Log.w(TAG, "Exception in new application when starting service "
+                      + sr.shortName, e);
+                badApp = true;
+            }
+        }
+
+        // Check if the next broadcast receiver is in this process...
+        BroadcastRecord br = mPendingBroadcast;
+        if (!badApp && br != null && br.curApp == app) {
+            try {
+                mPendingBroadcast = null;
+                processCurBroadcastLocked(br, app);
+                didSomething = true;
+            } catch (Exception e) {
+                Log.w(TAG, "Exception in new application when starting receiver "
+                      + br.curComponent.flattenToShortString(), e);
+                badApp = true;
+                logBroadcastReceiverDiscard(br);
+                finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
+                        br.resultExtras, br.resultAbort, true);
+                scheduleBroadcastsLocked();
+            }
+        }
+
+        if (badApp) {
+            // todo: Also need to kill application to deal with all
+            // kinds of exceptions.
+            handleAppDiedLocked(app, false);
+            return false;
+        }
+
+        if (!didSomething) {
+            updateOomAdjLocked();
+        }
+
+        return true;
+    }
+
+    public final void attachApplication(IApplicationThread thread) {
+        synchronized (this) {
+            int callingPid = Binder.getCallingPid();
+            final long origId = Binder.clearCallingIdentity();
+            attachApplicationLocked(thread, callingPid);
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    public final void activityIdle(IBinder token) {
+        final long origId = Binder.clearCallingIdentity();
+        activityIdleInternal(token, false);
+        Binder.restoreCallingIdentity(origId);
+    }
+
+    final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
+            boolean remove) {
+        int N = mStoppingActivities.size();
+        if (N <= 0) return null;
+
+        ArrayList<HistoryRecord> stops = null;
+
+        final boolean nowVisible = mResumedActivity != null
+                && mResumedActivity.nowVisible
+                && !mResumedActivity.waitingVisible;
+        for (int i=0; i<N; i++) {
+            HistoryRecord s = mStoppingActivities.get(i);
+            if (localLOGV) Log.v(TAG, "Stopping " + s + ": nowVisible="
+                    + nowVisible + " waitingVisible=" + s.waitingVisible
+                    + " finishing=" + s.finishing);
+            if (s.waitingVisible && nowVisible) {
+                mWaitingVisibleActivities.remove(s);
+                s.waitingVisible = false;
+                if (s.finishing) {
+                    // If this activity is finishing, it is sitting on top of
+                    // everyone else but we now know it is no longer needed...
+                    // so get rid of it.  Otherwise, we need to go through the
+                    // normal flow and hide it once we determine that it is
+                    // hidden by the activities in front of it.
+                    if (localLOGV) Log.v(TAG, "Before stopping, can hide: " + s);
+                    mWindowManager.setAppVisibility(s, false);
+                }
+            }
+            if (!s.waitingVisible && remove) {
+                if (localLOGV) Log.v(TAG, "Ready to stop: " + s);
+                if (stops == null) {
+                    stops = new ArrayList<HistoryRecord>();
+                }
+                stops.add(s);
+                mStoppingActivities.remove(i);
+                N--;
+                i--;
+            }
+        }
+
+        return stops;
+    }
+
+    void enableScreenAfterBoot() {
+        mWindowManager.enableScreenAfterBoot();
+    }
+
+    final void activityIdleInternal(IBinder token, boolean fromTimeout) {
+        if (localLOGV) Log.v(TAG, "Activity idle: " + token);
+
+        ArrayList<HistoryRecord> stops = null;
+        ArrayList<HistoryRecord> finishes = null;
+        ArrayList<HistoryRecord> thumbnails = null;
+        int NS = 0;
+        int NF = 0;
+        int NT = 0;
+        IApplicationThread sendThumbnail = null;
+        boolean booting = false;
+        boolean enableScreen = false;
+
+        synchronized (this) {
+            if (token != null) {
+                mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
+            }
+
+            // Get the activity record.
+            int index = indexOfTokenLocked(token, false);
+            if (index >= 0) {
+                HistoryRecord r = (HistoryRecord)mHistory.get(index);
+
+                // No longer need to keep the device awake.
+                if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
+                    mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
+                    mLaunchingActivity.release();
+                }
+
+                // We are now idle.  If someone is waiting for a thumbnail from
+                // us, we can now deliver.
+                r.idle = true;
+                scheduleAppGcsLocked();
+                if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
+                    sendThumbnail = r.app.thread;
+                    r.thumbnailNeeded = false;
+                }
+
+                // If this activity is fullscreen, set up to hide those under it.
+
+                if (DEBUG_VISBILITY) Log.v(TAG, "Idle activity for " + r);
+                ensureActivitiesVisibleLocked(null, 0);
+
+                //Log.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
+                if (!mBooted && !fromTimeout) {
+                    mBooted = true;
+                    enableScreen = true;
+                }
+            }
+
+            // Atomically retrieve all of the other things to do.
+            stops = processStoppingActivitiesLocked(true);
+            NS = stops != null ? stops.size() : 0;
+            if ((NF=mFinishingActivities.size()) > 0) {
+                finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
+                mFinishingActivities.clear();
+            }
+            if ((NT=mCancelledThumbnails.size()) > 0) {
+                thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
+                mCancelledThumbnails.clear();
+            }
+
+            booting = mBooting;
+            mBooting = false;
+        }
+
+        int i;
+
+        // Send thumbnail if requested.
+        if (sendThumbnail != null) {
+            try {
+                sendThumbnail.requestThumbnail(token);
+            } catch (Exception e) {
+                Log.w(TAG, "Exception thrown when requesting thumbnail", e);
+                sendPendingThumbnail(null, token, null, null, true);
+            }
+        }
+
+        // Stop any activities that are scheduled to do so but have been
+        // waiting for the next one to start.
+        for (i=0; i<NS; i++) {
+            HistoryRecord r = (HistoryRecord)stops.get(i);
+            synchronized (this) {
+                if (r.finishing) {
+                    finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
+                } else {
+                    stopActivityLocked(r);
+                }
+            }
+        }
+
+        // Finish any activities that are scheduled to do so but have been
+        // waiting for the next one to start.
+        for (i=0; i<NF; i++) {
+            HistoryRecord r = (HistoryRecord)finishes.get(i);
+            synchronized (this) {
+                destroyActivityLocked(r, true);
+            }
+        }
+
+        // Report back to any thumbnail receivers.
+        for (i=0; i<NT; i++) {
+            HistoryRecord r = (HistoryRecord)thumbnails.get(i);
+            sendPendingThumbnail(r, null, null, null, true);
+        }
+
+        if (booting) {
+            // Ensure that any processes we had put on hold are now started
+            // up.
+            final int NP = mProcessesOnHold.size();
+            if (NP > 0) {
+                ArrayList<ProcessRecord> procs =
+                    new ArrayList<ProcessRecord>(mProcessesOnHold);
+                for (int ip=0; ip<NP; ip++) {
+                    this.startProcessLocked(procs.get(ip), "on-hold", null);
+                }
+            }
+            if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+                // Tell anyone interested that we are done booting!
+                synchronized (this) {
+                    broadcastIntentLocked(null, null,
+                            new Intent(Intent.ACTION_BOOT_COMPLETED, null),
+                            null, null, 0, null, null,
+                            android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
+                            false, false, MY_PID, Process.SYSTEM_UID);
+                }
+            }
+        }
+
+        trimApplications();
+        //dump();
+        //mWindowManager.dump();
+
+        if (enableScreen) {
+            EventLog.writeEvent(LOG_BOOT_PROGRESS_ENABLE_SCREEN,
+                SystemClock.uptimeMillis());
+            enableScreenAfterBoot();
+        }
+    }
+
+    public final void activityPaused(IBinder token, Bundle icicle) {
+        // Refuse possible leaked file descriptors
+        if (icicle != null && icicle.hasFileDescriptors()) {
+            throw new IllegalArgumentException("File descriptors passed in Bundle");
+        }
+
+        final long origId = Binder.clearCallingIdentity();
+        activityPaused(token, icicle, false);
+        Binder.restoreCallingIdentity(origId);
+    }
+
+    final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
+        if (DEBUG_PAUSE) Log.v(
+            TAG, "Activity paused: token=" + token + ", icicle=" + icicle
+            + ", timeout=" + timeout);
+
+        HistoryRecord r = null;
+
+        synchronized (this) {
+            int index = indexOfTokenLocked(token, false);
+            if (index >= 0) {
+                r = (HistoryRecord)mHistory.get(index);
+                if (!timeout) {
+                    r.icicle = icicle;
+                    r.haveState = true;
+                }
+                mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
+                if (mPausingActivity == r) {
+                    r.state = ActivityState.PAUSED;
+                    completePauseLocked();
+                } else {
+                	EventLog.writeEvent(LOG_AM_FAILED_TO_PAUSE_ACTIVITY,
+                	        System.identityHashCode(r), r.shortComponentName, 
+                			mPausingActivity != null
+                			    ? mPausingActivity.shortComponentName : "(none)");
+                }
+            }
+        }
+    }
+
+    public final void activityStopped(IBinder token, Bitmap thumbnail,
+            CharSequence description) {
+        if (localLOGV) Log.v(
+            TAG, "Activity stopped: token=" + token);
+
+        HistoryRecord r = null;
+
+        final long origId = Binder.clearCallingIdentity();
+
+        synchronized (this) {
+            int index = indexOfTokenLocked(token, false);
+            if (index >= 0) {
+                r = (HistoryRecord)mHistory.get(index);
+                r.thumbnail = thumbnail;
+                r.description = description;
+                r.stopped = true;
+                r.state = ActivityState.STOPPED;
+                if (!r.finishing) {
+                    if (r.configDestroy) {
+                        destroyActivityLocked(r, true);
+                        resumeTopActivityLocked(null);
+                    }
+                }
+            }
+        }
+
+        if (r != null) {
+            sendPendingThumbnail(r, null, null, null, false);
+        }
+
+        trimApplications();
+
+        Binder.restoreCallingIdentity(origId);
+    }
+
+    public final void activityDestroyed(IBinder token) {
+        if (DEBUG_SWITCH) Log.v(TAG, "ACTIVITY DESTROYED: " + token);
+        synchronized (this) {
+            mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
+            
+            int index = indexOfTokenLocked(token, false);
+            if (index >= 0) {
+                HistoryRecord r = (HistoryRecord)mHistory.get(index);
+                if (r.state == ActivityState.DESTROYING) {
+                    final long origId = Binder.clearCallingIdentity();
+                    removeActivityFromHistoryLocked(r);
+                    Binder.restoreCallingIdentity(origId);
+                }
+            }
+        }
+    }
+    
+    public String getCallingPackage(IBinder token) {
+        synchronized (this) {
+            HistoryRecord r = getCallingRecordLocked(token);
+            return r != null && r.app != null ? r.app.processName : null;
+        }
+    }
+
+    public ComponentName getCallingActivity(IBinder token) {
+        synchronized (this) {
+            HistoryRecord r = getCallingRecordLocked(token);
+            return r != null ? r.intent.getComponent() : null;
+        }
+    }
+
+    private HistoryRecord getCallingRecordLocked(IBinder token) {
+        int index = indexOfTokenLocked(token, true);
+        if (index >= 0) {
+            HistoryRecord r = (HistoryRecord)mHistory.get(index);
+            if (r != null) {
+                return r.resultTo;
+            }
+        }
+        return null;
+    }
+
+    public ComponentName getActivityClassForToken(IBinder token) {
+        synchronized(this) {
+            int index = indexOfTokenLocked(token, false);
+            if (index >= 0) {
+                HistoryRecord r = (HistoryRecord)mHistory.get(index);
+                return r.intent.getComponent();
+            }
+            return null;
+        }
+    }
+
+    public String getPackageForToken(IBinder token) {
+        synchronized(this) {
+            int index = indexOfTokenLocked(token, false);
+            if (index >= 0) {
+                HistoryRecord r = (HistoryRecord)mHistory.get(index);
+                return r.packageName;
+            }
+            return null;
+        }
+    }
+
+    public IIntentSender getIntentSender(int type,
+            String packageName, IBinder token, String resultWho,
+            int requestCode, Intent intent, String resolvedType, int flags) {
+        // Refuse possible leaked file descriptors
+        if (intent != null && intent.hasFileDescriptors() == true) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        synchronized(this) {
+            int callingUid = Binder.getCallingUid();
+            try {
+                if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
+                        Process.supportsProcesses()) {
+                    int uid = ActivityThread.getPackageManager()
+                            .getPackageUid(packageName);
+                    if (uid != Binder.getCallingUid()) {
+                        String msg = "Permission Denial: getIntentSender() from pid="
+                            + Binder.getCallingPid()
+                            + ", uid=" + Binder.getCallingUid()
+                            + ", (need uid=" + uid + ")"
+                            + " is not allowed to send as package " + packageName;
+                        Log.w(TAG, msg);
+                        throw new SecurityException(msg);
+                    }
+                }
+            } catch (RemoteException e) {
+                throw new SecurityException(e);
+            }
+            HistoryRecord activity = null;
+            if (type == INTENT_SENDER_ACTIVITY_RESULT) {
+                int index = indexOfTokenLocked(token, false);
+                if (index < 0) {
+                    return null;
+                }
+                activity = (HistoryRecord)mHistory.get(index);
+                if (activity.finishing) {
+                    return null;
+                }
+            }
+
+            final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
+            final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
+            final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
+            flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
+                    |PendingIntent.FLAG_UPDATE_CURRENT);
+
+            PendingIntentRecord.Key key = new PendingIntentRecord.Key(
+                    type, packageName, activity, resultWho,
+                    requestCode, intent, resolvedType, flags);
+            WeakReference<PendingIntentRecord> ref;
+            ref = mIntentSenderRecords.get(key);
+            PendingIntentRecord rec = ref != null ? ref.get() : null;
+            if (rec != null) {
+                if (!cancelCurrent) {
+                    if (updateCurrent) {
+                        rec.key.requestIntent.replaceExtras(intent);
+                    }
+                    return rec;
+                }
+                rec.canceled = true;
+                mIntentSenderRecords.remove(key);
+            }
+            if (noCreate) {
+                return rec;
+            }
+            rec = new PendingIntentRecord(this, key, callingUid);
+            mIntentSenderRecords.put(key, rec.ref);
+            if (type == INTENT_SENDER_ACTIVITY_RESULT) {
+                if (activity.pendingResults == null) {
+                    activity.pendingResults
+                            = new HashSet<WeakReference<PendingIntentRecord>>();
+                }
+                activity.pendingResults.add(rec.ref);
+            }
+            return rec;
+        }
+    }
+
+    public void cancelIntentSender(IIntentSender sender) {
+        if (!(sender instanceof PendingIntentRecord)) {
+            return;
+        }
+        synchronized(this) {
+            PendingIntentRecord rec = (PendingIntentRecord)sender;
+            try {
+                int uid = ActivityThread.getPackageManager()
+                        .getPackageUid(rec.key.packageName);
+                if (uid != Binder.getCallingUid()) {
+                    String msg = "Permission Denial: cancelIntentSender() from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid()
+                        + " is not allowed to cancel packges "
+                        + rec.key.packageName;
+                    Log.w(TAG, msg);
+                    throw new SecurityException(msg);
+                }
+            } catch (RemoteException e) {
+                throw new SecurityException(e);
+            }
+            cancelIntentSenderLocked(rec, true);
+        }
+    }
+
+    void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
+        rec.canceled = true;
+        mIntentSenderRecords.remove(rec.key);
+        if (cleanActivity && rec.key.activity != null) {
+            rec.key.activity.pendingResults.remove(rec.ref);
+        }
+    }
+
+    public String getPackageForIntentSender(IIntentSender pendingResult) {
+        if (!(pendingResult instanceof PendingIntentRecord)) {
+            return null;
+        }
+        synchronized(this) {
+            try {
+                PendingIntentRecord res = (PendingIntentRecord)pendingResult;
+                return res.key.packageName;
+            } catch (ClassCastException e) {
+            }
+        }
+        return null;
+    }
+
+    public void setProcessLimit(int max) {
+        enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
+                "setProcessLimit()");
+        mProcessLimit = max;
+    }
+
+    public int getProcessLimit() {
+        return mProcessLimit;
+    }
+
+    void foregroundTokenDied(ForegroundToken token) {
+        synchronized (ActivityManagerService.this) {
+            synchronized (mPidsSelfLocked) {
+                ForegroundToken cur
+                    = mForegroundProcesses.get(token.pid);
+                if (cur != token) {
+                    return;
+                }
+                mForegroundProcesses.remove(token.pid);
+                ProcessRecord pr = mPidsSelfLocked.get(token.pid);
+                if (pr == null) {
+                    return;
+                }
+                pr.forcingToForeground = null;
+                pr.foregroundServices = false;
+            }
+            updateOomAdjLocked();
+        }
+    }
+    
+    public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
+        enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
+                "setProcessForeground()");
+        synchronized(this) {
+            boolean changed = false;
+            
+            synchronized (mPidsSelfLocked) {
+                ProcessRecord pr = mPidsSelfLocked.get(pid);
+                if (pr == null) {
+                    Log.w(TAG, "setProcessForeground called on unknown pid: " + pid);
+                    return;
+                }
+                ForegroundToken oldToken = mForegroundProcesses.get(pid);
+                if (oldToken != null) {
+                    oldToken.token.unlinkToDeath(oldToken, 0);
+                    mForegroundProcesses.remove(pid);
+                    pr.forcingToForeground = null;
+                    changed = true;
+                }
+                if (isForeground && token != null) {
+                    ForegroundToken newToken = new ForegroundToken() {
+                        public void binderDied() {
+                            foregroundTokenDied(this);
+                        }
+                    };
+                    newToken.pid = pid;
+                    newToken.token = token;
+                    try {
+                        token.linkToDeath(newToken, 0);
+                        mForegroundProcesses.put(pid, newToken);
+                        pr.forcingToForeground = token;
+                        changed = true;
+                    } catch (RemoteException e) {
+                        // If the process died while doing this, we will later
+                        // do the cleanup with the process death link.
+                    }
+                }
+            }
+            
+            if (changed) {
+                updateOomAdjLocked();
+            }
+        }
+    }
+    
+    // =========================================================
+    // PERMISSIONS
+    // =========================================================
+
+    static class PermissionController extends IPermissionController.Stub {
+        ActivityManagerService mActivityManagerService;
+        PermissionController(ActivityManagerService activityManagerService) {
+            mActivityManagerService = activityManagerService;
+        }
+
+        public boolean checkPermission(String permission, int pid, int uid) {
+            return mActivityManagerService.checkPermission(permission, pid,
+                    uid) == PackageManager.PERMISSION_GRANTED;
+        }
+    }
+
+    /**
+     * This can be called with or without the global lock held.
+     */
+    int checkComponentPermission(String permission, int pid, int uid,
+            int reqUid) {
+        // We might be performing an operation on behalf of an indirect binder
+        // invocation, e.g. via {@link #openContentUri}.  Check and adjust the
+        // client identity accordingly before proceeding.
+        Identity tlsIdentity = sCallerIdentity.get();
+        if (tlsIdentity != null) {
+            Log.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
+                    + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
+            uid = tlsIdentity.uid;
+            pid = tlsIdentity.pid;
+        }
+
+        // Root, system server and our own process get to do everything.
+        if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
+            !Process.supportsProcesses()) {
+            return PackageManager.PERMISSION_GRANTED;
+        }
+        // If the target requires a specific UID, always fail for others.
+        if (reqUid >= 0 && uid != reqUid) {
+            return PackageManager.PERMISSION_DENIED;
+        }
+        if (permission == null) {
+            return PackageManager.PERMISSION_GRANTED;
+        }
+        try {
+            return ActivityThread.getPackageManager()
+                    .checkUidPermission(permission, uid);
+        } catch (RemoteException e) {
+            // Should never happen, but if it does... deny!
+            Log.e(TAG, "PackageManager is dead?!?", e);
+        }
+        return PackageManager.PERMISSION_DENIED;
+    }
+
+    /**
+     * As the only public entry point for permissions checking, this method
+     * can enforce the semantic that requesting a check on a null global
+     * permission is automatically denied.  (Internally a null permission
+     * string is used when calling {@link #checkComponentPermission} in cases
+     * when only uid-based security is needed.)
+     * 
+     * This can be called with or without the global lock held.
+     */
+    public int checkPermission(String permission, int pid, int uid) {
+        if (permission == null) {
+            return PackageManager.PERMISSION_DENIED;
+        }
+        return checkComponentPermission(permission, pid, uid, -1);
+    }
+
+    /**
+     * Binder IPC calls go through the public entry point.
+     * This can be called with or without the global lock held.
+     */
+    int checkCallingPermission(String permission) {
+        return checkPermission(permission,
+                Binder.getCallingPid(),
+                Binder.getCallingUid());
+    }
+
+    /**
+     * This can be called with or without the global lock held.
+     */
+    void enforceCallingPermission(String permission, String func) {
+        if (checkCallingPermission(permission)
+                == PackageManager.PERMISSION_GRANTED) {
+            return;
+        }
+
+        String msg = "Permission Denial: " + func + " from pid="
+                + Binder.getCallingPid()
+                + ", uid=" + Binder.getCallingUid()
+                + " requires " + permission;
+        Log.w(TAG, msg);
+        throw new SecurityException(msg);
+    }
+
+    private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
+            ProviderInfo pi, int uid, int modeFlags) {
+        try {
+            if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+                if ((pi.readPermission != null) &&
+                        (pm.checkUidPermission(pi.readPermission, uid)
+                                != PackageManager.PERMISSION_GRANTED)) {
+                    return false;
+                }
+            }
+            if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+                if ((pi.writePermission != null) &&
+                        (pm.checkUidPermission(pi.writePermission, uid)
+                                != PackageManager.PERMISSION_GRANTED)) {
+                    return false;
+                }
+            }
+            return true;
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    private final boolean checkUriPermissionLocked(Uri uri, int uid,
+            int modeFlags) {
+        // Root gets to do everything.
+        if (uid == 0 || !Process.supportsProcesses()) {
+            return true;
+        }
+        HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
+        if (perms == null) return false;
+        UriPermission perm = perms.get(uri);
+        if (perm == null) return false;
+        return (modeFlags&perm.modeFlags) == modeFlags;
+    }
+
+    public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
+        // Another redirected-binder-call permissions check as in
+        // {@link checkComponentPermission}.
+        Identity tlsIdentity = sCallerIdentity.get();
+        if (tlsIdentity != null) {
+            uid = tlsIdentity.uid;
+            pid = tlsIdentity.pid;
+        }
+
+        // Our own process gets to do everything.
+        if (pid == MY_PID) {
+            return PackageManager.PERMISSION_GRANTED;
+        }
+        synchronized(this) {
+            return checkUriPermissionLocked(uri, uid, modeFlags)
+                    ? PackageManager.PERMISSION_GRANTED
+                    : PackageManager.PERMISSION_DENIED;
+        }
+    }
+
+    private void grantUriPermissionLocked(int callingUid,
+            String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        if (modeFlags == 0) {
+            return;
+        }
+
+        final IPackageManager pm = ActivityThread.getPackageManager();
+
+        // If this is not a content: uri, we can't do anything with it.
+        if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+            return;
+        }
+
+        String name = uri.getAuthority();
+        ProviderInfo pi = null;
+        ContentProviderRecord cpr
+                = (ContentProviderRecord)mProvidersByName.get(name);
+        if (cpr != null) {
+            pi = cpr.info;
+        } else {
+            try {
+                pi = pm.resolveContentProvider(name,
+                        PackageManager.GET_URI_PERMISSION_PATTERNS);
+            } catch (RemoteException ex) {
+            }
+        }
+        if (pi == null) {
+            Log.w(TAG, "No content provider found for: " + name);
+            return;
+        }
+
+        int targetUid;
+        try {
+            targetUid = pm.getPackageUid(targetPkg);
+            if (targetUid < 0) {
+                return;
+            }
+        } catch (RemoteException ex) {
+            return;
+        }
+
+        // First...  does the target actually need this permission?
+        if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
+            // No need to grant the target this permission.
+            return;
+        }
+
+        // Second...  maybe someone else has already granted the
+        // permission?
+        if (checkUriPermissionLocked(uri, targetUid, modeFlags)) {
+            // No need to grant the target this permission.
+            return;
+        }
+
+        // Third...  is the provider allowing granting of URI permissions?
+        if (!pi.grantUriPermissions) {
+            throw new SecurityException("Provider " + pi.packageName
+                    + "/" + pi.name
+                    + " does not allow granting of Uri permissions (uri "
+                    + uri + ")");
+        }
+        if (pi.uriPermissionPatterns != null) {
+            final int N = pi.uriPermissionPatterns.length;
+            boolean allowed = false;
+            for (int i=0; i<N; i++) {
+                if (pi.uriPermissionPatterns[i] != null
+                        && pi.uriPermissionPatterns[i].match(uri.getPath())) {
+                    allowed = true;
+                    break;
+                }
+            }
+            if (!allowed) {
+                throw new SecurityException("Provider " + pi.packageName
+                        + "/" + pi.name
+                        + " does not allow granting of permission to path of Uri "
+                        + uri);
+            }
+        }
+
+        // Fourth...  does the caller itself have permission to access
+        // this uri?
+        if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
+            if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
+                throw new SecurityException("Uid " + callingUid
+                        + " does not have permission to uri " + uri);
+            }
+        }
+
+        // Okay!  So here we are: the caller has the assumed permission
+        // to the uri, and the target doesn't.  Let's now give this to
+        // the target.
+
+        HashMap<Uri, UriPermission> targetUris
+                = mGrantedUriPermissions.get(targetUid);
+        if (targetUris == null) {
+            targetUris = new HashMap<Uri, UriPermission>();
+            mGrantedUriPermissions.put(targetUid, targetUris);
+        }
+
+        UriPermission perm = targetUris.get(uri);
+        if (perm == null) {
+            perm = new UriPermission(targetUid, uri);
+            targetUris.put(uri, perm);
+
+        }
+        perm.modeFlags |= modeFlags;
+        if (activity == null) {
+            perm.globalModeFlags |= modeFlags;
+        } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+            perm.readActivities.add(activity);
+            if (activity.readUriPermissions == null) {
+                activity.readUriPermissions = new HashSet<UriPermission>();
+            }
+            activity.readUriPermissions.add(perm);
+        } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+            perm.writeActivities.add(activity);
+            if (activity.writeUriPermissions == null) {
+                activity.writeUriPermissions = new HashSet<UriPermission>();
+            }
+            activity.writeUriPermissions.add(perm);
+        }
+    }
+
+    private void grantUriPermissionFromIntentLocked(int callingUid,
+            String targetPkg, Intent intent, HistoryRecord activity) {
+        if (intent == null) {
+            return;
+        }
+        Uri data = intent.getData();
+        if (data == null) {
+            return;
+        }
+        grantUriPermissionLocked(callingUid, targetPkg, data,
+                intent.getFlags(), activity);
+    }
+
+    public void grantUriPermission(IApplicationThread caller, String targetPkg,
+            Uri uri, int modeFlags) {
+        synchronized(this) {
+            final ProcessRecord r = getRecordForAppLocked(caller);
+            if (r == null) {
+                throw new SecurityException("Unable to find app for caller "
+                        + caller
+                        + " when granting permission to uri " + uri);
+            }
+            if (targetPkg == null) {
+                Log.w(TAG, "grantUriPermission: null target");
+                return;
+            }
+            if (uri == null) {
+                Log.w(TAG, "grantUriPermission: null uri");
+                return;
+            }
+
+            grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
+                    null);
+        }
+    }
+
+    private void removeUriPermissionIfNeededLocked(UriPermission perm) {
+        if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
+                |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
+            HashMap<Uri, UriPermission> perms
+                    = mGrantedUriPermissions.get(perm.uid);
+            if (perms != null) {
+                perms.remove(perm.uri);
+                if (perms.size() == 0) {
+                    mGrantedUriPermissions.remove(perm.uid);
+                }
+            }
+        }
+    }
+
+    private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
+        if (activity.readUriPermissions != null) {
+            for (UriPermission perm : activity.readUriPermissions) {
+                perm.readActivities.remove(activity);
+                if (perm.readActivities.size() == 0 && (perm.globalModeFlags
+                        &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
+                    perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+                    removeUriPermissionIfNeededLocked(perm);
+                }
+            }
+        }
+        if (activity.writeUriPermissions != null) {
+            for (UriPermission perm : activity.writeUriPermissions) {
+                perm.writeActivities.remove(activity);
+                if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
+                        &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
+                    perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+                    removeUriPermissionIfNeededLocked(perm);
+                }
+            }
+        }
+    }
+
+    private void revokeUriPermissionLocked(int callingUid, Uri uri,
+            int modeFlags) {
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        if (modeFlags == 0) {
+            return;
+        }
+
+        final IPackageManager pm = ActivityThread.getPackageManager();
+
+        final String authority = uri.getAuthority();
+        ProviderInfo pi = null;
+        ContentProviderRecord cpr
+                = (ContentProviderRecord)mProvidersByName.get(authority);
+        if (cpr != null) {
+            pi = cpr.info;
+        } else {
+            try {
+                pi = pm.resolveContentProvider(authority,
+                        PackageManager.GET_URI_PERMISSION_PATTERNS);
+            } catch (RemoteException ex) {
+            }
+        }
+        if (pi == null) {
+            Log.w(TAG, "No content provider found for: " + authority);
+            return;
+        }
+
+        // Does the caller have this permission on the URI?
+        if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
+            // Right now, if you are not the original owner of the permission,
+            // you are not allowed to revoke it.
+            //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
+                throw new SecurityException("Uid " + callingUid
+                        + " does not have permission to uri " + uri);
+            //}
+        }
+
+        // Go through all of the permissions and remove any that match.
+        final List<String> SEGMENTS = uri.getPathSegments();
+        if (SEGMENTS != null) {
+            final int NS = SEGMENTS.size();
+            int N = mGrantedUriPermissions.size();
+            for (int i=0; i<N; i++) {
+                HashMap<Uri, UriPermission> perms
+                        = mGrantedUriPermissions.valueAt(i);
+                Iterator<UriPermission> it = perms.values().iterator();
+            toploop:
+                while (it.hasNext()) {
+                    UriPermission perm = it.next();
+                    Uri targetUri = perm.uri;
+                    if (!authority.equals(targetUri.getAuthority())) {
+                        continue;
+                    }
+                    List<String> targetSegments = targetUri.getPathSegments();
+                    if (targetSegments == null) {
+                        continue;
+                    }
+                    if (targetSegments.size() < NS) {
+                        continue;
+                    }
+                    for (int j=0; j<NS; j++) {
+                        if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
+                            continue toploop;
+                        }
+                    }
+                    perm.clearModes(modeFlags);
+                    if (perm.modeFlags == 0) {
+                        it.remove();
+                    }
+                }
+                if (perms.size() == 0) {
+                    mGrantedUriPermissions.remove(
+                            mGrantedUriPermissions.keyAt(i));
+                    N--;
+                    i--;
+                }
+            }
+        }
+    }
+
+    public void revokeUriPermission(IApplicationThread caller, Uri uri,
+            int modeFlags) {
+        synchronized(this) {
+            final ProcessRecord r = getRecordForAppLocked(caller);
+            if (r == null) {
+                throw new SecurityException("Unable to find app for caller "
+                        + caller
+                        + " when revoking permission to uri " + uri);
+            }
+            if (uri == null) {
+                Log.w(TAG, "revokeUriPermission: null uri");
+                return;
+            }
+
+            modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+            if (modeFlags == 0) {
+                return;
+            }
+
+            final IPackageManager pm = ActivityThread.getPackageManager();
+
+            final String authority = uri.getAuthority();
+            ProviderInfo pi = null;
+            ContentProviderRecord cpr
+                    = (ContentProviderRecord)mProvidersByName.get(authority);
+            if (cpr != null) {
+                pi = cpr.info;
+            } else {
+                try {
+                    pi = pm.resolveContentProvider(authority,
+                            PackageManager.GET_URI_PERMISSION_PATTERNS);
+                } catch (RemoteException ex) {
+                }
+            }
+            if (pi == null) {
+                Log.w(TAG, "No content provider found for: " + authority);
+                return;
+            }
+
+            revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
+        }
+    }
+
+    public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
+        synchronized (this) {
+            ProcessRecord app =
+                who != null ? getRecordForAppLocked(who) : null;
+            if (app == null) return;
+
+            Message msg = Message.obtain();
+            msg.what = WAIT_FOR_DEBUGGER_MSG;
+            msg.obj = app;
+            msg.arg1 = waiting ? 1 : 0;
+            mHandler.sendMessage(msg);
+        }
+    }
+
+    public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
+        outInfo.availMem = Process.getFreeMemory();
+        outInfo.threshold = SECONDARY_SERVER_MEM;
+        outInfo.lowMemory = outInfo.availMem <
+                (SECONDARY_SERVER_MEM + ((HIDDEN_APP_MEM-SECONDARY_SERVER_MEM)/2));
+    }
+    
+    // =========================================================
+    // TASK MANAGEMENT
+    // =========================================================
+
+    public List getTasks(int maxNum, int flags,
+                         IThumbnailReceiver receiver) {
+        ArrayList list = new ArrayList();
+
+        PendingThumbnailsRecord pending = null;
+        IApplicationThread topThumbnail = null;
+        HistoryRecord topRecord = null;
+
+        synchronized(this) {
+            if (localLOGV) Log.v(
+                TAG, "getTasks: max=" + maxNum + ", flags=" + flags
+                + ", receiver=" + receiver);
+
+            if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
+                    != PackageManager.PERMISSION_GRANTED) {
+                if (receiver != null) {
+                    // If the caller wants to wait for pending thumbnails,
+                    // it ain't gonna get them.
+                    try {
+                        receiver.finished();
+                    } catch (RemoteException ex) {
+                    }
+                }
+                String msg = "Permission Denial: getTasks() from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid()
+                        + " requires " + android.Manifest.permission.GET_TASKS;
+                Log.w(TAG, msg);
+                throw new SecurityException(msg);
+            }
+
+            int pos = mHistory.size()-1;
+            HistoryRecord next =
+                pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
+            HistoryRecord top = null;
+            CharSequence topDescription = null;
+            TaskRecord curTask = null;
+            int numActivities = 0;
+            int numRunning = 0;
+            while (pos >= 0 && maxNum > 0) {
+                final HistoryRecord r = next;
+                pos--;
+                next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
+
+                // Initialize state for next task if needed.
+                if (top == null ||
+                        (top.state == ActivityState.INITIALIZING
+                            && top.task == r.task)) {
+                    top = r;
+                    topDescription = r.description;
+                    curTask = r.task;
+                    numActivities = numRunning = 0;
+                }
+
+                // Add 'r' into the current task.
+                numActivities++;
+                if (r.app != null && r.app.thread != null) {
+                    numRunning++;
+                }
+                if (topDescription == null) {
+                    topDescription = r.description;
+                }
+
+                if (localLOGV) Log.v(
+                    TAG, r.intent.getComponent().flattenToShortString()
+                    + ": task=" + r.task);
+
+                // If the next one is a different task, generate a new
+                // TaskInfo entry for what we have.
+                if (next == null || next.task != curTask) {
+                    ActivityManager.RunningTaskInfo ci
+                            = new ActivityManager.RunningTaskInfo();
+                    ci.id = curTask.taskId;
+                    ci.baseActivity = r.intent.getComponent();
+                    ci.topActivity = top.intent.getComponent();
+                    ci.thumbnail = top.thumbnail;
+                    ci.description = topDescription;
+                    ci.numActivities = numActivities;
+                    ci.numRunning = numRunning;
+                    //System.out.println(
+                    //    "#" + maxNum + ": " + " descr=" + ci.description);
+                    if (ci.thumbnail == null && receiver != null) {
+                        if (localLOGV) Log.v(
+                            TAG, "State=" + top.state + "Idle=" + top.idle
+                            + " app=" + top.app
+                            + " thr=" + (top.app != null ? top.app.thread : null));
+                        if (top.state == ActivityState.RESUMED
+                                || top.state == ActivityState.PAUSING) {
+                            if (top.idle && top.app != null
+                                && top.app.thread != null) {
+                                topRecord = top;
+                                topThumbnail = top.app.thread;
+                            } else {
+                                top.thumbnailNeeded = true;
+                            }
+                        }
+                        if (pending == null) {
+                            pending = new PendingThumbnailsRecord(receiver);
+                        }
+                        pending.pendingRecords.add(top);
+                    }
+                    list.add(ci);
+                    maxNum--;
+                    top = null;
+                }
+            }
+
+            if (pending != null) {
+                mPendingThumbnails.add(pending);
+            }
+        }
+
+        if (localLOGV) Log.v(TAG, "We have pending thumbnails: " + pending);
+
+        if (topThumbnail != null) {
+            if (localLOGV) Log.v(TAG, "Requesting top thumbnail");
+            try {
+                topThumbnail.requestThumbnail(topRecord);
+            } catch (Exception e) {
+                Log.w(TAG, "Exception thrown when requesting thumbnail", e);
+                sendPendingThumbnail(null, topRecord, null, null, true);
+            }
+        }
+
+        if (pending == null && receiver != null) {
+            // In this case all thumbnails were available and the client
+            // is being asked to be told when the remaining ones come in...
+            // which is unusually, since the top-most currently running
+            // activity should never have a canned thumbnail!  Oh well.
+            try {
+                receiver.finished();
+            } catch (RemoteException ex) {
+            }
+        }
+
+        return list;
+    }
+
+    public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
+            int flags) {
+        synchronized (this) {
+            enforceCallingPermission(android.Manifest.permission.GET_TASKS,
+                    "getRecentTasks()");
+
+            final int N = mRecentTasks.size();
+            ArrayList<ActivityManager.RecentTaskInfo> res
+                    = new ArrayList<ActivityManager.RecentTaskInfo>(
+                            maxNum < N ? maxNum : N);
+            for (int i=0; i<N && maxNum > 0; i++) {
+                TaskRecord tr = mRecentTasks.get(i);
+                if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
+                        || (tr.intent == null)
+                        || ((tr.intent.getFlags()
+                                &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
+                    ActivityManager.RecentTaskInfo rti
+                            = new ActivityManager.RecentTaskInfo();
+                    rti.id = tr.numActivities > 0 ? tr.taskId : -1;
+                    rti.baseIntent = new Intent(
+                            tr.intent != null ? tr.intent : tr.affinityIntent);
+                    rti.origActivity = tr.origActivity;
+                    res.add(rti);
+                    maxNum--;
+                }
+            }
+            return res;
+        }
+    }
+
+    private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
+        int j;
+        TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task; 
+        TaskRecord jt = startTask;
+        
+        // First look backwards
+        for (j=startIndex-1; j>=0; j--) {
+            HistoryRecord r = (HistoryRecord)mHistory.get(j);
+            if (r.task != jt) {
+                jt = r.task;
+                if (affinity.equals(jt.affinity)) {
+                    return j;
+                }
+            }
+        }
+        
+        // Now look forwards
+        final int N = mHistory.size();
+        jt = startTask;
+        for (j=startIndex+1; j<N; j++) {
+            HistoryRecord r = (HistoryRecord)mHistory.get(j);
+            if (r.task != jt) {
+                if (affinity.equals(jt.affinity)) {
+                    return j;
+                }
+                jt = r.task;
+            }
+        }
+        
+        // Might it be at the top?
+        if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
+            return N-1;
+        }
+        
+        return -1;
+    }
+    
+    /**
+     * Perform a reset of the given task, if needed as part of launching it.
+     * Returns the new HistoryRecord at the top of the task.
+     */
+    private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
+            HistoryRecord newActivity) {
+        boolean forceReset = (newActivity.info.flags
+                &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
+        if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
+            if ((newActivity.info.flags
+                    &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
+                forceReset = true;
+            }
+        }
+        
+        final TaskRecord task = taskTop.task;
+        
+        // We are going to move through the history list so that we can look
+        // at each activity 'target' with 'below' either the interesting
+        // activity immediately below it in the stack or null.
+        HistoryRecord target = null;
+        int targetI = 0;
+        int taskTopI = -1;
+        int replyChainEnd = -1;
+        int lastReparentPos = -1;
+        for (int i=mHistory.size()-1; i>=-1; i--) {
+            HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
+            
+            if (below != null && below.finishing) {
+                continue;
+            }
+            if (target == null) {
+                target = below;
+                targetI = i;
+                // If we were in the middle of a reply chain before this
+                // task, it doesn't appear like the root of the chain wants
+                // anything interesting, so drop it.
+                replyChainEnd = -1;
+                continue;
+            }
+        
+            final int flags = target.info.flags;
+            
+            final boolean finishOnTaskLaunch =
+                (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
+            final boolean allowTaskReparenting =
+                (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
+            
+            if (target.task == task) {
+                // We are inside of the task being reset...  we'll either
+                // finish this activity, push it out for another task,
+                // or leave it as-is.  We only do this
+                // for activities that are not the root of the task (since
+                // if we finish the root, we may no longer have the task!).
+                if (taskTopI < 0) {
+                    taskTopI = targetI;
+                }
+                if (below != null && below.task == task) {
+                    final boolean clearWhenTaskReset =
+                            (target.intent.getFlags()
+                                    &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
+                    if (!finishOnTaskLaunch && target.resultTo != null) {
+                        // If this activity is sending a reply to a previous
+                        // activity, we can't do anything with it now until
+                        // we reach the start of the reply chain.
+                        // XXX note that we are assuming the result is always
+                        // to the previous activity, which is almost always
+                        // the case but we really shouldn't count on.
+                        if (replyChainEnd < 0) {
+                            replyChainEnd = targetI;
+                        }
+                    } else if (!finishOnTaskLaunch && allowTaskReparenting
+                            && target.taskAffinity != null
+                            && !target.taskAffinity.equals(task.affinity)) {
+                        // If this activity has an affinity for another
+                        // task, then we need to move it out of here.  We will
+                        // move it as far out of the way as possible, to the
+                        // bottom of the activity stack.  This also keeps it
+                        // correctly ordered with any activities we previously
+                        // moved.
+                        HistoryRecord p = (HistoryRecord)mHistory.get(0);
+                        if (target.taskAffinity != null
+                                && target.taskAffinity.equals(p.task.affinity)) {
+                            // If the activity currently at the bottom has the
+                            // same task affinity as the one we are moving,
+                            // then merge it into the same task.
+                            target.task = p.task;
+                            if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
+                                    + " out to bottom task " + p.task);
+                        } else {
+                            mCurTask++;
+                            if (mCurTask <= 0) {
+                                mCurTask = 1;
+                            }
+                            target.task = new TaskRecord(mCurTask, target.info, null,
+                                    (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
+                            target.task.affinityIntent = target.intent;
+                            if (DEBUG_TASKS) Log.v(TAG, "Start pushing activity " + target
+                                    + " out to new task " + target.task);
+                        }
+                        mWindowManager.setAppGroupId(target, task.taskId);
+                        if (replyChainEnd < 0) {
+                            replyChainEnd = targetI;
+                        }
+                        int dstPos = 0;
+                        for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
+                            p = (HistoryRecord)mHistory.get(srcPos);
+                            if (p.finishing) {
+                                continue;
+                            }
+                            if (DEBUG_TASKS) Log.v(TAG, "Pushing next activity " + p
+                                    + " out to target's task " + target.task);
+                            task.numActivities--;
+                            p.task = target.task;
+                            target.task.numActivities++;
+                            mHistory.remove(srcPos);
+                            mHistory.add(dstPos, p);
+                            mWindowManager.moveAppToken(dstPos, p);
+                            mWindowManager.setAppGroupId(p, p.task.taskId);
+                            dstPos++;
+                            if (VALIDATE_TOKENS) {
+                                mWindowManager.validateAppTokens(mHistory);
+                            }
+                            i++;
+                        }
+                        if (taskTop == p) {
+                            taskTop = below;
+                        }
+                        if (taskTopI == replyChainEnd) {
+                            taskTopI = -1;
+                        }
+                        replyChainEnd = -1;
+                        addRecentTask(target.task);
+                    } else if (forceReset || finishOnTaskLaunch
+                            || clearWhenTaskReset) {
+                        // If the activity should just be removed -- either
+                        // because it asks for it, or the task should be
+                        // cleared -- then finish it and anything that is
+                        // part of its reply chain.
+                        if (clearWhenTaskReset) {
+                            // In this case, we want to finish this activity
+                            // and everything above it, so be sneaky and pretend
+                            // like these are all in the reply chain.
+                            replyChainEnd = targetI+1;
+                            while (replyChainEnd < mHistory.size() &&
+                                    ((HistoryRecord)mHistory.get(
+                                                replyChainEnd)).task == task) {
+                                replyChainEnd++;
+                            }
+                            replyChainEnd--;
+                        } else if (replyChainEnd < 0) {
+                            replyChainEnd = targetI;
+                        }
+                        HistoryRecord p = null;
+                        for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
+                            p = (HistoryRecord)mHistory.get(srcPos);
+                            if (p.finishing) {
+                                continue;
+                            }
+                            if (finishActivityLocked(p, srcPos,
+                                    Activity.RESULT_CANCELED, null, "reset")) {
+                                replyChainEnd--;
+                                srcPos--;
+                            }
+                        }
+                        if (taskTop == p) {
+                            taskTop = below;
+                        }
+                        if (taskTopI == replyChainEnd) {
+                            taskTopI = -1;
+                        }
+                        replyChainEnd = -1;
+                    } else {
+                        // If we were in the middle of a chain, well the
+                        // activity that started it all doesn't want anything
+                        // special, so leave it all as-is.
+                        replyChainEnd = -1;
+                    }
+                } else {
+                    // Reached the bottom of the task -- any reply chain
+                    // should be left as-is.
+                    replyChainEnd = -1;
+                }
+                
+            } else if (target.resultTo != null) {
+                // If this activity is sending a reply to a previous
+                // activity, we can't do anything with it now until
+                // we reach the start of the reply chain.
+                // XXX note that we are assuming the result is always
+                // to the previous activity, which is almost always
+                // the case but we really shouldn't count on.
+                if (replyChainEnd < 0) {
+                    replyChainEnd = targetI;
+                }
+
+            } else if (taskTopI >= 0 && allowTaskReparenting
+                    && task.affinity != null
+                    && task.affinity.equals(target.taskAffinity)) {
+                // We are inside of another task...  if this activity has
+                // an affinity for our task, then either remove it if we are
+                // clearing or move it over to our task.  Note that
+                // we currently punt on the case where we are resetting a
+                // task that is not at the top but who has activities above
+                // with an affinity to it...  this is really not a normal
+                // case, and we will need to later pull that task to the front
+                // and usually at that point we will do the reset and pick
+                // up those remaining activities.  (This only happens if
+                // someone starts an activity in a new task from an activity
+                // in a task that is not currently on top.)
+                if (forceReset || finishOnTaskLaunch) {
+                    if (replyChainEnd < 0) {
+                        replyChainEnd = targetI;
+                    }
+                    HistoryRecord p = null;
+                    for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
+                        p = (HistoryRecord)mHistory.get(srcPos);
+                        if (p.finishing) {
+                            continue;
+                        }
+                        if (finishActivityLocked(p, srcPos,
+                                Activity.RESULT_CANCELED, null, "reset")) {
+                            taskTopI--;
+                            lastReparentPos--;
+                            replyChainEnd--;
+                            srcPos--;
+                        }
+                    }
+                    replyChainEnd = -1;
+                } else {
+                    if (replyChainEnd < 0) {
+                        replyChainEnd = targetI;
+                    }
+                    for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
+                        HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
+                        if (p.finishing) {
+                            continue;
+                        }
+                        if (lastReparentPos < 0) {
+                            lastReparentPos = taskTopI;
+                            taskTop = p;
+                        } else {
+                            lastReparentPos--;
+                        }
+                        mHistory.remove(srcPos);
+                        p.task.numActivities--;
+                        p.task = task;
+                        mHistory.add(lastReparentPos, p);
+                        if (DEBUG_TASKS) Log.v(TAG, "Pulling activity " + p
+                                + " in to resetting task " + task);
+                        task.numActivities++;
+                        mWindowManager.moveAppToken(lastReparentPos, p);
+                        mWindowManager.setAppGroupId(p, p.task.taskId);
+                        if (VALIDATE_TOKENS) {
+                            mWindowManager.validateAppTokens(mHistory);
+                        }
+                    }
+                    replyChainEnd = -1;
+                    
+                    // Now we've moved it in to place...  but what if this is
+                    // a singleTop activity and we have put it on top of another
+                    // instance of the same activity?  Then we drop the instance
+                    // below so it remains singleTop.
+                    if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
+                        for (int j=lastReparentPos-1; j>=0; j--) {
+                            HistoryRecord p = (HistoryRecord)mHistory.get(j);
+                            if (p.finishing) {
+                                continue;
+                            }
+                            if (p.intent.getComponent().equals(target.intent.getComponent())) {
+                                if (finishActivityLocked(p, j,
+                                        Activity.RESULT_CANCELED, null, "replace")) {
+                                    taskTopI--;
+                                    lastReparentPos--;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            
+            target = below;
+            targetI = i;
+        }
+        
+        return taskTop;
+    }
+    
+    /**
+     * TODO: Add mWatcher hook
+     */
+    public void moveTaskToFront(int task) {
+        enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
+                "moveTaskToFront()");
+
+        synchronized(this) {
+            final long origId = Binder.clearCallingIdentity();
+            try {
+                int N = mRecentTasks.size();
+                for (int i=0; i<N; i++) {
+                    TaskRecord tr = mRecentTasks.get(i);
+                    if (tr.taskId == task) {
+                        moveTaskToFrontLocked(tr);
+                        return;
+                    }
+                }
+                for (int i=mHistory.size()-1; i>=0; i--) {
+                    HistoryRecord hr = (HistoryRecord)mHistory.get(i);
+                    if (hr.task.taskId == task) {
+                        moveTaskToFrontLocked(hr.task);
+                        return;
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
+        }
+    }
+
+    private final void moveTaskToFrontLocked(TaskRecord tr) {
+        if (DEBUG_SWITCH) Log.v(TAG, "moveTaskToFront: " + tr);
+
+        final int task = tr.taskId;
+        int top = mHistory.size()-1;
+
+        if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
+            // nothing to do!
+            return;
+        }
+
+        if (DEBUG_TRANSITION) Log.v(TAG,
+                "Prepare to front transition: task=" + tr);
+        mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
+        
+        ArrayList moved = new ArrayList();
+
+        // Applying the affinities may have removed entries from the history,
+        // so get the size again.
+        top = mHistory.size()-1;
+        int pos = top;
+
+        // Shift all activities with this task up to the top
+        // of the stack, keeping them in the same internal order.
+        while (pos >= 0) {
+            HistoryRecord r = (HistoryRecord)mHistory.get(pos);
+            if (localLOGV) Log.v(
+                TAG, "At " + pos + " ckp " + r.task + ": " + r);
+            boolean first = true;
+            if (r.task.taskId == task) {
+                if (localLOGV) Log.v(TAG, "Removing and adding at " + top);
+                mHistory.remove(pos);
+                mHistory.add(top, r);
+                moved.add(0, r);
+                top--;
+                if (first) {
+                    addRecentTask(r.task);
+                    first = false;
+                }
+            }
+            pos--;
+        }
+
+        mWindowManager.moveAppTokensToTop(moved);
+        if (VALIDATE_TOKENS) {
+            mWindowManager.validateAppTokens(mHistory);
+        }
+
+        finishTaskMove(task);
+        EventLog.writeEvent(LOG_TASK_TO_FRONT, task);
+    }
+
+    private final void finishTaskMove(int task) {
+        resumeTopActivityLocked(null);
+    }
+
+    public void moveTaskToBack(int task) {
+        enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
+                "moveTaskToBack()");
+
+        synchronized(this) {
+            final long origId = Binder.clearCallingIdentity();
+            moveTaskToBackLocked(task);
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    /**
+     * Moves an activity, and all of the other activities within the same task, to the bottom
+     * of the history stack.  The activity's order within the task is unchanged.
+     * 
+     * @param token A reference to the activity we wish to move
+     * @param nonRoot If false then this only works if the activity is the root
+     *                of a task; if true it will work for any activity in a task.
+     * @return Returns true if the move completed, false if not.
+     */
+    public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
+        synchronized(this) {
+            final long origId = Binder.clearCallingIdentity();
+            int taskId = getTaskForActivityLocked(token, !nonRoot);
+            if (taskId >= 0) {
+                return moveTaskToBackLocked(taskId);
+            }
+            Binder.restoreCallingIdentity(origId);
+        }
+        return false;
+    }
+
+    /**
+     * Worker method for rearranging history stack.  Implements the function of moving all 
+     * activities for a specific task (gathering them if disjoint) into a single group at the 
+     * bottom of the stack.
+     * 
+     * If a watcher is installed, the action is preflighted and the watcher has an opportunity
+     * to premeptively cancel the move.
+     * 
+     * @param task The taskId to collect and move to the bottom.
+     * @return Returns true if the move completed, false if not.
+     */
+    private final boolean moveTaskToBackLocked(int task) {
+        Log.i(TAG, "moveTaskToBack: " + task);
+        
+        // If we have a watcher, preflight the move before committing to it.  First check
+        // for *other* available tasks, but if none are available, then try again allowing the
+        // current task to be selected.
+        if (mWatcher != null) {
+            HistoryRecord next = topRunningActivityLocked(null, task);
+            if (next == null) {
+                next = topRunningActivityLocked(null, 0);
+            }
+            if (next != null) {
+                // ask watcher if this is allowed
+                boolean moveOK = true;
+                try {
+                    moveOK = mWatcher.activityResuming(next.packageName);
+                } catch (RemoteException e) {
+                    mWatcher = null;
+                }
+                if (!moveOK) {
+                    return false;
+                }
+            }
+        }
+
+        ArrayList moved = new ArrayList();
+
+        if (DEBUG_TRANSITION) Log.v(TAG,
+                "Prepare to back transition: task=" + task);
+        mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
+        
+        final int N = mHistory.size();
+        int bottom = 0;
+        int pos = 0;
+
+        // Shift all activities with this task down to the bottom
+        // of the stack, keeping them in the same internal order.
+        while (pos < N) {
+            HistoryRecord r = (HistoryRecord)mHistory.get(pos);
+            if (localLOGV) Log.v(
+                TAG, "At " + pos + " ckp " + r.task + ": " + r);
+            if (r.task.taskId == task) {
+                if (localLOGV) Log.v(TAG, "Removing and adding at " + (N-1));
+                mHistory.remove(pos);
+                mHistory.add(bottom, r);
+                moved.add(r);
+                bottom++;
+            }
+            pos++;
+        }
+
+        mWindowManager.moveAppTokensToBottom(moved);
+        if (VALIDATE_TOKENS) {
+            mWindowManager.validateAppTokens(mHistory);
+        }
+
+        finishTaskMove(task);
+        return true;
+    }
+
+    public void moveTaskBackwards(int task) {
+        enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
+                "moveTaskBackwards()");
+
+        synchronized(this) {
+            final long origId = Binder.clearCallingIdentity();
+            moveTaskBackwardsLocked(task);
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    private final void moveTaskBackwardsLocked(int task) {
+        Log.e(TAG, "moveTaskBackwards not yet implemented!");
+    }
+
+    public int getTaskForActivity(IBinder token, boolean onlyRoot) {
+        synchronized(this) {
+            return getTaskForActivityLocked(token, onlyRoot);
+        }
+    }
+
+    int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
+        final int N = mHistory.size();
+        TaskRecord lastTask = null;
+        for (int i=0; i<N; i++) {
+            HistoryRecord r = (HistoryRecord)mHistory.get(i);
+            if (r == token) {
+                if (!onlyRoot || lastTask != r.task) {
+                    return r.task.taskId;
+                }
+                return -1;
+            }
+            lastTask = r.task;
+        }
+
+        return -1;
+    }
+
+    /**
+     * Returns the top activity in any existing task matching the given
+     * Intent.  Returns null if no such task is found.
+     */
+    private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
+        ComponentName cls = intent.getComponent();
+        if (info.targetActivity != null) {
+            cls = new ComponentName(info.packageName, info.targetActivity);
+        }
+
+        TaskRecord cp = null;
+
+        final int N = mHistory.size();
+        for (int i=(N-1); i>=0; i--) {
+            HistoryRecord r = (HistoryRecord)mHistory.get(i);
+            if (!r.finishing && r.task != cp
+                    && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
+                cp = r.task;
+                //Log.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
+                //        + "/aff=" + r.task.affinity + " to new cls="
+                //        + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
+                if (r.task.affinity != null) {
+                    if (r.task.affinity.equals(info.taskAffinity)) {
+                        //Log.i(TAG, "Found matching affinity!");
+                        return r;
+                    }
+                } else if (r.task.intent != null
+                        && r.task.intent.getComponent().equals(cls)) {
+                    //Log.i(TAG, "Found matching class!");
+                    //dump();
+                    //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
+                    return r;
+                } else if (r.task.affinityIntent != null
+                        && r.task.affinityIntent.getComponent().equals(cls)) {
+                    //Log.i(TAG, "Found matching class!");
+                    //dump();
+                    //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
+                    return r;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the first activity (starting from the top of the stack) that
+     * is the same as the given activity.  Returns null if no such activity
+     * is found.
+     */
+    private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
+        ComponentName cls = intent.getComponent();
+        if (info.targetActivity != null) {
+            cls = new ComponentName(info.packageName, info.targetActivity);
+        }
+
+        final int N = mHistory.size();
+        for (int i=(N-1); i>=0; i--) {
+            HistoryRecord r = (HistoryRecord)mHistory.get(i);
+            if (!r.finishing) {
+                if (r.intent.getComponent().equals(cls)) {
+                    //Log.i(TAG, "Found matching class!");
+                    //dump();
+                    //Log.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
+                    return r;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public void finishOtherInstances(IBinder token, ComponentName className) {
+        synchronized(this) {
+            final long origId = Binder.clearCallingIdentity();
+
+            int N = mHistory.size();
+            TaskRecord lastTask = null;
+            for (int i=0; i<N; i++) {
+                HistoryRecord r = (HistoryRecord)mHistory.get(i);
+                if (r.realActivity.equals(className)
+                        && r != token && lastTask != r.task) {
+                    if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
+                            null, "others")) {
+                        i--;
+                        N--;
+                    }
+                }
+                lastTask = r.task;
+            }
+
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    // =========================================================
+    // THUMBNAILS
+    // =========================================================
+
+    public void reportThumbnail(IBinder token,
+            Bitmap thumbnail, CharSequence description) {
+        //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
+        final long origId = Binder.clearCallingIdentity();
+        sendPendingThumbnail(null, token, thumbnail, description, true);
+        Binder.restoreCallingIdentity(origId);
+    }
+
+    final void sendPendingThumbnail(HistoryRecord r, IBinder token,
+            Bitmap thumbnail, CharSequence description, boolean always) {
+        TaskRecord task = null;
+        ArrayList receivers = null;
+
+        //System.out.println("Send pending thumbnail: " + r);
+
+        synchronized(this) {
+            if (r == null) {
+                int index = indexOfTokenLocked(token, false);
+                if (index < 0) {
+                    return;
+                }
+                r = (HistoryRecord)mHistory.get(index);
+            }
+            if (thumbnail == null) {
+                thumbnail = r.thumbnail;
+                description = r.description;
+            }
+            if (thumbnail == null && !always) {
+                // If there is no thumbnail, and this entry is not actually
+                // going away, then abort for now and pick up the next
+                // thumbnail we get.
+                return;
+            }
+            task = r.task;
+
+            int N = mPendingThumbnails.size();
+            int i=0;
+            while (i<N) {
+                PendingThumbnailsRecord pr =
+                    (PendingThumbnailsRecord)mPendingThumbnails.get(i);
+                //System.out.println("Looking in " + pr.pendingRecords);
+                if (pr.pendingRecords.remove(r)) {
+                    if (receivers == null) {
+                        receivers = new ArrayList();
+                    }
+                    receivers.add(pr);
+                    if (pr.pendingRecords.size() == 0) {
+                        pr.finished = true;
+                        mPendingThumbnails.remove(i);
+                        N--;
+                        continue;
+                    }
+                }
+                i++;
+            }
+        }
+
+        if (receivers != null) {
+            final int N = receivers.size();
+            for (int i=0; i<N; i++) {
+                try {
+                    PendingThumbnailsRecord pr =
+                        (PendingThumbnailsRecord)receivers.get(i);
+                    pr.receiver.newThumbnail(
+                        task != null ? task.taskId : -1, thumbnail, description);
+                    if (pr.finished) {
+                        pr.receiver.finished();
+                    }
+                } catch (Exception e) {
+                    Log.w(TAG, "Exception thrown when sending thumbnail", e);
+                }
+            }
+        }
+    }
+
+    // =========================================================
+    // CONTENT PROVIDERS
+    // =========================================================
+
+    private final List generateApplicationProvidersLocked(ProcessRecord app) {
+        List providers = null;
+        try {
+            providers = ActivityThread.getPackageManager().
+                queryContentProviders(app.processName, app.info.uid,
+                        PackageManager.GET_SHARED_LIBRARY_FILES
+                        | PackageManager.GET_URI_PERMISSION_PATTERNS);
+        } catch (RemoteException ex) {
+        }
+        if (providers != null) {
+            final int N = providers.size();
+            for (int i=0; i<N; i++) {
+                ProviderInfo cpi =
+                    (ProviderInfo)providers.get(i);
+                ContentProviderRecord cpr =
+                    (ContentProviderRecord)mProvidersByClass.get(cpi.name);
+                if (cpr == null) {
+                    cpr = new ContentProviderRecord(cpi, app.info);
+                    mProvidersByClass.put(cpi.name, cpr);
+                }
+                app.pubProviders.put(cpi.name, cpr);
+                app.addPackage(cpi.applicationInfo.packageName);
+            }
+        }
+        return providers;
+    }
+
+    private final String checkContentProviderPermissionLocked(
+            ProviderInfo cpi, ProcessRecord r, int mode) {
+        final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
+        final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
+        if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
+                cpi.exported ? -1 : cpi.applicationInfo.uid)
+                == PackageManager.PERMISSION_GRANTED
+                && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
+            return null;
+        }
+        if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
+                cpi.exported ? -1 : cpi.applicationInfo.uid)
+                == PackageManager.PERMISSION_GRANTED) {
+            return null;
+        }
+        String msg = "Permission Denial: opening provider " + cpi.name
+                + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
+                + ", uid=" + callingUid + ") requires "
+                + cpi.readPermission + " or " + cpi.writePermission;
+        Log.w(TAG, msg);
+        return msg;
+    }
+
+    private final ContentProviderHolder getContentProviderImpl(
+        IApplicationThread caller, String name) {
+        ContentProviderRecord cpr;
+        ProviderInfo cpi = null;
+
+        synchronized(this) {
+            ProcessRecord r = null;
+            if (caller != null) {
+                r = getRecordForAppLocked(caller);
+                if (r == null) {
+                    throw new SecurityException(
+                            "Unable to find app for caller " + caller
+                          + " (pid=" + Binder.getCallingPid()
+                          + ") when getting content provider " + name);
+                }
+            }
+
+            // First check if this content provider has been published...
+            cpr = (ContentProviderRecord)mProvidersByName.get(name);
+            if (cpr != null) {
+                cpi = cpr.info;
+                if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
+                    return new ContentProviderHolder(cpi,
+                            cpi.readPermission != null
+                                    ? cpi.readPermission : cpi.writePermission);
+                }
+
+                if (r != null && cpr.canRunHere(r)) {
+                    // This provider has been published or is in the process
+                    // of being published...  but it is also allowed to run
+                    // in the caller's process, so don't make a connection
+                    // and just let the caller instantiate its own instance.
+                    if (cpr.provider != null) {
+                        // don't give caller the provider object, it needs
+                        // to make its own.
+                        cpr = new ContentProviderRecord(cpr);
+                    }
+                    return cpr;
+                }
+
+                final long origId = Binder.clearCallingIdentity();
+
+                // In this case the provider is a single instance, so we can
+                // return it right away.
+                if (r != null) {
+                    r.conProviders.add(cpr);
+                    cpr.clients.add(r);
+                } else {
+                    cpr.externals++;
+                }
+
+                if (cpr.app != null) {
+                    updateOomAdjLocked(cpr.app);
+                }
+
+                Binder.restoreCallingIdentity(origId);
+
+            } else {
+                try {
+                    cpi = ActivityThread.getPackageManager().
+                        resolveContentProvider(name, PackageManager.GET_URI_PERMISSION_PATTERNS);
+                } catch (RemoteException ex) {
+                }
+                if (cpi == null) {
+                    return null;
+                }
+
+                if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
+                    return new ContentProviderHolder(cpi,
+                            cpi.readPermission != null
+                                    ? cpi.readPermission : cpi.writePermission);
+                }
+
+                cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
+                final boolean firstClass = cpr == null;
+                if (firstClass) {
+                    try {
+                        ApplicationInfo ai =
+                            ActivityThread.getPackageManager().
+                                getApplicationInfo(
+                                        cpi.applicationInfo.packageName,
+                                        PackageManager.GET_SHARED_LIBRARY_FILES);
+                        if (ai == null) {
+                            Log.w(TAG, "No package info for content provider "
+                                    + cpi.name);
+                            return null;
+                        }
+                        cpr = new ContentProviderRecord(cpi, ai);
+                    } catch (RemoteException ex) {
+                        // pm is in same process, this will never happen.
+                    }
+                }
+
+                if (r != null && cpr.canRunHere(r)) {
+                    // If this is a multiprocess provider, then just return its
+                    // info and allow the caller to instantiate it.  Only do
+                    // this if the provider is the same user as the caller's
+                    // process, or can run as root (so can be in any process).
+                    return cpr;
+                }
+
+                if (false) {
+                    RuntimeException e = new RuntimeException("foo");
+                    //Log.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
+                    //      + " pruid " + ai.uid + "): " + cpi.className, e);
+                }
+
+                // This is single process, and our app is now connecting to it.
+                // See if we are already in the process of launching this
+                // provider.
+                final int N = mLaunchingProviders.size();
+                int i;
+                for (i=0; i<N; i++) {
+                    if (mLaunchingProviders.get(i) == cpr) {
+                        break;
+                    }
+                    if (false) {
+                        final ContentProviderRecord rec =
+                            (ContentProviderRecord)mLaunchingProviders.get(i);
+                        if (rec.info.name.equals(cpr.info.name)) {
+                            cpr = rec;
+                            break;
+                        }
+                    }
+                }
+
+                // If the provider is not already being launched, then get it
+                // started.
+                if (i >= N) {
+                    final long origId = Binder.clearCallingIdentity();
+                    ProcessRecord proc = startProcessLocked(cpi.processName,
+                            cpr.appInfo, false, 0, "content provider",
+                            new ComponentName(cpi.applicationInfo.packageName,
+                                    cpi.name));
+                    if (proc == null) {
+                        Log.w(TAG, "Unable to launch app "
+                                + cpi.applicationInfo.packageName + "/"
+                                + cpi.applicationInfo.uid + " for provider "
+                                + name + ": process is bad");
+                        return null;
+                    }
+                    cpr.launchingApp = proc;
+                    mLaunchingProviders.add(cpr);
+                    Binder.restoreCallingIdentity(origId);
+                }
+
+                // Make sure the provider is published (the same provider class
+                // may be published under multiple names).
+                if (firstClass) {
+                    mProvidersByClass.put(cpi.name, cpr);
+                }
+                mProvidersByName.put(name, cpr);
+
+                if (r != null) {
+                    r.conProviders.add(cpr);
+                    cpr.clients.add(r);
+                } else {
+                    cpr.externals++;
+                }
+            }
+        }
+
+        // Wait for the provider to be published...
+        synchronized (cpr) {
+            while (cpr.provider == null) {
+                if (cpr.launchingApp == null) {
+                    Log.w(TAG, "Unable to launch app "
+                            + cpi.applicationInfo.packageName + "/"
+                            + cpi.applicationInfo.uid + " for provider "
+                            + name + ": launching app became null");
+                    EventLog.writeEvent(LOG_AM_PROVIDER_LOST_PROCESS,
+                            cpi.applicationInfo.packageName,
+                            cpi.applicationInfo.uid, name);
+                    return null;
+                }
+                try {
+                    cpr.wait();
+                } catch (InterruptedException ex) {
+                }
+            }
+        }
+        return cpr;
+    }
+
+    public final ContentProviderHolder getContentProvider(
+            IApplicationThread caller, String name) {
+        if (caller == null) {
+            String msg = "null IApplicationThread when getting content provider "
+                    + name;
+            Log.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+
+        return getContentProviderImpl(caller, name);
+    }
+
+    private ContentProviderHolder getContentProviderExternal(String name) {
+        return getContentProviderImpl(null, name);
+    }
+
+    /**
+     * Drop a content provider from a ProcessRecord's bookkeeping
+     * @param cpr
+     */
+    public void removeContentProvider(IApplicationThread caller, String name) {
+        synchronized (this) {
+            ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
+            if(cpr == null) {
+                //remove from mProvidersByClass
+                if(localLOGV) Log.v(TAG, name+" content provider not found in providers list");
+                return;
+            }
+            final ProcessRecord r = getRecordForAppLocked(caller);
+            if (r == null) {
+                throw new SecurityException(
+                        "Unable to find app for caller " + caller +
+                        " when removing content provider " + name);
+            }
+            //update content provider record entry info
+            ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
+            if(localLOGV) Log.v(TAG, "Removing content provider requested by "+
+                    r.info.processName+" from process "+localCpr.appInfo.processName);
+            if(localCpr.appInfo.processName ==  r.info.processName) {
+                //should not happen. taken care of as a local provider
+                if(localLOGV) Log.v(TAG, "local provider doing nothing Ignoring other names");
+                return;
+            } else {
+                localCpr.clients.remove(r);
+                r.conProviders.remove(localCpr);
+            }
+            updateOomAdjLocked();
+        }
+    }
+
+    private void removeContentProviderExternal(String name) {
+        synchronized (this) {
+            ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
+            if(cpr == null) {
+                //remove from mProvidersByClass
+                if(localLOGV) Log.v(TAG, name+" content provider not found in providers list");
+                return;
+            }
+
+            //update content provider record entry info
+            ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
+            localCpr.externals--;
+            if (localCpr.externals < 0) {
+                Log.e(TAG, "Externals < 0 for content provider " + localCpr);
+            }
+            updateOomAdjLocked();
+        }
+    }
+    
+    public final void publishContentProviders(IApplicationThread caller,
+            List<ContentProviderHolder> providers) {
+        if (providers == null) {
+            return;
+        }
+
+        synchronized(this) {
+            final ProcessRecord r = getRecordForAppLocked(caller);
+            if (r == null) {
+                throw new SecurityException(
+                        "Unable to find app for caller " + caller
+                      + " (pid=" + Binder.getCallingPid()
+                      + ") when publishing content providers");
+            }
+
+            final long origId = Binder.clearCallingIdentity();
+
+            final int N = providers.size();
+            for (int i=0; i<N; i++) {
+                ContentProviderHolder src = providers.get(i);
+                if (src == null || src.info == null || src.provider == null) {
+                    continue;
+                }
+                ContentProviderRecord dst =
+                    (ContentProviderRecord)r.pubProviders.get(src.info.name);
+                if (dst != null) {
+                    mProvidersByClass.put(dst.info.name, dst);
+                    String names[] = dst.info.authority.split(";");
+                    for (int j = 0; j < names.length; j++) {
+                        mProvidersByName.put(names[j], dst);
+                    }
+
+                    int NL = mLaunchingProviders.size();
+                    int j;
+                    for (j=0; j<NL; j++) {
+                        if (mLaunchingProviders.get(j) == dst) {
+                            mLaunchingProviders.remove(j);
+                            j--;
+                            NL--;
+                        }
+                    }
+                    synchronized (dst) {
+                        dst.provider = src.provider;
+                        dst.app = r;
+                        dst.notifyAll();
+                    }
+                    updateOomAdjLocked(r);
+                }
+            }
+
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    public static final void installSystemProviders() {
+        ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
+        List providers = mSelf.generateApplicationProvidersLocked(app);
+        mSystemThread.installSystemProviders(providers);
+    }
+
+    // =========================================================
+    // GLOBAL MANAGEMENT
+    // =========================================================
+
+    final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
+            ApplicationInfo info, String customProcess) {
+        String proc = customProcess != null ? customProcess : info.processName;
+        BatteryStatsImpl.Uid.Proc ps = null;
+        BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+        synchronized (stats) {
+            ps = stats.getProcessStatsLocked(info.uid, proc);
+        }
+        return new ProcessRecord(ps, thread, info, proc);
+    }
+
+    final ProcessRecord addAppLocked(ApplicationInfo info) {
+        ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
+
+        if (app == null) {
+            app = newProcessRecordLocked(null, info, null);
+            mProcessNames.put(info.processName, info.uid, app);
+            updateLRUListLocked(app, true);
+        }
+
+        if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
+                == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
+            app.persistent = true;
+            app.maxAdj = CORE_SERVER_ADJ;
+        }
+        if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
+            mPersistentStartingProcesses.add(app);
+            startProcessLocked(app, "added application", app.processName);
+        }
+
+        return app;
+    }
+
+    public void unhandledBack() {
+        enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
+                "unhandledBack()");
+
+        synchronized(this) {
+            int count = mHistory.size();
+            if (Config.LOGD) Log.d(
+                TAG, "Performing unhandledBack(): stack size = " + count);
+            if (count > 1) {
+                final long origId = Binder.clearCallingIdentity();
+                finishActivityLocked((HistoryRecord)mHistory.get(count-1),
+                        count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
+                Binder.restoreCallingIdentity(origId);
+            }
+        }
+    }
+
+    public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
+        String name = uri.getAuthority();
+        ContentProviderHolder cph = getContentProviderExternal(name);
+        ParcelFileDescriptor pfd = null;
+        if (cph != null) {
+            // We record the binder invoker's uid in thread-local storage before
+            // going to the content provider to open the file.  Later, in the code
+            // that handles all permissions checks, we look for this uid and use
+            // that rather than the Activity Manager's own uid.  The effect is that
+            // we do the check against the caller's permissions even though it looks
+            // to the content provider like the Activity Manager itself is making
+            // the request.
+            sCallerIdentity.set(new Identity(
+                    Binder.getCallingPid(), Binder.getCallingUid()));
+            try {
+                pfd = cph.provider.openFile(uri, "r");
+            } catch (FileNotFoundException e) {
+                // do nothing; pfd will be returned null
+            } finally {
+                // Ensure that whatever happens, we clean up the identity state
+                sCallerIdentity.remove();
+            }
+
+            // We've got the fd now, so we're done with the provider.
+            removeContentProviderExternal(name);
+        } else {
+            Log.d(TAG, "Failed to get provider for authority '" + name + "'");
+        }
+        return pfd;
+    }
+
+    public void goingToSleep() {
+        synchronized(this) {
+            mSleeping = true;
+            mWindowManager.setEventDispatching(false);
+
+            if (mResumedActivity != null) {
+                pauseIfSleepingLocked();
+            } else {
+                Log.w(TAG, "goingToSleep with no resumed activity!");
+            }
+        }
+    }
+
+    void pauseIfSleepingLocked() {
+        if (mSleeping) {
+            if (!mGoingToSleep.isHeld()) {
+                mGoingToSleep.acquire();
+                if (mLaunchingActivity.isHeld()) {
+                    mLaunchingActivity.release();
+                    mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
+                }
+            }
+
+            // If we are not currently pausing an activity, get the current
+            // one to pause.  If we are pausing one, we will just let that stuff
+            // run and release the wake lock when all done.
+            if (mPausingActivity == null) {
+                if (DEBUG_PAUSE) Log.v(TAG, "Sleep needs to pause...");
+                if (DEBUG_USER_LEAVING) Log.v(TAG, "Sleep => pause with userLeaving=false");
+                startPausingLocked(false, true);
+            }
+        }
+    }
+    
+    public void wakingUp() {
+        synchronized(this) {
+            if (mGoingToSleep.isHeld()) {
+                mGoingToSleep.release();
+            }
+            mWindowManager.setEventDispatching(true);
+            mSleeping = false;
+            resumeTopActivityLocked(null);
+        }
+    }
+
+    public void setDebugApp(String packageName, boolean waitForDebugger,
+            boolean persistent) {
+        enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
+                "setDebugApp()");
+
+        // Note that this is not really thread safe if there are multiple
+        // callers into it at the same time, but that's not a situation we
+        // care about.
+        if (persistent) {
+            final ContentResolver resolver = mContext.getContentResolver();
+            Settings.System.putString(
+                resolver, Settings.System.DEBUG_APP,
+                packageName);
+            Settings.System.putInt(
+                resolver, Settings.System.WAIT_FOR_DEBUGGER,
+                waitForDebugger ? 1 : 0);
+        }
+
+        synchronized (this) {
+            if (!persistent) {
+                mOrigDebugApp = mDebugApp;
+                mOrigWaitForDebugger = mWaitForDebugger;
+            }
+            mDebugApp = packageName;
+            mWaitForDebugger = waitForDebugger;
+            mDebugTransient = !persistent;
+            if (packageName != null) {
+                final long origId = Binder.clearCallingIdentity();
+                uninstallPackageLocked(packageName, -1, false);
+                Binder.restoreCallingIdentity(origId);
+            }
+        }
+    }
+
+    public void setAlwaysFinish(boolean enabled) {
+        enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
+                "setAlwaysFinish()");
+
+        Settings.System.putInt(
+                mContext.getContentResolver(),
+                Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
+        
+        synchronized (this) {
+            mAlwaysFinishActivities = enabled;
+        }
+    }
+
+    public void setActivityWatcher(IActivityWatcher watcher) {
+        enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
+                "setActivityWatcher()");
+        synchronized (this) {
+            mWatcher = watcher;
+        }
+    }
+
+    public final void enterSafeMode() {
+        synchronized(this) {
+            // It only makes sense to do this before the system is ready
+            // and started launching other packages.
+            if (!mSystemReady) {
+                try {
+                    ActivityThread.getPackageManager().enterSafeMode();
+                } catch (RemoteException e) {
+                }
+
+                View v = LayoutInflater.from(mContext).inflate(
+                        com.android.internal.R.layout.safe_mode, null);
+                WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
+                lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
+                lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
+                lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
+                lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
+                lp.format = v.getBackground().getOpacity();
+                lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+                ((WindowManager)mContext.getSystemService(
+                        Context.WINDOW_SERVICE)).addView(v, lp);
+            }
+        }
+    }
+
+    public void noteWakeupAlarm(IIntentSender sender) {
+        if (!(sender instanceof PendingIntentRecord)) {
+            return;
+        }
+        BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+        synchronized (stats) {
+            if (mBatteryStatsService.isOnBattery()) {
+                mBatteryStatsService.enforceCallingPermission();
+                PendingIntentRecord rec = (PendingIntentRecord)sender;
+                int MY_UID = Binder.getCallingUid();
+                int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+                BatteryStatsImpl.Uid.Pkg pkg =
+                    stats.getPackageStatsLocked(uid, rec.key.packageName);
+                pkg.incWakeupsLocked();
+            }
+        }
+    }
+
+    public boolean killPidsForMemory(int[] pids) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("killPidsForMemory only available to the system");
+        }
+        
+        // XXX Note: don't acquire main activity lock here, because the window
+        // manager calls in with its locks held.
+        
+        boolean killed = false;
+        synchronized (mPidsSelfLocked) {
+            int[] types = new int[pids.length];
+            int worstType = 0;
+            for (int i=0; i<pids.length; i++) {
+                ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
+                if (proc != null) {
+                    int type = proc.setAdj;
+                    types[i] = type;
+                    if (type > worstType) {
+                        worstType = type;
+                    }
+                }
+            }
+            
+            // If the worse oom_adj is somewhere in the hidden proc LRU range,
+            // then constrain it so we will kill all hidden procs.
+            if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
+                worstType = HIDDEN_APP_MIN_ADJ;
+            }
+            Log.w(TAG, "Killing processes for memory at adjustment " + worstType);
+            for (int i=0; i<pids.length; i++) {
+                ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
+                if (proc == null) {
+                    continue;
+                }
+                int adj = proc.setAdj;
+                if (adj >= worstType) {
+                    Log.w(TAG, "Killing for memory: " + proc + " (adj "
+                            + adj + ")");
+                    EventLog.writeEvent(LOG_AM_KILL_FOR_MEMORY, proc.pid,
+                            proc.processName, adj);
+                    killed = true;
+                    Process.killProcess(pids[i]);
+                }
+            }
+        }
+        return killed;
+    }
+    
+    public void reportPss(IApplicationThread caller, int pss) {
+        Watchdog.PssRequestor req;
+        String name;
+        ProcessRecord callerApp;
+        synchronized (this) {
+            if (caller == null) {
+                return;
+            }
+            callerApp = getRecordForAppLocked(caller);
+            if (callerApp == null) {
+                return;
+            }
+            callerApp.lastPss = pss;
+            req = callerApp;
+            name = callerApp.processName;
+        }
+        Watchdog.getInstance().reportPss(req, name, pss);
+        if (!callerApp.persistent) {
+            removeRequestedPss(callerApp);
+        }
+    }
+    
+    public void requestPss(Runnable completeCallback) {
+        ArrayList<ProcessRecord> procs;
+        synchronized (this) {
+            mRequestPssCallback = completeCallback;
+            mRequestPssList.clear();
+            for (int i=mLRUProcesses.size()-1; i>=0; i--) {
+                ProcessRecord proc = mLRUProcesses.get(i);
+                if (!proc.persistent) {
+                    mRequestPssList.add(proc);
+                }
+            }
+            procs = new ArrayList<ProcessRecord>(mRequestPssList);
+        }
+        
+        int oldPri = Process.getThreadPriority(Process.myTid()); 
+        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+        for (int i=procs.size()-1; i>=0; i--) {
+            ProcessRecord proc = procs.get(i);
+            proc.lastPss = 0;
+            proc.requestPss();
+        }
+        Process.setThreadPriority(oldPri);
+    }
+    
+    void removeRequestedPss(ProcessRecord proc) {
+        Runnable callback = null;
+        synchronized (this) {
+            if (mRequestPssList.remove(proc)) {
+                if (mRequestPssList.size() == 0) {
+                    callback = mRequestPssCallback;
+                    mRequestPssCallback = null;
+                }
+            }
+        }
+        
+        if (callback != null) {
+            callback.run();
+        }
+    }
+    
+    public void collectPss(Watchdog.PssStats stats) {
+        stats.mEmptyPss = 0;
+        stats.mEmptyCount = 0;
+        stats.mBackgroundPss = 0;
+        stats.mBackgroundCount = 0;
+        stats.mServicePss = 0;
+        stats.mServiceCount = 0;
+        stats.mVisiblePss = 0;
+        stats.mVisibleCount = 0;
+        stats.mForegroundPss = 0;
+        stats.mForegroundCount = 0;
+        stats.mNoPssCount = 0;
+        synchronized (this) {
+            int i;
+            int NPD = mProcDeaths.length < stats.mProcDeaths.length
+                    ? mProcDeaths.length : stats.mProcDeaths.length;
+            int aggr = 0;
+            for (i=0; i<NPD; i++) {
+                aggr += mProcDeaths[i];
+                stats.mProcDeaths[i] = aggr;
+            }
+            while (i<stats.mProcDeaths.length) {
+                stats.mProcDeaths[i] = 0;
+                i++;
+            }
+            
+            for (i=mLRUProcesses.size()-1; i>=0; i--) {
+                ProcessRecord proc = mLRUProcesses.get(i);
+                if (proc.persistent) {
+                    continue;
+                }
+                //Log.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
+                if (proc.lastPss == 0) {
+                    stats.mNoPssCount++;
+                    continue;
+                }
+                if (proc.setAdj == EMPTY_APP_ADJ) {
+                    stats.mEmptyPss += proc.lastPss;
+                    stats.mEmptyCount++;
+                } else if (proc.setAdj == CONTENT_PROVIDER_ADJ) {
+                    stats.mEmptyPss += proc.lastPss;
+                    stats.mEmptyCount++;
+                } else if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
+                    stats.mBackgroundPss += proc.lastPss;
+                    stats.mBackgroundCount++;
+                } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
+                    stats.mVisiblePss += proc.lastPss;
+                    stats.mVisibleCount++;
+                } else {
+                    stats.mForegroundPss += proc.lastPss;
+                    stats.mForegroundCount++;
+                }
+            }
+        }
+    }
+    
+    public final void startRunning(String pkg, String cls, String action,
+            String data) {
+        synchronized(this) {
+            if (mStartRunning) {
+                return;
+            }
+            mStartRunning = true;
+            mTopComponent = pkg != null && cls != null
+                    ? new ComponentName(pkg, cls) : null;
+            mTopAction = action != null ? action : Intent.ACTION_MAIN;
+            mTopData = data;
+            if (!mSystemReady) {
+                return;
+            }
+        }
+
+        systemReady();
+    }
+
+    private void retrieveSettings() {
+        final ContentResolver resolver = mContext.getContentResolver();
+        String debugApp = Settings.System.getString(
+            resolver, Settings.System.DEBUG_APP);
+        boolean waitForDebugger = Settings.System.getInt(
+            resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
+        boolean alwaysFinishActivities = Settings.System.getInt(
+            resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
+
+        Configuration configuration = new Configuration();
+        Settings.System.getConfiguration(resolver, configuration);
+
+        synchronized (this) {
+            mDebugApp = mOrigDebugApp = debugApp;
+            mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
+            mAlwaysFinishActivities = alwaysFinishActivities;
+            // This happens before any activities are started, so we can
+            // change mConfiguration in-place.
+            mConfiguration.updateFrom(configuration);
+        }
+    }
+
+    public boolean testIsSystemReady() {
+        // no need to synchronize(this) just to read & return the value
+        return mSystemReady;
+    }
+    
+    public void systemReady() {
+        // In the simulator, startRunning will never have been called, which
+        // normally sets a few crucial variables. Do it here instead.
+        if (!Process.supportsProcesses()) {
+            mStartRunning = true;
+            mTopAction = Intent.ACTION_MAIN;
+        }
+
+        synchronized(this) {
+            if (mSystemReady) {
+                return;
+            }
+            mSystemReady = true;
+            if (!mStartRunning) {
+                return;
+            }
+        }
+
+        if (Config.LOGD) Log.d(TAG, "Start running!");
+        EventLog.writeEvent(LOG_BOOT_PROGRESS_AMS_READY,
+            SystemClock.uptimeMillis());
+
+        synchronized(this) {
+            if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
+                ResolveInfo ri = mContext.getPackageManager()
+                        .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
+                                0);
+                CharSequence errorMsg = null;
+                if (ri != null) {
+                    ActivityInfo ai = ri.activityInfo;
+                    ApplicationInfo app = ai.applicationInfo;
+                    if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
+                        mTopAction = Intent.ACTION_FACTORY_TEST;
+                        mTopData = null;
+                        mTopComponent = new ComponentName(app.packageName,
+                                ai.name);
+                    } else {
+                        errorMsg = mContext.getResources().getText(
+                                com.android.internal.R.string.factorytest_not_system);
+                    }
+                } else {
+                    errorMsg = mContext.getResources().getText(
+                            com.android.internal.R.string.factorytest_no_action);
+                }
+                if (errorMsg != null) {
+                    mTopAction = null;
+                    mTopData = null;
+                    mTopComponent = null;
+                    Message msg = Message.obtain();
+                    msg.what = SHOW_FACTORY_ERROR_MSG;
+                    msg.getData().putCharSequence("msg", errorMsg);
+                    mHandler.sendMessage(msg);
+                }
+            }
+        }
+
+        retrieveSettings();
+
+        synchronized (this) {
+            if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+                try {
+                    List apps = ActivityThread.getPackageManager().
+                        getPersistentApplications(PackageManager.GET_SHARED_LIBRARY_FILES);
+                    if (apps != null) {
+                        int N = apps.size();
+                        int i;
+                        for (i=0; i<N; i++) {
+                            ApplicationInfo info
+                                = (ApplicationInfo)apps.get(i);
+                            if (info != null &&
+                                    !info.packageName.equals("android")) {
+                                addAppLocked(info);
+                            }
+                        }
+                    }
+                } catch (RemoteException ex) {
+                    // pm is in same process, this will never happen.
+                }
+            }
+
+            try {
+                if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
+                    Message msg = Message.obtain();
+                    msg.what = SHOW_UID_ERROR_MSG;
+                    mHandler.sendMessage(msg);
+                }
+            } catch (RemoteException e) {
+            }
+
+            // Start up initial activity.
+            mBooting = true;
+            resumeTopActivityLocked(null);
+        }
+    }
+
+    boolean makeAppCrashingLocked(ProcessRecord app,
+            String tag, String shortMsg, String longMsg, byte[] crashData) {
+        app.crashing = true;
+        app.crashingReport = generateProcessError(app, 
+                ActivityManager.ProcessErrorStateInfo.CRASHED, tag, shortMsg, longMsg, crashData);
+        startAppProblemLocked(app);
+        app.stopFreezingAllLocked();
+        return handleAppCrashLocked(app);
+    }
+
+    void makeAppNotRespondingLocked(ProcessRecord app,
+            String tag, String shortMsg, String longMsg, byte[] crashData) {
+        app.notResponding = true;
+        app.notRespondingReport = generateProcessError(app, 
+                ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING, tag, shortMsg, longMsg, 
+                crashData);
+        startAppProblemLocked(app);
+        app.stopFreezingAllLocked();
+    }
+    
+    /**
+     * Generate a process error record, suitable for attachment to a ProcessRecord.
+     * 
+     * @param app The ProcessRecord in which the error occurred.
+     * @param condition Crashing, Application Not Responding, etc.  Values are defined in 
+     *                      ActivityManager.AppErrorStateInfo
+     * @param tag The tag that was passed into handleApplicationError().  Typically the classname.
+     * @param shortMsg Short message describing the crash.
+     * @param longMsg Long message describing the crash.
+     * @param crashData Raw data passed into handleApplicationError().  Typically a stack trace.
+     * 
+     * @return Returns a fully-formed AppErrorStateInfo record.
+     */
+    private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app, 
+            int condition, String tag, String shortMsg, String longMsg, byte[] crashData) {
+        ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
+        
+        report.condition = condition;
+        report.processName = app.processName;
+        report.pid = app.pid;
+        report.uid = app.info.uid;
+        report.tag = tag;
+        report.shortMsg = shortMsg;
+        report.longMsg = longMsg;
+        report.crashData = crashData;
+
+        return report;
+    }
+
+    void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog,
+            boolean crashed) {
+        synchronized (this) {
+            app.crashing = false;
+            app.crashingReport = null;
+            app.notResponding = false;
+            app.notRespondingReport = null;
+            if (app.anrDialog == fromDialog) {
+                app.anrDialog = null;
+            }
+            if (app.waitDialog == fromDialog) {
+                app.waitDialog = null;
+            }
+            if (app.pid > 0 && app.pid != MY_PID) {
+                if (crashed) {
+                    handleAppCrashLocked(app);
+                }
+                Log.i(ActivityManagerService.TAG, "Killing process "
+                        + app.processName
+                        + " (pid=" + app.pid + ") at user's request");
+                Process.killProcess(app.pid);
+            }
+            
+        }
+    }
+    
+    boolean handleAppCrashLocked(ProcessRecord app) {
+        long now = SystemClock.uptimeMillis();
+
+        Long crashTime = mProcessCrashTimes.get(app.info.processName,
+                app.info.uid);
+        if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
+            // This process loses!
+            Log.w(TAG, "Process " + app.info.processName
+                    + " has crashed too many times: killing!");
+            EventLog.writeEvent(LOG_AM_PROCESS_CRASHED_TOO_MUCH,
+                    app.info.processName, app.info.uid);
+            killServicesLocked(app, false);
+            for (int i=mHistory.size()-1; i>=0; i--) {
+                HistoryRecord r = (HistoryRecord)mHistory.get(i);
+                if (r.app == app) {
+                    if (Config.LOGD) Log.d(
+                        TAG, "  Force finishing activity "
+                        + r.intent.getComponent().flattenToShortString());
+                    finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
+                }
+            }
+            if (!app.persistent) {
+                // We don't want to start this process again until the user
+                // explicitly does so...  but for persistent process, we really
+                // need to keep it running.  If a persistent process is actually
+                // repeatedly crashing, then badness for everyone.
+                EventLog.writeEvent(LOG_AM_PROCESS_BAD, app.info.uid,
+                        app.info.processName);
+                mBadProcesses.put(app.info.processName, app.info.uid, now);
+                app.bad = true;
+                mProcessCrashTimes.remove(app.info.processName, app.info.uid);
+                app.removed = true;
+                removeProcessLocked(app, false);
+                return false;
+            }
+        }
+
+        // Bump up the crash count of any services currently running in the proc.
+        if (app.services.size() != 0) {
+            // Any services running in the application need to be placed
+            // back in the pending list.
+            Iterator it = app.services.iterator();
+            while (it.hasNext()) {
+                ServiceRecord sr = (ServiceRecord)it.next();
+                sr.crashCount++;
+            }
+        }
+        
+        mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
+        return true;
+    }
+
+    void startAppProblemLocked(ProcessRecord app) {
+        skipCurrentReceiverLocked(app);
+    }
+
+    void skipCurrentReceiverLocked(ProcessRecord app) {
+        boolean reschedule = false;
+        BroadcastRecord r = app.curReceiver;
+        if (r != null) {
+            // The current broadcast is waiting for this app's receiver
+            // to be finished.  Looks like that's not going to happen, so
+            // let the broadcast continue.
+            logBroadcastReceiverDiscard(r);
+            finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
+                    r.resultExtras, r.resultAbort, true);
+            reschedule = true;
+        }
+        r = mPendingBroadcast;
+        if (r != null && r.curApp == app) {
+            if (DEBUG_BROADCAST) Log.v(TAG,
+                    "skip & discard pending app " + r);
+            logBroadcastReceiverDiscard(r);
+            finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
+                    r.resultExtras, r.resultAbort, true);
+            reschedule = true;
+        }
+        if (reschedule) {
+            scheduleBroadcastsLocked();
+        }
+    }
+
+    public int handleApplicationError(IBinder app, int flags,
+            String tag, String shortMsg, String longMsg, byte[] crashData) {
+        AppErrorResult result = new AppErrorResult();
+
+        ProcessRecord r = null;
+        synchronized (this) {
+            if (app != null) {
+                for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
+                    final int NA = apps.size();
+                    for (int ia=0; ia<NA; ia++) {
+                        ProcessRecord p = apps.valueAt(ia);
+                        if (p.thread != null && p.thread.asBinder() == app) {
+                            r = p;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (r != null) {
+                // The application has crashed. Send the SIGQUIT to the process so
+                // that it can dump its state.
+                Process.sendSignal(r.pid, Process.SIGNAL_QUIT);
+                //Log.i(TAG, "Current system threads:");
+                //Process.sendSignal(MY_PID, Process.SIGNAL_QUIT);
+            }
+
+            if (mWatcher != null) {
+                try {
+                    String name = r != null ? r.processName : null;
+                    int pid = r != null ? r.pid : Binder.getCallingPid();
+                    if (!mWatcher.appCrashed(name, pid,
+                            shortMsg, longMsg, crashData)) {
+                        Log.w(TAG, "Force-killing crashed app " + name
+                                + " at watcher's request");
+                        Process.killProcess(pid);
+                        return 0;
+                    }
+                } catch (RemoteException e) {
+                    mWatcher = null;
+                }
+            }
+
+            final long origId = Binder.clearCallingIdentity();
+
+            // If this process is running instrumentation, finish it.
+            if (r != null && r.instrumentationClass != null) {
+                Log.w(TAG, "Error in app " + r.processName
+                      + " running instrumentation " + r.instrumentationClass + ":");
+                if (shortMsg != null) Log.w(TAG, "  " + shortMsg);
+                if (longMsg != null) Log.w(TAG, "  " + longMsg);
+                Bundle info = new Bundle();
+                info.putString("shortMsg", shortMsg);
+                info.putString("longMsg", longMsg);
+                finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
+                Binder.restoreCallingIdentity(origId);
+                return 0;
+            }
+
+            if (r != null) {
+                if (!makeAppCrashingLocked(r, tag, shortMsg, longMsg, crashData)) {
+                    return 0;
+                }
+            } else {
+                Log.w(TAG, "Some application object " + app + " tag " + tag
+                        + " has crashed, but I don't know who it is.");
+                Log.w(TAG, "ShortMsg:" + shortMsg);
+                Log.w(TAG, "LongMsg:" + longMsg);
+                Binder.restoreCallingIdentity(origId);
+                return 0;
+            }
+
+            Message msg = Message.obtain();
+            msg.what = SHOW_ERROR_MSG;
+            HashMap data = new HashMap();
+            data.put("result", result);
+            data.put("app", r);
+            data.put("flags", flags);
+            data.put("shortMsg", shortMsg);
+            data.put("longMsg", longMsg);
+            if (r != null && (r.info.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
+                // For system processes, submit crash data to the server.
+                data.put("crashData", crashData);
+            }
+            msg.obj = data;
+            mHandler.sendMessage(msg);
+
+            Binder.restoreCallingIdentity(origId);
+        }
+
+        int res = result.get();
+
+        synchronized (this) {
+            if (r != null) {
+                mProcessCrashTimes.put(r.info.processName, r.info.uid,
+                        SystemClock.uptimeMillis());
+            }
+        }
+
+        return res;
+    }
+    
+    public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
+        // assume our apps are happy - lazy create the list
+        List<ActivityManager.ProcessErrorStateInfo> errList = null;
+
+        synchronized (this) {
+
+            // iterate across all processes
+            final int N = mLRUProcesses.size();
+            for (int i = 0; i < N; i++) {
+                ProcessRecord app = mLRUProcesses.get(i);
+                if ((app.thread != null) && (app.crashing || app.notResponding)) {
+                    // This one's in trouble, so we'll generate a report for it
+                    // crashes are higher priority (in case there's a crash *and* an anr)
+                    ActivityManager.ProcessErrorStateInfo report = null;
+                    if (app.crashing) {
+                        report = app.crashingReport;
+                    } else if (app.notResponding) {
+                        report = app.notRespondingReport;
+                    }
+                    
+                    if (report != null) {
+                        if (errList == null) {
+                            errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
+                        }
+                        errList.add(report);
+                    } else {
+                        Log.w(TAG, "Missing app error report, app = " + app.processName + 
+                                " crashing = " + app.crashing +
+                                " notResponding = " + app.notResponding);
+                    }
+                }
+            }
+        }
+
+        return errList;
+    }
+    
+    public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
+        // Lazy instantiation of list
+        List<ActivityManager.RunningAppProcessInfo> runList = null;
+        synchronized (this) {
+            // Iterate across all processes
+            final int N = mLRUProcesses.size();
+            for (int i = 0; i < N; i++) {
+                ProcessRecord app = mLRUProcesses.get(i);
+                if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
+                    // Generate process state info for running application
+                    ActivityManager.RunningAppProcessInfo currApp = 
+                        new ActivityManager.RunningAppProcessInfo(app.processName,
+                                app.pid, app.getPackageList());
+                    int adj = app.curAdj;
+                    if (adj >= CONTENT_PROVIDER_ADJ) {
+                        currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
+                    } else if (adj >= HIDDEN_APP_MIN_ADJ) {
+                        currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
+                        currApp.lru = adj - HIDDEN_APP_MIN_ADJ;
+                    } else if (adj >= SECONDARY_SERVER_ADJ) {
+                        currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
+                    } else if (adj >= VISIBLE_APP_ADJ) {
+                        currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
+                    } else {
+                        currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+                    }
+                    //Log.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
+                    //        + " lru=" + currApp.lru);
+                    if (runList == null) {
+                        runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
+                    }
+                    runList.add(currApp);
+                }
+            }
+        }
+        return runList;
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        synchronized (this) {
+            if (checkCallingPermission(android.Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump ActivityManager from from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid()
+                        + " without permission "
+                        + android.Manifest.permission.DUMP);
+                return;
+            }
+            if (args.length != 0 && "service".equals(args[0])) {
+                dumpService(fd, pw, args);
+                return;
+            }
+            pw.println("Activities in Current Activity Manager State:");
+            dumpHistoryList(pw, mHistory, "  ", "History");
+            pw.println(" ");
+            pw.println("  Running activities (most recent first):");
+            dumpHistoryList(pw, mLRUActivities, "  ", "Running");
+            if (mWaitingVisibleActivities.size() > 0) {
+                pw.println(" ");
+                pw.println("  Activities waiting for another to become visible:");
+                dumpHistoryList(pw, mWaitingVisibleActivities, "  ", "Waiting");
+            }
+            if (mStoppingActivities.size() > 0) {
+                pw.println(" ");
+                pw.println("  Activities waiting to stop:");
+                dumpHistoryList(pw, mStoppingActivities, "  ", "Stopping");
+            }
+            if (mFinishingActivities.size() > 0) {
+                pw.println(" ");
+                pw.println("  Activities waiting to finish:");
+                dumpHistoryList(pw, mFinishingActivities, "  ", "Finishing");
+            }
+
+            pw.println(" ");
+            pw.println("  mPausingActivity: " + mPausingActivity);
+            pw.println("  mResumedActivity: " + mResumedActivity);
+            pw.println("  mFocusedActivity: " + mFocusedActivity);
+            pw.println("  mLastPausedActivity: " + mLastPausedActivity);
+
+            if (mRecentTasks.size() > 0) {
+                pw.println(" ");
+                pw.println("Recent tasks in Current Activity Manager State:");
+
+                final int N = mRecentTasks.size();
+                for (int i=0; i<N; i++) {
+                    pw.println("  Recent Task #" + i);
+                    mRecentTasks.get(i).dump(pw, "    ");
+                }
+            }
+            
+            pw.println(" ");
+            pw.println("  mCurTask: " + mCurTask);
+            
+            pw.println(" ");
+            pw.println("Processes in Current Activity Manager State:");
+
+            boolean needSep = false;
+            int numPers = 0;
+
+            for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
+                final int NA = procs.size();
+                for (int ia=0; ia<NA; ia++) {
+                    if (!needSep) {
+                        pw.println("  All known processes:");
+                        needSep = true;
+                    }
+                    ProcessRecord r = procs.valueAt(ia);
+                    pw.println((r.persistent ? "  *PERSISTENT* Process [" : "  Process [")
+                            + r.processName + "] UID " + procs.keyAt(ia));
+                    r.dump(pw, "    ");
+                    if (r.persistent) {
+                        numPers++;
+                    }
+                }
+            }
+            
+            if (mLRUProcesses.size() > 0) {
+                if (needSep) pw.println(" ");
+                needSep = true;
+                pw.println("  Running processes (most recent first):");
+                dumpProcessList(pw, mLRUProcesses, "    ",
+                        "Running Norm Proc", "Running PERS Proc", true);
+                needSep = true;
+            }
+
+            synchronized (mPidsSelfLocked) {
+                if (mPidsSelfLocked.size() > 0) {
+                    if (needSep) pw.println(" ");
+                    needSep = true;
+                    pw.println("  PID mappings:");
+                    for (int i=0; i<mPidsSelfLocked.size(); i++) {
+                        pw.println("    PID #" + mPidsSelfLocked.keyAt(i)
+                                + ": " + mPidsSelfLocked.valueAt(i));
+                    }
+                }
+            }
+            
+            if (mForegroundProcesses.size() > 0) {
+                if (needSep) pw.println(" ");
+                needSep = true;
+                pw.println("  Foreground Processes:");
+                for (int i=0; i<mForegroundProcesses.size(); i++) {
+                    pw.println("    PID #" + mForegroundProcesses.keyAt(i)
+                            + ": " + mForegroundProcesses.valueAt(i));
+                }
+            }
+            
+            if (mPersistentStartingProcesses.size() > 0) {
+                if (needSep) pw.println(" ");
+                needSep = true;
+                pw.println("  Persisent processes that are starting:");
+                dumpProcessList(pw, mPersistentStartingProcesses, "    ",
+                        "Starting Initial Proc", "Restarting PERS Proc", false);
+            }
+
+            if (mStartingProcesses.size() > 0) {
+                if (needSep) pw.println(" ");
+                needSep = true;
+                pw.println("  Processes that are starting:");
+                dumpProcessList(pw, mStartingProcesses, "    ",
+                        "Starting Norm Proc", "Starting PERS Proc", false);
+            }
+
+            if (mRemovedProcesses.size() > 0) {
+                if (needSep) pw.println(" ");
+                needSep = true;
+                pw.println("  Processes that are being removed:");
+                dumpProcessList(pw, mRemovedProcesses, "    ",
+                        "Removed Norm Proc", "Removed PERS Proc", false);
+            }
+            
+            if (mProcessesOnHold.size() > 0) {
+                if (needSep) pw.println(" ");
+                needSep = true;
+                pw.println("  Processes that are on old until the system is ready:");
+                dumpProcessList(pw, mProcessesOnHold, "    ",
+                        "OnHold Norm Proc", "OnHold PERS Proc", false);
+            }
+
+            if (mProcessCrashTimes.getMap().size() > 0) {
+                if (needSep) pw.println(" ");
+                needSep = true;
+                pw.println("  Time since processes crashed:");
+                long now = SystemClock.uptimeMillis();
+                for (Map.Entry<String, SparseArray<Long>> procs
+                        : mProcessCrashTimes.getMap().entrySet()) {
+                    SparseArray<Long> uids = procs.getValue();
+                    final int N = uids.size();
+                    for (int i=0; i<N; i++) {
+                        pw.println("    Process " + procs.getKey()
+                                + " uid " + uids.keyAt(i)
+                                + ": last crashed "
+                                + (now-uids.valueAt(i)) + " ms ago");
+                    }
+                }
+            }
+
+            if (mBadProcesses.getMap().size() > 0) {
+                if (needSep) pw.println(" ");
+                needSep = true;
+                pw.println("  Bad processes:");
+                for (Map.Entry<String, SparseArray<Long>> procs
+                        : mBadProcesses.getMap().entrySet()) {
+                    SparseArray<Long> uids = procs.getValue();
+                    final int N = uids.size();
+                    for (int i=0; i<N; i++) {
+                        pw.println("    Bad process " + procs.getKey()
+                                + " uid " + uids.keyAt(i)
+                                + ": crashed at time " + uids.valueAt(i));
+                    }
+                }
+            }
+
+            pw.println(" ");
+            pw.println("  Total persistent processes: " + numPers);
+            pw.println("  mConfiguration: " + mConfiguration);
+            pw.println("  mStartRunning=" + mStartRunning
+                    + " mSystemReady=" + mSystemReady
+                    + " mBooting=" + mBooting
+                    + " mBooted=" + mBooted
+                    + " mFactoryTest=" + mFactoryTest);
+            pw.println("  mSleeping=" + mSleeping);
+            pw.println("  mGoingToSleep=" + mGoingToSleep);
+            pw.println("  mLaunchingActivity=" + mLaunchingActivity);
+            pw.println("  mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
+                    + " mDebugTransient=" + mDebugTransient
+                    + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
+            pw.println("  mAlwaysFinishActivities=" + mAlwaysFinishActivities
+                    + " mWatcher=" + mWatcher);
+        }
+    }
+
+    /**
+     * There are three ways to call this:
+     *  - no service specified: dump all the services
+     *  - a flattened component name that matched an existing service was specified as the
+     *    first arg: dump that one service
+     *  - the first arg isn't the flattened component name of an existing service:
+     *    dump all services whose component contains the first arg as a substring
+     */
+    protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args) {
+        String[] newArgs;
+        String componentNameString;
+        ServiceRecord r;
+        if (args.length == 1) {
+            componentNameString = null;
+            newArgs = EMPTY_STRING_ARRAY;
+            r = null;
+        } else {
+            componentNameString = args[1];
+            ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
+            r = componentName != null ? mServices.get(componentName) : null;
+            newArgs = new String[args.length - 2];
+            if (args.length > 2) System.arraycopy(args, 2, newArgs, 0, args.length - 2);
+        }
+
+        if (r != null) {
+            dumpService(fd, pw, r, newArgs);
+        } else {
+            for (ServiceRecord r1 : mServices.values()) {
+                if (componentNameString == null
+                        || r1.name.flattenToString().contains(componentNameString)) {
+                    dumpService(fd, pw, r1, newArgs);
+                }
+            }
+        }
+    }
+
+    /**
+     * Invokes IApplicationThread.dumpService() on the thread of the specified service if
+     * there is a thread associated with the service.
+     */
+    private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
+        pw.println("  Service " + r.name.flattenToString());
+        if (r.app != null && r.app.thread != null) {
+            try {
+                // flush anything that is already in the PrintWriter since the thread is going
+                // to write to the file descriptor directly
+                pw.flush();
+                r.app.thread.dumpService(fd, r, args);
+                pw.print("\n");
+            } catch (RemoteException e) {
+                pw.println("got a RemoteException while dumping the service");
+            }
+        }
+    }
+
+    void dumpBroadcasts(PrintWriter pw) {
+        synchronized (this) {
+            if (checkCallingPermission(android.Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump ActivityManager from from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid()
+                        + " without permission "
+                        + android.Manifest.permission.DUMP);
+                return;
+            }
+            pw.println("Broadcasts in Current Activity Manager State:");
+
+            if (mRegisteredReceivers.size() > 0) {
+                pw.println(" ");
+                pw.println("  Registered Receivers:");
+                Iterator it = mRegisteredReceivers.values().iterator();
+                while (it.hasNext()) {
+                    ReceiverList r = (ReceiverList)it.next();
+                    pw.println("  Receiver " + r.receiver);
+                    r.dump(pw, "    ");
+                }
+            }
+
+            pw.println(" ");
+            pw.println("Receiver Resolver Table:");
+            mReceiverResolver.dump(new PrintWriterPrinter(pw), "  ");
+            
+            if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
+                    || mPendingBroadcast != null) {
+                if (mParallelBroadcasts.size() > 0) {
+                    pw.println(" ");
+                    pw.println("  Active broadcasts:");
+                }
+                for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
+                    pw.println("  Broadcast #" + i + ":");
+                    mParallelBroadcasts.get(i).dump(pw, "    ");
+                }
+                if (mOrderedBroadcasts.size() > 0) {
+                    pw.println(" ");
+                    pw.println("  Active serialized broadcasts:");
+                }
+                for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
+                    pw.println("  Serialized Broadcast #" + i + ":");
+                    mOrderedBroadcasts.get(i).dump(pw, "    ");
+                }
+                pw.println(" ");
+                pw.println("  Pending broadcast:");
+                if (mPendingBroadcast != null) {
+                    mPendingBroadcast.dump(pw, "    ");
+                } else {
+                    pw.println("    (null)");
+                }
+            }
+
+            pw.println(" ");
+            pw.println("  mBroadcastsScheduled=" + mBroadcastsScheduled);
+            if (mStickyBroadcasts != null) {
+                pw.println(" ");
+                pw.println("  Sticky broadcasts:");
+                for (Map.Entry<String, ArrayList<Intent>> ent
+                        : mStickyBroadcasts.entrySet()) {
+                    pw.println("  Sticky action " + ent.getKey() + ":");
+                    ArrayList<Intent> intents = ent.getValue();
+                    final int N = intents.size();
+                    for (int i=0; i<N; i++) {
+                        pw.println("    " + intents.get(i));
+                    }
+                }
+            }
+            
+            pw.println(" ");
+            pw.println("  mHandler:");
+            mHandler.dump(new PrintWriterPrinter(pw), "    ");
+        }
+    }
+
+    void dumpServices(PrintWriter pw) {
+        synchronized (this) {
+            if (checkCallingPermission(android.Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump ActivityManager from from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid()
+                        + " without permission "
+                        + android.Manifest.permission.DUMP);
+                return;
+            }
+            pw.println("Services in Current Activity Manager State:");
+
+            boolean needSep = false;
+
+            if (mServices.size() > 0) {
+                pw.println("  Active services:");
+                Iterator<ServiceRecord> it = mServices.values().iterator();
+                while (it.hasNext()) {
+                    ServiceRecord r = it.next();
+                    pw.println("  Service " + r.shortName);
+                    r.dump(pw, "    ");
+                }
+                needSep = true;
+            }
+
+            if (mPendingServices.size() > 0) {
+                if (needSep) pw.println(" ");
+                pw.println("  Pending services:");
+                for (int i=0; i<mPendingServices.size(); i++) {
+                    ServiceRecord r = mPendingServices.get(i);
+                    pw.println("  Pending Service " + r.shortName);
+                    r.dump(pw, "    ");
+                }
+                needSep = true;
+            }
+
+            if (mRestartingServices.size() > 0) {
+                if (needSep) pw.println(" ");
+                pw.println("  Restarting services:");
+                for (int i=0; i<mRestartingServices.size(); i++) {
+                    ServiceRecord r = mRestartingServices.get(i);
+                    pw.println("  Restarting Service " + r.shortName);
+                    r.dump(pw, "    ");
+                }
+                needSep = true;
+            }
+
+            if (mStoppingServices.size() > 0) {
+                if (needSep) pw.println(" ");
+                pw.println("  Stopping services:");
+                for (int i=0; i<mStoppingServices.size(); i++) {
+                    ServiceRecord r = mStoppingServices.get(i);
+                    pw.println("  Stopping Service " + r.shortName);
+                    r.dump(pw, "    ");
+                }
+                needSep = true;
+            }
+
+            if (mServiceConnections.size() > 0) {
+                if (needSep) pw.println(" ");
+                pw.println("  Connection bindings to services:");
+                Iterator<ConnectionRecord> it
+                        = mServiceConnections.values().iterator();
+                while (it.hasNext()) {
+                    ConnectionRecord r = it.next();
+                    pw.println("  " + r.binding.service.shortName
+                          + " -> " + r.conn.asBinder());
+                    r.dump(pw, "    ");
+                }
+            }
+        }
+    }
+
+    void dumpProviders(PrintWriter pw) {
+        synchronized (this) {
+            if (checkCallingPermission(android.Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump ActivityManager from from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid()
+                        + " without permission "
+                        + android.Manifest.permission.DUMP);
+                return;
+            }
+
+            pw.println("Content Providers in Current Activity Manager State:");
+
+            boolean needSep = false;
+
+            if (mProvidersByName.size() > 0) {
+                pw.println("  Published content providers (by name):");
+                Iterator it = mProvidersByName.entrySet().iterator();
+                while (it.hasNext()) {
+                    Map.Entry e = (Map.Entry)it.next();
+                    ContentProviderRecord r = (ContentProviderRecord)e.getValue();
+                    pw.println("  Provider " + (String)e.getKey());
+                    r.dump(pw, "    ");
+                }
+                needSep = true;
+            }
+
+            if (mProvidersByClass.size() > 0) {
+                if (needSep) pw.println(" ");
+                pw.println("  Published content providers (by class):");
+                Iterator it = mProvidersByClass.entrySet().iterator();
+                while (it.hasNext()) {
+                    Map.Entry e = (Map.Entry)it.next();
+                    ContentProviderRecord r = (ContentProviderRecord)e.getValue();
+                    pw.println("  Provider " + (String)e.getKey());
+                    r.dump(pw, "    ");
+                }
+                needSep = true;
+            }
+
+            if (mLaunchingProviders.size() > 0) {
+                if (needSep) pw.println(" ");
+                pw.println("  Launching content providers:");
+                for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
+                    pw.println("  Provider #" + i + ":");
+                    ((ContentProviderRecord)mLaunchingProviders.get(i)).dump(pw, "    ");
+                }
+                needSep = true;
+            }
+
+            pw.println();
+            pw.println("Granted Uri Permissions:");
+            for (int i=0; i<mGrantedUriPermissions.size(); i++) {
+                int uid = mGrantedUriPermissions.keyAt(i);
+                HashMap<Uri, UriPermission> perms
+                        = mGrantedUriPermissions.valueAt(i);
+                pw.println("  Uris granted to uid " + uid + ":");
+                for (UriPermission perm : perms.values()) {
+                    perm.dump(pw, "    ");
+                }
+            }
+        }
+    }
+
+    void dumpSenders(PrintWriter pw) {
+        synchronized (this) {
+            if (checkCallingPermission(android.Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump ActivityManager from from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid()
+                        + " without permission "
+                        + android.Manifest.permission.DUMP);
+                return;
+            }
+
+            pw.println("Intent Senders in Current Activity Manager State:");
+
+            if (this.mIntentSenderRecords.size() > 0) {
+                Iterator<WeakReference<PendingIntentRecord>> it
+                        = mIntentSenderRecords.values().iterator();
+                while (it.hasNext()) {
+                    WeakReference<PendingIntentRecord> ref = it.next();
+                    PendingIntentRecord rec = ref != null ? ref.get(): null;
+                    if (rec != null) {
+                        pw.println("  IntentSender " + rec);
+                        rec.dump(pw, "    ");
+                    } else {
+                        pw.println("  IntentSender " + ref);
+                    }
+                }
+            }
+        }
+    }
+
+    private static final void dumpHistoryList(PrintWriter pw, List list,
+            String prefix, String label) {
+        TaskRecord lastTask = null;
+        for (int i=list.size()-1; i>=0; i--) {
+            HistoryRecord r = (HistoryRecord)list.get(i);
+            if (lastTask != r.task) {
+                lastTask = r.task;
+                lastTask.dump(pw, prefix + "  ");
+            }
+            pw.println(prefix + "    " + label + " #" + i + ":");
+            r.dump(pw, prefix + "      ");
+        }
+    }
+
+    private static final int dumpProcessList(PrintWriter pw, List list,
+            String prefix, String normalLabel, String persistentLabel,
+            boolean inclOomAdj) {
+        int numPers = 0;
+        for (int i=list.size()-1; i>=0; i--) {
+            ProcessRecord r = (ProcessRecord)list.get(i);
+            if (false) {
+                pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
+                      + " #" + i + ":");
+                r.dump(pw, prefix + "  ");
+            } else if (inclOomAdj) {
+                pw.println(String.format("%s%s #%2d: oom_adj=%3d %s",
+                        prefix, (r.persistent ? persistentLabel : normalLabel),
+                        i, r.setAdj, r.toString()));
+            } else {
+                pw.println(String.format("%s%s #%2d: %s",
+                        prefix, (r.persistent ? persistentLabel : normalLabel),
+                        i, r.toString()));
+            }
+            if (r.persistent) {
+                numPers++;
+            }
+        }
+        return numPers;
+    }
+
+    private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
+            PrintWriter pw, List list, String prefix, String[] args) {
+        final boolean isCheckinRequest = scanArgs(args, "-c");
+        long uptime = SystemClock.uptimeMillis();
+        long realtime = SystemClock.elapsedRealtime();
+        
+        if (isCheckinRequest) {
+            // short checkin version
+            pw.println(uptime + "," + realtime);
+            pw.flush();
+        } else {
+            pw.println("Applications Memory Usage (kB):");
+            pw.println("Uptime: " + uptime + " Realtime: " + realtime);
+        }
+        for (int i = list.size() - 1 ; i >= 0 ; i--) {
+            ProcessRecord r = (ProcessRecord)list.get(i);
+            if (r.thread != null) {
+                if (!isCheckinRequest) {
+                    pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
+                    pw.flush();
+                }
+                try {
+                    r.thread.asBinder().dump(fd, args);
+                } catch (RemoteException e) {
+                    if (!isCheckinRequest) {
+                        pw.println("Got RemoteException!");
+                        pw.flush();
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Searches array of arguments for the specified string
+     * @param args array of argument strings
+     * @param value value to search for
+     * @return true if the value is contained in the array
+     */
+    private static boolean scanArgs(String[] args, String value) {
+        if (args != null) {
+            for (String arg : args) {
+                if (value.equals(arg)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private final int indexOfTokenLocked(IBinder token, boolean required) {
+        int count = mHistory.size();
+
+        // convert the token to an entry in the history.
+        HistoryRecord r = null;
+        int index = -1;
+        for (int i=count-1; i>=0; i--) {
+            Object o = mHistory.get(i);
+            if (o == token) {
+                r = (HistoryRecord)o;
+                index = i;
+                break;
+            }
+        }
+        if (index < 0 && required) {
+            RuntimeInit.crash(TAG, new InvalidTokenException(token));
+        }
+
+        return index;
+    }
+
+    static class InvalidTokenException extends Exception {
+        InvalidTokenException(IBinder token) {
+            super("Bad activity token: " + token);
+        }
+    }
+
+    private final void killServicesLocked(ProcessRecord app,
+            boolean allowRestart) {
+        // Report disconnected services.
+        if (false) {
+            // XXX we are letting the client link to the service for
+            // death notifications.
+            if (app.services.size() > 0) {
+                Iterator it = app.services.iterator();
+                while (it.hasNext()) {
+                    ServiceRecord r = (ServiceRecord)it.next();
+                    if (r.connections.size() > 0) {
+                        Iterator<ConnectionRecord> jt
+                                = r.connections.values().iterator();
+                        while (jt.hasNext()) {
+                            ConnectionRecord c = jt.next();
+                            if (c.binding.client != app) {
+                                try {
+                                    //c.conn.connected(r.className, null);
+                                } catch (Exception e) {
+                                    // todo: this should be asynchronous!
+                                    Log.w(TAG, "Exception thrown disconnected servce "
+                                          + r.shortName
+                                          + " from app " + app.processName, e);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // Clean up any connections this application has to other services.
+        if (app.connections.size() > 0) {
+            Iterator<ConnectionRecord> it = app.connections.iterator();
+            while (it.hasNext()) {
+                ConnectionRecord r = it.next();
+                removeConnectionLocked(r, app, null);
+            }
+        }
+        app.connections.clear();
+
+        if (app.services.size() != 0) {
+            // Any services running in the application need to be placed
+            // back in the pending list.
+            Iterator it = app.services.iterator();
+            while (it.hasNext()) {
+                ServiceRecord sr = (ServiceRecord)it.next();
+                synchronized (sr.stats.getBatteryStats()) {
+                    sr.stats.stopLaunchedLocked();
+                }
+                sr.app = null;
+                sr.executeNesting = 0;
+                mStoppingServices.remove(sr);
+                if (sr.bindings.size() > 0) {
+                    Iterator<IntentBindRecord> bindings
+                            = sr.bindings.values().iterator();
+                    while (bindings.hasNext()) {
+                        IntentBindRecord b = bindings.next();
+                        if (DEBUG_SERVICE) Log.v(TAG, "Killing binding " + b
+                                + ": shouldUnbind=" + b.hasBound);
+                        b.binder = null;
+                        b.requested = b.received = b.hasBound = false;
+                    }
+                }
+
+                if (sr.crashCount >= 2) {
+                    Log.w(TAG, "Service crashed " + sr.crashCount
+                            + " times, stopping: " + sr);
+                    EventLog.writeEvent(LOG_AM_SERVICE_CRASHED_TOO_MUCH,
+                            sr.crashCount, sr.shortName, app.pid);
+                    bringDownServiceLocked(sr, true);
+                } else if (!allowRestart) {
+                    bringDownServiceLocked(sr, true);
+                } else {
+                    scheduleServiceRestartLocked(sr);
+                }
+            }
+
+            if (!allowRestart) {
+                app.services.clear();
+            }
+        }
+
+        app.executingServices.clear();
+    }
+
+    private final void removeDyingProviderLocked(ProcessRecord proc,
+            ContentProviderRecord cpr) {
+        synchronized (cpr) {
+            cpr.launchingApp = null;
+            cpr.notifyAll();
+        }
+        
+        mProvidersByClass.remove(cpr.info.name);
+        String names[] = cpr.info.authority.split(";");
+        for (int j = 0; j < names.length; j++) {
+            mProvidersByName.remove(names[j]);
+        }
+        
+        Iterator<ProcessRecord> cit = cpr.clients.iterator();
+        while (cit.hasNext()) {
+            ProcessRecord capp = cit.next();
+            if (!capp.persistent && capp.thread != null
+                    && capp.pid != 0
+                    && capp.pid != MY_PID) {
+                Log.i(TAG, "Killing app " + capp.processName
+                        + " (pid " + capp.pid
+                        + ") because provider " + cpr.info.name
+                        + " is in dying process " + proc.processName);
+                Process.killProcess(capp.pid);
+            }
+        }
+        
+        mLaunchingProviders.remove(cpr);
+    }
+    
+    /**
+     * Main code for cleaning up a process when it has gone away.  This is
+     * called both as a result of the process dying, or directly when stopping 
+     * a process when running in single process mode.
+     */
+    private final void cleanUpApplicationRecordLocked(ProcessRecord app,
+            boolean restarting, int index) {
+        if (index >= 0) {
+            mLRUProcesses.remove(index);
+        }
+
+        // Dismiss any open dialogs.
+        if (app.crashDialog != null) {
+            app.crashDialog.dismiss();
+            app.crashDialog = null;
+        }
+        if (app.anrDialog != null) {
+            app.anrDialog.dismiss();
+            app.anrDialog = null;
+        }
+        if (app.waitDialog != null) {
+            app.waitDialog.dismiss();
+            app.waitDialog = null;
+        }
+
+        app.crashing = false;
+        app.notResponding = false;
+        
+        app.resetPackageList();
+        app.thread = null;
+        app.forcingToForeground = null;
+        app.foregroundServices = false;
+
+        killServicesLocked(app, true);
+
+        boolean restart = false;
+
+        int NL = mLaunchingProviders.size();
+        
+        // Remove published content providers.
+        if (!app.pubProviders.isEmpty()) {
+            Iterator it = app.pubProviders.values().iterator();
+            while (it.hasNext()) {
+                ContentProviderRecord cpr = (ContentProviderRecord)it.next();
+                cpr.provider = null;
+                cpr.app = null;
+
+                // See if someone is waiting for this provider...  in which
+                // case we don't remove it, but just let it restart.
+                int i = 0;
+                if (!app.bad) {
+                    for (; i<NL; i++) {
+                        if (mLaunchingProviders.get(i) == cpr) {
+                            restart = true;
+                            break;
+                        }
+                    }
+                } else {
+                    i = NL;
+                }
+
+                if (i >= NL) {
+                    removeDyingProviderLocked(app, cpr);
+                    NL = mLaunchingProviders.size();
+                }
+            }
+            app.pubProviders.clear();
+        }
+        
+        // Look through the content providers we are waiting to have launched,
+        // and if any run in this process then either schedule a restart of
+        // the process or kill the client waiting for it if this process has
+        // gone bad.
+        for (int i=0; i<NL; i++) {
+            ContentProviderRecord cpr = (ContentProviderRecord)
+                    mLaunchingProviders.get(i);
+            if (cpr.launchingApp == app) {
+                if (!app.bad) {
+                    restart = true;
+                } else {
+                    removeDyingProviderLocked(app, cpr);
+                    NL = mLaunchingProviders.size();
+                }
+            }
+        }
+
+        // Unregister from connected content providers.
+        if (!app.conProviders.isEmpty()) {
+            Iterator it = app.conProviders.iterator();
+            while (it.hasNext()) {
+                ContentProviderRecord cpr = (ContentProviderRecord)it.next();
+                cpr.clients.remove(app);
+            }
+            app.conProviders.clear();
+        }
+
+        skipCurrentReceiverLocked(app);
+
+        // Unregister any receivers.
+        if (app.receivers.size() > 0) {
+            Iterator<ReceiverList> it = app.receivers.iterator();
+            while (it.hasNext()) {
+                removeReceiverLocked(it.next());
+            }
+            app.receivers.clear();
+        }
+        
+        // If the caller is restarting this app, then leave it in its
+        // current lists and let the caller take care of it.
+        if (restarting) {
+            return;
+        }
+
+        if (!app.persistent) {
+            if (DEBUG_PROCESSES) Log.v(TAG,
+                    "Removing non-persistent process during cleanup: " + app);
+            mProcessNames.remove(app.processName, app.info.uid);
+        } else if (!app.removed) {
+            // This app is persistent, so we need to keep its record around.
+            // If it is not already on the pending app list, add it there
+            // and start a new process for it.
+            app.thread = null;
+            app.forcingToForeground = null;
+            app.foregroundServices = false;
+            if (mPersistentStartingProcesses.indexOf(app) < 0) {
+                mPersistentStartingProcesses.add(app);
+                restart = true;
+            }
+        }
+        mProcessesOnHold.remove(app);
+
+        if (restart) {
+            // We have components that still need to be running in the
+            // process, so re-launch it.
+            mProcessNames.put(app.processName, app.info.uid, app);
+            startProcessLocked(app, "restart", app.processName);
+        } else if (app.pid > 0 && app.pid != MY_PID) {
+            // Goodbye!
+            synchronized (mPidsSelfLocked) {
+                mPidsSelfLocked.remove(app.pid);
+                mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
+            }
+            app.pid = 0;
+        }
+    }
+
+    // =========================================================
+    // SERVICES
+    // =========================================================
+
+    ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
+        ActivityManager.RunningServiceInfo info =
+            new ActivityManager.RunningServiceInfo();
+        info.service = r.name;
+        if (r.app != null) {
+            info.pid = r.app.pid;
+        }
+        info.process = r.processName;
+        info.foreground = r.isForeground;
+        info.activeSince = r.createTime;
+        info.started = r.startRequested;
+        info.clientCount = r.connections.size();
+        info.crashCount = r.crashCount;
+        info.lastActivityTime = r.lastActivity;
+        return info;
+    }
+    
+    public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
+            int flags) {
+        synchronized (this) {
+            ArrayList<ActivityManager.RunningServiceInfo> res
+                    = new ArrayList<ActivityManager.RunningServiceInfo>();
+            
+            if (mServices.size() > 0) {
+                Iterator<ServiceRecord> it = mServices.values().iterator();
+                while (it.hasNext() && res.size() < maxNum) {
+                    res.add(makeRunningServiceInfoLocked(it.next()));
+                }
+            }
+
+            for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
+                ServiceRecord r = mRestartingServices.get(i);
+                ActivityManager.RunningServiceInfo info =
+                        makeRunningServiceInfoLocked(r);
+                info.restarting = r.nextRestartTime;
+                res.add(info);
+            }
+            
+            return res;
+        }
+    }
+
+    private final ServiceRecord findServiceLocked(ComponentName name,
+            IBinder token) {
+        ServiceRecord r = mServices.get(name);
+        return r == token ? r : null;
+    }
+
+    private final class ServiceLookupResult {
+        final ServiceRecord record;
+        final String permission;
+
+        ServiceLookupResult(ServiceRecord _record, String _permission) {
+            record = _record;
+            permission = _permission;
+        }
+    };
+
+    private ServiceLookupResult findServiceLocked(Intent service,
+            String resolvedType) {
+        ServiceRecord r = null;
+        if (service.getComponent() != null) {
+            r = mServices.get(service.getComponent());
+        }
+        if (r == null) {
+            Intent.FilterComparison filter = new Intent.FilterComparison(service);
+            r = mServicesByIntent.get(filter);
+        }
+
+        if (r == null) {
+            try {
+                ResolveInfo rInfo =
+                    ActivityThread.getPackageManager().resolveService(
+                            service, resolvedType, 0);
+                ServiceInfo sInfo =
+                    rInfo != null ? rInfo.serviceInfo : null;
+                if (sInfo == null) {
+                    return null;
+                }
+
+                ComponentName name = new ComponentName(
+                        sInfo.applicationInfo.packageName, sInfo.name);
+                r = mServices.get(name);
+            } catch (RemoteException ex) {
+                // pm is in same process, this will never happen.
+            }
+        }
+        if (r != null) {
+            int callingPid = Binder.getCallingPid();
+            int callingUid = Binder.getCallingUid();
+            if (checkComponentPermission(r.permission,
+                    callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
+                    != PackageManager.PERMISSION_GRANTED) {
+                Log.w(TAG, "Permission Denial: Accessing service " + r.name
+                        + " from pid=" + callingPid
+                        + ", uid=" + callingUid
+                        + " requires " + r.permission);
+                return new ServiceLookupResult(null, r.permission);
+            }
+            return new ServiceLookupResult(r, null);
+        }
+        return null;
+    }
+
+    private class ServiceRestarter implements Runnable {
+        private ServiceRecord mService;
+
+        void setService(ServiceRecord service) {
+            mService = service;
+        }
+
+        public void run() {
+            synchronized(ActivityManagerService.this) {
+                performServiceRestartLocked(mService);
+            }
+        }
+    }
+
+    private ServiceLookupResult retrieveServiceLocked(Intent service,
+            String resolvedType, int callingPid, int callingUid) {
+        ServiceRecord r = null;
+        if (service.getComponent() != null) {
+            r = mServices.get(service.getComponent());
+        }
+        Intent.FilterComparison filter = new Intent.FilterComparison(service);
+        r = mServicesByIntent.get(filter);
+        if (r == null) {
+            try {
+                ResolveInfo rInfo =
+                    ActivityThread.getPackageManager().resolveService(
+                            service, resolvedType, PackageManager.GET_SHARED_LIBRARY_FILES);
+                ServiceInfo sInfo =
+                    rInfo != null ? rInfo.serviceInfo : null;
+                if (sInfo == null) {
+                    Log.w(TAG, "Unable to start service " + service +
+                          ": not found");
+                    return null;
+                }
+
+                ComponentName name = new ComponentName(
+                        sInfo.applicationInfo.packageName, sInfo.name);
+                r = mServices.get(name);
+                if (r == null) {
+                    filter = new Intent.FilterComparison(service.cloneFilter());
+                    ServiceRestarter res = new ServiceRestarter();
+                    BatteryStatsImpl.Uid.Pkg.Serv ss = null;
+                    BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+                    synchronized (stats) {
+                        ss = stats.getServiceStatsLocked(
+                                sInfo.applicationInfo.uid, sInfo.packageName,
+                                sInfo.name);
+                    }
+                    r = new ServiceRecord(ss, name, filter, sInfo, res);
+                    res.setService(r);
+                    mServices.put(name, r);
+                    mServicesByIntent.put(filter, r);
+                    
+                    // Make sure this component isn't in the pending list.
+                    int N = mPendingServices.size();
+                    for (int i=0; i<N; i++) {
+                        ServiceRecord pr = mPendingServices.get(i);
+                        if (pr.name.equals(name)) {
+                            mPendingServices.remove(i);
+                            i--;
+                            N--;
+                        }
+                    }
+                }
+            } catch (RemoteException ex) {
+                // pm is in same process, this will never happen.
+            }
+        }
+        if (r != null) {
+            if (checkComponentPermission(r.permission,
+                    callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
+                    != PackageManager.PERMISSION_GRANTED) {
+                Log.w(TAG, "Permission Denial: Accessing service " + r.name
+                        + " from pid=" + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid()
+                        + " requires " + r.permission);
+                return new ServiceLookupResult(null, r.permission);
+            }
+            return new ServiceLookupResult(r, null);
+        }
+        return null;
+    }
+
+    private final void bumpServiceExecutingLocked(ServiceRecord r) {
+        long now = SystemClock.uptimeMillis();
+        if (r.executeNesting == 0 && r.app != null) {
+            if (r.app.executingServices.size() == 0) {
+                Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
+                msg.obj = r.app;
+                mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
+            }
+            r.app.executingServices.add(r);
+        }
+        r.executeNesting++;
+        r.executingStart = now;
+    }
+
+    private final void sendServiceArgsLocked(ServiceRecord r,
+            boolean oomAdjusted) {
+        final int N = r.startArgs.size();
+        if (N == 0) {
+            return;
+        }
+
+        final int BASEID = r.lastStartId - N + 1;
+        int i = 0;
+        while (i < N) {
+            try {
+                Intent args = r.startArgs.get(i);
+                if (DEBUG_SERVICE) Log.v(TAG, "Sending arguments to service: "
+                        + r.name + " " + r.intent + " args=" + args);
+                bumpServiceExecutingLocked(r);
+                if (!oomAdjusted) {
+                    oomAdjusted = true;
+                    updateOomAdjLocked(r.app);
+                }
+                r.app.thread.scheduleServiceArgs(r, BASEID+i, args);
+                i++;
+            } catch (Exception e) {
+                break;
+            }
+        }
+        if (i == N) {
+            r.startArgs.clear();
+        } else {
+            while (i > 0) {
+                r.startArgs.remove(0);
+                i--;
+            }
+        }
+    }
+
+    private final boolean requestServiceBindingLocked(ServiceRecord r,
+            IntentBindRecord i, boolean rebind) {
+        if (r.app == null || r.app.thread == null) {
+            // If service is not currently running, can't yet bind.
+            return false;
+        }
+        if ((!i.requested || rebind) && i.apps.size() > 0) {
+            try {
+                bumpServiceExecutingLocked(r);
+                if (DEBUG_SERVICE) Log.v(TAG, "Connecting binding " + i
+                        + ": shouldUnbind=" + i.hasBound);
+                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
+                if (!rebind) {
+                    i.requested = true;
+                }
+                i.hasBound = true;
+                i.doRebind = false;
+            } catch (RemoteException e) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private final void requestServiceBindingsLocked(ServiceRecord r) {
+        Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
+        while (bindings.hasNext()) {
+            IntentBindRecord i = bindings.next();
+            if (!requestServiceBindingLocked(r, i, false)) {
+                break;
+            }
+        }
+    }
+
+    private final void realStartServiceLocked(ServiceRecord r,
+            ProcessRecord app) throws RemoteException {
+        if (app.thread == null) {
+            throw new RemoteException();
+        }
+
+        r.app = app;
+        r.restartTime = SystemClock.uptimeMillis();
+
+        app.services.add(r);
+        bumpServiceExecutingLocked(r);
+        updateLRUListLocked(app, true);
+
+        boolean created = false;
+        try {
+            if (DEBUG_SERVICE) Log.v(TAG, "Scheduling start service: "
+                    + r.name + " " + r.intent);
+            EventLog.writeEvent(LOG_AM_CREATE_SERVICE,
+                    System.identityHashCode(r), r.shortName,
+                    r.intent.getIntent().toString(), r.app.pid);
+            synchronized (r.stats.getBatteryStats()) {
+                r.stats.startLaunchedLocked();
+            }
+            app.thread.scheduleCreateService(r, r.serviceInfo);
+            created = true;
+        } finally {
+            if (!created) {
+                app.services.remove(r);
+                scheduleServiceRestartLocked(r);
+            }
+        }
+
+        requestServiceBindingsLocked(r);
+        sendServiceArgsLocked(r, true);
+    }
+
+    private final void scheduleServiceRestartLocked(ServiceRecord r) {
+        r.totalRestartCount++;
+        if (r.restartDelay == 0) {
+            r.restartCount++;
+            r.restartDelay = SERVICE_RESTART_DURATION;
+        } else {
+            // If it has been a "reasonably long time" since the service
+            // was started, then reset our restart duration back to
+            // the beginning, so we don't infinitely increase the duration
+            // on a service that just occasionally gets killed (which is
+            // a normal case, due to process being killed to reclaim memory).
+            long now = SystemClock.uptimeMillis();
+            if (now > (r.restartTime+(SERVICE_RESTART_DURATION*2*2*2))) {
+                r.restartCount = 1;
+                r.restartDelay = SERVICE_RESTART_DURATION;
+            } else {
+                r.restartDelay *= 2;
+            }
+        }
+        if (!mRestartingServices.contains(r)) {
+            mRestartingServices.add(r);
+        }
+        mHandler.removeCallbacks(r.restarter);
+        mHandler.postDelayed(r.restarter, r.restartDelay);
+        r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
+        Log.w(TAG, "Scheduling restart of crashed service "
+                + r.shortName + " in " + r.restartDelay + "ms");
+        EventLog.writeEvent(LOG_AM_SCHEDULE_SERVICE_RESTART,
+                r.shortName, r.restartDelay);
+
+        Message msg = Message.obtain();
+        msg.what = SERVICE_ERROR_MSG;
+        msg.obj = r;
+        mHandler.sendMessage(msg);
+    }
+
+    final void performServiceRestartLocked(ServiceRecord r) {
+        if (!mRestartingServices.contains(r)) {
+            return;
+        }
+        bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
+    }
+
+    private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
+        if (r.restartDelay == 0) {
+            return false;
+        }
+        r.resetRestartCounter();
+        mRestartingServices.remove(r);
+        mHandler.removeCallbacks(r.restarter);
+        return true;
+    }
+
+    private final boolean bringUpServiceLocked(ServiceRecord r,
+            int intentFlags, boolean whileRestarting) {
+        //Log.i(TAG, "Bring up service:");
+        //r.dump("  ");
+
+        if (r.app != null) {
+            sendServiceArgsLocked(r, false);
+            return true;
+        }
+
+        if (!whileRestarting && r.restartDelay > 0) {
+            // If waiting for a restart, then do nothing.
+            return true;
+        }
+
+        if (DEBUG_SERVICE) Log.v(TAG, "Bringing up service " + r.name
+                + " " + r.intent);
+
+        final String appName = r.processName;
+        ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
+        if (app != null && app.thread != null) {
+            try {
+                realStartServiceLocked(r, app);
+                return true;
+            } catch (RemoteException e) {
+                Log.w(TAG, "Exception when starting service " + r.shortName, e);
+            }
+
+            // If a dead object exception was thrown -- fall through to
+            // restart the application.
+        }
+
+        if (!mPendingServices.contains(r)) {
+            // Not running -- get it started, and enqueue this service record
+            // to be executed when the app comes up.
+            if (startProcessLocked(appName, r.appInfo, true, intentFlags,
+                    "service", r.name) == null) {
+                Log.w(TAG, "Unable to launch app "
+                        + r.appInfo.packageName + "/"
+                        + r.appInfo.uid + " for service "
+                        + r.intent.getIntent() + ": process is bad");
+                bringDownServiceLocked(r, true);
+                return false;
+            }
+            mPendingServices.add(r);
+        }
+        return true;
+    }
+
+    private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
+        //Log.i(TAG, "Bring down service:");
+        //r.dump("  ");
+
+        // Does it still need to run?
+        if (!force && r.startRequested) {
+            return;
+        }
+        if (r.connections.size() > 0) {
+            if (!force) {
+                // XXX should probably keep a count of the number of auto-create
+                // connections directly in the service.
+                Iterator<ConnectionRecord> it = r.connections.values().iterator();
+                while (it.hasNext()) {
+                    ConnectionRecord cr = it.next();
+                    if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
+                        return;
+                    }
+                }
+            }
+
+            // Report to all of the connections that the service is no longer
+            // available.
+            Iterator<ConnectionRecord> it = r.connections.values().iterator();
+            while (it.hasNext()) {
+                ConnectionRecord c = it.next();
+                try {
+                    // todo: shouldn't be a synchronous call!
+                    c.conn.connected(r.name, null);
+                } catch (Exception e) {
+                    Log.w(TAG, "Failure disconnecting service " + r.name +
+                          " to connection " + c.conn.asBinder() +
+                          " (in " + c.binding.client.processName + ")", e);
+                }
+            }
+        }
+
+        // Tell the service that it has been unbound.
+        if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
+            Iterator<IntentBindRecord> it = r.bindings.values().iterator();
+            while (it.hasNext()) {
+                IntentBindRecord ibr = it.next();
+                if (DEBUG_SERVICE) Log.v(TAG, "Bringing down binding " + ibr
+                        + ": hasBound=" + ibr.hasBound);
+                if (r.app != null && r.app.thread != null && ibr.hasBound) {
+                    try {
+                        bumpServiceExecutingLocked(r);
+                        updateOomAdjLocked(r.app);
+                        ibr.hasBound = false;
+                        r.app.thread.scheduleUnbindService(r,
+                                ibr.intent.getIntent());
+                    } catch (Exception e) {
+                        Log.w(TAG, "Exception when unbinding service "
+                                + r.shortName, e);
+                        serviceDoneExecutingLocked(r, true);
+                    }
+                }
+            }
+        }
+
+        if (DEBUG_SERVICE) Log.v(TAG, "Bringing down service " + r.name
+                 + " " + r.intent);
+        EventLog.writeEvent(LOG_AM_DESTROY_SERVICE,
+                System.identityHashCode(r), r.shortName,
+                (r.app != null) ? r.app.pid : -1);
+
+        mServices.remove(r.name);
+        mServicesByIntent.remove(r.intent);
+        if (localLOGV) Log.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
+        r.totalRestartCount = 0;
+        unscheduleServiceRestartLocked(r);
+
+        // Also make sure it is not on the pending list.
+        int N = mPendingServices.size();
+        for (int i=0; i<N; i++) {
+            if (mPendingServices.get(i) == r) {
+                mPendingServices.remove(i);
+                if (DEBUG_SERVICE) Log.v(
+                    TAG, "Removed pending service: " + r.shortName);
+                i--;
+                N--;
+            }
+        }
+
+        if (r.app != null) {
+            synchronized (r.stats.getBatteryStats()) {
+                r.stats.stopLaunchedLocked();
+            }
+            r.app.services.remove(r);
+            if (r.app.thread != null) {
+                updateServiceForegroundLocked(r.app, false);
+                try {
+                    Log.i(TAG, "Stopping service: " + r.shortName);
+                    bumpServiceExecutingLocked(r);
+                    mStoppingServices.add(r);
+                    updateOomAdjLocked(r.app);
+                    r.app.thread.scheduleStopService(r);
+                } catch (Exception e) {
+                    Log.w(TAG, "Exception when stopping service "
+                            + r.shortName, e);
+                    serviceDoneExecutingLocked(r, true);
+                }
+            } else {
+                if (DEBUG_SERVICE) Log.v(
+                    TAG, "Removed service that has no process: " + r.shortName);
+            }
+        } else {
+            if (DEBUG_SERVICE) Log.v(
+                TAG, "Removed service that is not running: " + r.shortName);
+        }
+    }
+
+    ComponentName startServiceLocked(IApplicationThread caller,
+            Intent service, String resolvedType,
+            int callingPid, int callingUid) {
+        synchronized(this) {
+            if (DEBUG_SERVICE) Log.v(TAG, "startService: " + service
+                    + " type=" + resolvedType + " args=" + service.getExtras());
+
+            if (caller != null) {
+                final ProcessRecord callerApp = getRecordForAppLocked(caller);
+                if (callerApp == null) {
+                    throw new SecurityException(
+                            "Unable to find app for caller " + caller
+                            + " (pid=" + Binder.getCallingPid()
+                            + ") when starting service " + service);
+                }
+            }
+
+            ServiceLookupResult res =
+                retrieveServiceLocked(service, resolvedType,
+                        callingPid, callingUid);
+            if (res == null) {
+                return null;
+            }
+            if (res.record == null) {
+                return new ComponentName("!", res.permission != null
+                        ? res.permission : "private to package");
+            }
+            ServiceRecord r = res.record;
+            if (unscheduleServiceRestartLocked(r)) {
+                if (DEBUG_SERVICE) Log.v(TAG, "START SERVICE WHILE RESTART PENDING: "
+                        + r.shortName);
+            }
+            r.startRequested = true;
+            r.startArgs.add(service);
+            r.lastStartId++;
+            if (r.lastStartId < 1) {
+                r.lastStartId = 1;
+            }
+            r.lastActivity = SystemClock.uptimeMillis();
+            synchronized (r.stats.getBatteryStats()) {
+                r.stats.startRunningLocked();
+            }
+            if (!bringUpServiceLocked(r, service.getFlags(), false)) {
+                return new ComponentName("!", "Service process is bad");
+            }
+            return r.name;
+        }
+    }
+
+    public ComponentName startService(IApplicationThread caller, Intent service,
+            String resolvedType) {
+        // Refuse possible leaked file descriptors
+        if (service != null && service.hasFileDescriptors() == true) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        synchronized(this) {
+            final int callingPid = Binder.getCallingPid();
+            final int callingUid = Binder.getCallingUid();
+            final long origId = Binder.clearCallingIdentity();
+            ComponentName res = startServiceLocked(caller, service,
+                    resolvedType, callingPid, callingUid);
+            Binder.restoreCallingIdentity(origId);
+            return res;
+        }
+    }
+
+    ComponentName startServiceInPackage(int uid,
+            Intent service, String resolvedType) {
+        synchronized(this) {
+            final long origId = Binder.clearCallingIdentity();
+            ComponentName res = startServiceLocked(null, service,
+                    resolvedType, -1, uid);
+            Binder.restoreCallingIdentity(origId);
+            return res;
+        }
+    }
+
+    public int stopService(IApplicationThread caller, Intent service,
+            String resolvedType) {
+        // Refuse possible leaked file descriptors
+        if (service != null && service.hasFileDescriptors() == true) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        synchronized(this) {
+            if (DEBUG_SERVICE) Log.v(TAG, "stopService: " + service
+                    + " type=" + resolvedType);
+
+            final ProcessRecord callerApp = getRecordForAppLocked(caller);
+            if (caller != null && callerApp == null) {
+                throw new SecurityException(
+                        "Unable to find app for caller " + caller
+                        + " (pid=" + Binder.getCallingPid()
+                        + ") when stopping service " + service);
+            }
+
+            // If this service is active, make sure it is stopped.
+            ServiceLookupResult r = findServiceLocked(service, resolvedType);
+            if (r != null) {
+                if (r.record != null) {
+                    synchronized (r.record.stats.getBatteryStats()) {
+                        r.record.stats.stopRunningLocked();
+                    }
+                    r.record.startRequested = false;
+                    final long origId = Binder.clearCallingIdentity();
+                    bringDownServiceLocked(r.record, false);
+                    Binder.restoreCallingIdentity(origId);
+                    return 1;
+                }
+                return -1;
+            }
+        }
+
+        return 0;
+    }
+
+    public IBinder peekService(Intent service, String resolvedType) {
+        // Refuse possible leaked file descriptors
+        if (service != null && service.hasFileDescriptors() == true) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        IBinder ret = null;
+
+        synchronized(this) {
+            ServiceLookupResult r = findServiceLocked(service, resolvedType);
+            
+            if (r != null) {
+                // r.record is null if findServiceLocked() failed the caller permission check
+                if (r.record == null) {
+                    throw new SecurityException(
+                            "Permission Denial: Accessing service " + r.record.name
+                            + " from pid=" + Binder.getCallingPid()
+                            + ", uid=" + Binder.getCallingUid()
+                            + " requires " + r.permission);
+                }
+                IntentBindRecord ib = r.record.bindings.get(r.record.intent);
+                if (ib != null) {
+                    ret = ib.binder;
+                }
+            }
+        }
+
+        return ret;
+    }
+    
+    public boolean stopServiceToken(ComponentName className, IBinder token,
+            int startId) {
+        synchronized(this) {
+            if (DEBUG_SERVICE) Log.v(TAG, "stopServiceToken: " + className
+                    + " " + token + " startId=" + startId);
+            ServiceRecord r = findServiceLocked(className, token);
+            if (r != null && (startId < 0 || r.lastStartId == startId)) {
+                synchronized (r.stats.getBatteryStats()) {
+                    r.stats.stopRunningLocked();
+                    r.startRequested = false;
+                }
+                final long origId = Binder.clearCallingIdentity();
+                bringDownServiceLocked(r, false);
+                Binder.restoreCallingIdentity(origId);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void setServiceForeground(ComponentName className, IBinder token,
+            boolean isForeground) {
+        synchronized(this) {
+            ServiceRecord r = findServiceLocked(className, token);
+            if (r != null) {
+                if (r.isForeground != isForeground) {
+                    final long origId = Binder.clearCallingIdentity();
+                    r.isForeground = isForeground;
+                    if (r.app != null) {
+                        updateServiceForegroundLocked(r.app, true);
+                    }
+                    Binder.restoreCallingIdentity(origId);
+                }
+            }
+        }
+    }
+
+    public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
+        boolean anyForeground = false;
+        for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
+            if (sr.isForeground) {
+                anyForeground = true;
+                break;
+            }
+        }
+        if (anyForeground != proc.foregroundServices) {
+            proc.foregroundServices = anyForeground;
+            if (oomAdj) {
+                updateOomAdjLocked();
+            }
+        }
+    }
+    
+    public int bindService(IApplicationThread caller, IBinder token,
+            Intent service, String resolvedType,
+            IServiceConnection connection, int flags) {
+        // Refuse possible leaked file descriptors
+        if (service != null && service.hasFileDescriptors() == true) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        synchronized(this) {
+            if (DEBUG_SERVICE) Log.v(TAG, "bindService: " + service
+                    + " type=" + resolvedType + " conn=" + connection.asBinder()
+                    + " flags=0x" + Integer.toHexString(flags));
+            final ProcessRecord callerApp = getRecordForAppLocked(caller);
+            if (callerApp == null) {
+                throw new SecurityException(
+                        "Unable to find app for caller " + caller
+                        + " (pid=" + Binder.getCallingPid()
+                        + ") when binding service " + service);
+            }
+
+            HistoryRecord activity = null;
+            if (token != null) {
+                int aindex = indexOfTokenLocked(token, false);
+                if (aindex < 0) {
+                    Log.w(TAG, "Binding with unknown activity: " + token);
+                    return 0;
+                }
+                activity = (HistoryRecord)mHistory.get(aindex);
+            }
+
+            ServiceLookupResult res =
+                retrieveServiceLocked(service, resolvedType,
+                        Binder.getCallingPid(), Binder.getCallingUid());
+            if (res == null) {
+                return 0;
+            }
+            if (res.record == null) {
+                return -1;
+            }
+            ServiceRecord s = res.record;
+
+            final long origId = Binder.clearCallingIdentity();
+
+            if (unscheduleServiceRestartLocked(s)) {
+                if (DEBUG_SERVICE) Log.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
+                        + s.shortName);
+            }
+
+            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
+            ConnectionRecord c = new ConnectionRecord(b, activity,
+                    connection, flags);
+
+            IBinder binder = connection.asBinder();
+            s.connections.put(binder, c);
+            b.connections.add(c);
+            if (activity != null) {
+                if (activity.connections == null) {
+                    activity.connections = new HashSet<ConnectionRecord>();
+                }
+                activity.connections.add(c);
+            }
+            b.client.connections.add(c);
+            mServiceConnections.put(binder, c);
+
+            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
+                s.lastActivity = SystemClock.uptimeMillis();
+                if (!bringUpServiceLocked(s, service.getFlags(), false)) {
+                    return 0;
+                }
+            }
+
+            if (s.app != null) {
+                // This could have made the service more important.
+                updateOomAdjLocked(s.app);
+            }
+
+            if (DEBUG_SERVICE) Log.v(TAG, "Bind " + s + " with " + b
+                    + ": received=" + b.intent.received
+                    + " apps=" + b.intent.apps.size()
+                    + " doRebind=" + b.intent.doRebind);
+
+            if (s.app != null && b.intent.received) {
+                // Service is already running, so we can immediately
+                // publish the connection.
+                try {
+                    c.conn.connected(s.name, b.intent.binder);
+                } catch (Exception e) {
+                    Log.w(TAG, "Failure sending service " + s.shortName
+                            + " to connection " + c.conn.asBinder()
+                            + " (in " + c.binding.client.processName + ")", e);
+                }
+
+                // If this is the first app connected back to this binding,
+                // and the service had previously asked to be told when
+                // rebound, then do so.
+                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
+                    requestServiceBindingLocked(s, b.intent, true);
+                }
+            } else if (!b.intent.requested) {
+                requestServiceBindingLocked(s, b.intent, false);
+            }
+
+            Binder.restoreCallingIdentity(origId);
+        }
+
+        return 1;
+    }
+
+    private void removeConnectionLocked(
+        ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
+        IBinder binder = c.conn.asBinder();
+        AppBindRecord b = c.binding;
+        ServiceRecord s = b.service;
+        s.connections.remove(binder);
+        b.connections.remove(c);
+        if (c.activity != null && c.activity != skipAct) {
+            if (c.activity.connections != null) {
+                c.activity.connections.remove(c);
+            }
+        }
+        if (b.client != skipApp) {
+            b.client.connections.remove(c);
+        }
+        mServiceConnections.remove(binder);
+
+        if (b.connections.size() == 0) {
+            b.intent.apps.remove(b.client);
+        }
+
+        if (DEBUG_SERVICE) Log.v(TAG, "Disconnecting binding " + b.intent
+                + ": shouldUnbind=" + b.intent.hasBound);
+        if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
+                && b.intent.hasBound) {
+            try {
+                bumpServiceExecutingLocked(s);
+                updateOomAdjLocked(s.app);
+                b.intent.hasBound = false;
+                // Assume the client doesn't want to know about a rebind;
+                // we will deal with that later if it asks for one.
+                b.intent.doRebind = false;
+                s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
+            } catch (Exception e) {
+                Log.w(TAG, "Exception when unbinding service " + s.shortName, e);
+                serviceDoneExecutingLocked(s, true);
+            }
+        }
+
+        if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
+            bringDownServiceLocked(s, false);
+        }
+    }
+
+    public boolean unbindService(IServiceConnection connection) {
+        synchronized (this) {
+            IBinder binder = connection.asBinder();
+            if (DEBUG_SERVICE) Log.v(TAG, "unbindService: conn=" + binder);
+            ConnectionRecord r = mServiceConnections.get(binder);
+            if (r == null) {
+                Log.w(TAG, "Unbind failed: could not find connection for "
+                      + connection.asBinder());
+                return false;
+            }
+
+            final long origId = Binder.clearCallingIdentity();
+
+            removeConnectionLocked(r, null, null);
+
+            if (r.binding.service.app != null) {
+                // This could have made the service less important.
+                updateOomAdjLocked(r.binding.service.app);
+            }
+
+            Binder.restoreCallingIdentity(origId);
+        }
+
+        return true;
+    }
+
+    public void publishService(IBinder token, Intent intent, IBinder service) {
+        // Refuse possible leaked file descriptors
+        if (intent != null && intent.hasFileDescriptors() == true) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        synchronized(this) {
+            if (!(token instanceof ServiceRecord)) {
+                throw new IllegalArgumentException("Invalid service token");
+            }
+            ServiceRecord r = (ServiceRecord)token;
+
+            final long origId = Binder.clearCallingIdentity();
+
+            if (DEBUG_SERVICE) Log.v(TAG, "PUBLISHING SERVICE " + r.name
+                    + " " + intent + ": " + service);
+            if (r != null) {
+                Intent.FilterComparison filter
+                        = new Intent.FilterComparison(intent);
+                IntentBindRecord b = r.bindings.get(filter);
+                if (b != null && !b.received) {
+                    b.binder = service;
+                    b.requested = true;
+                    b.received = true;
+                    if (r.connections.size() > 0) {
+                        Iterator<ConnectionRecord> it
+                                = r.connections.values().iterator();
+                        while (it.hasNext()) {
+                            ConnectionRecord c = it.next();
+                            if (!filter.equals(c.binding.intent.intent)) {
+                                if (DEBUG_SERVICE) Log.v(
+                                        TAG, "Not publishing to: " + c);
+                                if (DEBUG_SERVICE) Log.v(
+                                        TAG, "Bound intent: " + c.binding.intent.intent);
+                                if (DEBUG_SERVICE) Log.v(
+                                        TAG, "Published intent: " + intent);
+                                continue;
+                            }
+                            if (DEBUG_SERVICE) Log.v(TAG, "Publishing to: " + c);
+                            try {
+                                c.conn.connected(r.name, service);
+                            } catch (Exception e) {
+                                Log.w(TAG, "Failure sending service " + r.name +
+                                      " to connection " + c.conn.asBinder() +
+                                      " (in " + c.binding.client.processName + ")", e);
+                            }
+                        }
+                    }
+                }
+
+                serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
+
+                Binder.restoreCallingIdentity(origId);
+            }
+        }
+    }
+
+    public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
+        // Refuse possible leaked file descriptors
+        if (intent != null && intent.hasFileDescriptors() == true) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        synchronized(this) {
+            if (!(token instanceof ServiceRecord)) {
+                throw new IllegalArgumentException("Invalid service token");
+            }
+            ServiceRecord r = (ServiceRecord)token;
+
+            final long origId = Binder.clearCallingIdentity();
+
+            if (r != null) {
+                Intent.FilterComparison filter
+                        = new Intent.FilterComparison(intent);
+                IntentBindRecord b = r.bindings.get(filter);
+                if (DEBUG_SERVICE) Log.v(TAG, "unbindFinished in " + r
+                        + " at " + b + ": apps="
+                        + (b != null ? b.apps.size() : 0));
+                if (b != null) {
+                    if (b.apps.size() > 0) {
+                        // Applications have already bound since the last
+                        // unbind, so just rebind right here.
+                        requestServiceBindingLocked(r, b, true);
+                    } else {
+                        // Note to tell the service the next time there is
+                        // a new client.
+                        b.doRebind = true;
+                    }
+                }
+
+                serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
+
+                Binder.restoreCallingIdentity(origId);
+            }
+        }
+    }
+
+    public void serviceDoneExecuting(IBinder token) {
+        synchronized(this) {
+            if (!(token instanceof ServiceRecord)) {
+                throw new IllegalArgumentException("Invalid service token");
+            }
+            ServiceRecord r = (ServiceRecord)token;
+            boolean inStopping = mStoppingServices.contains(token);
+            if (r != null) {
+                if (DEBUG_SERVICE) Log.v(TAG, "DONE EXECUTING SERVICE " + r.name
+                        + ": nesting=" + r.executeNesting
+                        + ", inStopping=" + inStopping);
+                if (r != token) {
+                    Log.w(TAG, "Done executing service " + r.name
+                          + " with incorrect token: given " + token
+                          + ", expected " + r);
+                    return;
+                }
+
+                final long origId = Binder.clearCallingIdentity();
+                serviceDoneExecutingLocked(r, inStopping);
+                Binder.restoreCallingIdentity(origId);
+            } else {
+                Log.w(TAG, "Done executing unknown service " + r.name
+                        + " with token " + token);
+            }
+        }
+    }
+
+    public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
+        r.executeNesting--;
+        if (r.executeNesting <= 0 && r.app != null) {
+            r.app.executingServices.remove(r);
+            if (r.app.executingServices.size() == 0) {
+                mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
+            }
+            if (inStopping) {
+                mStoppingServices.remove(r);
+            }
+            updateOomAdjLocked(r.app);
+        }
+    }
+
+    void serviceTimeout(ProcessRecord proc) {
+        synchronized(this) {
+            if (proc.executingServices.size() == 0 || proc.thread == null) {
+                return;
+            }
+            long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
+            Iterator<ServiceRecord> it = proc.executingServices.iterator();
+            ServiceRecord timeout = null;
+            long nextTime = 0;
+            while (it.hasNext()) {
+                ServiceRecord sr = it.next();
+                if (sr.executingStart < maxTime) {
+                    timeout = sr;
+                    break;
+                }
+                if (sr.executingStart > nextTime) {
+                    nextTime = sr.executingStart;
+                }
+            }
+            if (timeout != null && mLRUProcesses.contains(proc)) {
+                Log.w(TAG, "Timeout executing service: " + timeout);
+                appNotRespondingLocked(proc, null, "Executing service "
+                        + timeout.name);
+            } else {
+                Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
+                msg.obj = proc;
+                mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
+            }
+        }
+    }
+    
+    // =========================================================
+    // BROADCASTS
+    // =========================================================
+
+    private final List getStickies(String action, IntentFilter filter,
+            List cur) {
+        final ContentResolver resolver = mContext.getContentResolver();
+        final ArrayList<Intent> list = mStickyBroadcasts.get(action);
+        if (list == null) {
+            return cur;
+        }
+        int N = list.size();
+        for (int i=0; i<N; i++) {
+            Intent intent = list.get(i);
+            if (filter.match(resolver, intent, true, TAG) >= 0) {
+                if (cur == null) {
+                    cur = new ArrayList<Intent>();
+                }
+                cur.add(intent);
+            }
+        }
+        return cur;
+    }
+
+    private final void scheduleBroadcastsLocked() {
+        if (DEBUG_BROADCAST) Log.v(TAG, "Schedule broadcasts: current="
+                + mBroadcastsScheduled);
+
+        if (mBroadcastsScheduled) {
+            return;
+        }
+        mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
+        mBroadcastsScheduled = true;
+    }
+
+    public Intent registerReceiver(IApplicationThread caller,
+            IIntentReceiver receiver, IntentFilter filter, String permission) {
+        synchronized(this) {
+            ProcessRecord callerApp = null;
+            if (caller != null) {
+                callerApp = getRecordForAppLocked(caller);
+                if (callerApp == null) {
+                    throw new SecurityException(
+                            "Unable to find app for caller " + caller
+                            + " (pid=" + Binder.getCallingPid()
+                            + ") when registering receiver " + receiver);
+                }
+            }
+
+            List allSticky = null;
+
+            // Look for any matching sticky broadcasts...
+            Iterator actions = filter.actionsIterator();
+            if (actions != null) {
+                while (actions.hasNext()) {
+                    String action = (String)actions.next();
+                    allSticky = getStickies(action, filter, allSticky);
+                }
+            } else {
+                allSticky = getStickies(null, filter, allSticky);
+            }
+
+            // The first sticky in the list is returned directly back to
+            // the client.
+            Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
+
+            if (DEBUG_BROADCAST) Log.v(TAG, "Register receiver " + filter
+                    + ": " + sticky);
+
+            if (receiver == null) {
+                return sticky;
+            }
+
+            ReceiverList rl
+                = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
+            if (rl == null) {
+                rl = new ReceiverList(this, callerApp,
+                        Binder.getCallingPid(),
+                        Binder.getCallingUid(), receiver);
+                if (rl.app != null) {
+                    rl.app.receivers.add(rl);
+                } else {
+                    try {
+                        receiver.asBinder().linkToDeath(rl, 0);
+                    } catch (RemoteException e) {
+                        return sticky;
+                    }
+                    rl.linkedToDeath = true;
+                }
+                mRegisteredReceivers.put(receiver.asBinder(), rl);
+            }
+            BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
+            rl.add(bf);
+            if (!bf.debugCheck()) {
+                Log.w(TAG, "==> For Dynamic broadast");
+            }
+            mReceiverResolver.addFilter(bf);
+
+            // Enqueue broadcasts for all existing stickies that match
+            // this filter.
+            if (allSticky != null) {
+                ArrayList receivers = new ArrayList();
+                receivers.add(bf);
+
+                int N = allSticky.size();
+                for (int i=0; i<N; i++) {
+                    Intent intent = (Intent)allSticky.get(i);
+                    BroadcastRecord r = new BroadcastRecord(intent, null,
+                            null, -1, -1, null, receivers, null, 0, null, null,
+                            false);
+                    if (mParallelBroadcasts.size() == 0) {
+                        scheduleBroadcastsLocked();
+                    }
+                    mParallelBroadcasts.add(r);
+                }
+            }
+
+            return sticky;
+        }
+    }
+
+    public void unregisterReceiver(IIntentReceiver receiver) {
+        if (DEBUG_BROADCAST) Log.v(TAG, "Unregister receiver: " + receiver);
+
+        boolean doNext = false;
+
+        synchronized(this) {
+            ReceiverList rl
+                = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
+            if (rl != null) {
+                if (rl.curBroadcast != null) {
+                    BroadcastRecord r = rl.curBroadcast;
+                    doNext = finishReceiverLocked(
+                        receiver.asBinder(), r.resultCode, r.resultData,
+                        r.resultExtras, r.resultAbort, true);
+                }
+
+                if (rl.app != null) {
+                    rl.app.receivers.remove(rl);
+                }
+                removeReceiverLocked(rl);
+                if (rl.linkedToDeath) {
+                    rl.linkedToDeath = false;
+                    rl.receiver.asBinder().unlinkToDeath(rl, 0);
+                }
+            }
+        }
+
+        if (!doNext) {
+            return;
+        }
+        
+        final long origId = Binder.clearCallingIdentity();
+        processNextBroadcast(false);
+        trimApplications();
+        Binder.restoreCallingIdentity(origId);
+    }
+
+    void removeReceiverLocked(ReceiverList rl) {
+        mRegisteredReceivers.remove(rl.receiver.asBinder());
+        int N = rl.size();
+        for (int i=0; i<N; i++) {
+            mReceiverResolver.removeFilter(rl.get(i));
+        }
+    }
+    
+    private final int broadcastIntentLocked(ProcessRecord callerApp,
+            String callerPackage, Intent intent, String resolvedType,
+            IIntentReceiver resultTo, int resultCode, String resultData,
+            Bundle map, String requiredPermission,
+            boolean ordered, boolean sticky, int callingPid, int callingUid) {
+        intent = new Intent(intent);
+
+        if (DEBUG_BROADCAST) Log.v(
+            TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
+            + " ordered=" + ordered);
+        if ((resultTo != null) && !ordered) {
+            Log.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
+        }
+        
+        // Handle special intents: if this broadcast is from the package
+        // manager about a package being removed, we need to remove all of
+        // its activities from the history stack.
+        final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
+                intent.getAction());
+        if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
+                || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
+                || uidRemoved) {
+            if (checkComponentPermission(
+                    android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
+                    callingPid, callingUid, -1)
+                    == PackageManager.PERMISSION_GRANTED) {
+                if (uidRemoved) {
+                    final Bundle intentExtras = intent.getExtras();
+                    final int uid = intentExtras != null
+                            ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
+                    if (uid >= 0) {
+                        BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
+                        synchronized (bs) {
+                            bs.removeUidStatsLocked(uid);
+                        }
+                    }
+                } else {
+                    Uri data = intent.getData();
+                    String ssp;
+                    if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
+                        if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
+                            uninstallPackageLocked(ssp,
+                                    intent.getIntExtra(Intent.EXTRA_UID, -1), false);
+                        }
+                    }
+                }
+            } else {
+                String msg = "Permission Denial: " + intent.getAction()
+                        + " broadcast from " + callerPackage + " (pid=" + callingPid
+                        + ", uid=" + callingUid + ")"
+                        + " requires "
+                        + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
+                Log.w(TAG, msg);
+                throw new SecurityException(msg);
+            }
+        }
+
+        /*
+         * If this is the time zone changed action, queue up a message that will reset the timezone
+         * of all currently running processes. This message will get queued up before the broadcast
+         * happens.
+         */
+        if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
+            mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
+        }
+
+        // Add to the sticky list if requested.
+        if (sticky) {
+            if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
+                    callingPid, callingUid)
+                    != PackageManager.PERMISSION_GRANTED) {
+                String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
+                        + callingPid + ", uid=" + callingUid
+                        + " requires " + android.Manifest.permission.BROADCAST_STICKY;
+                Log.w(TAG, msg);
+                throw new SecurityException(msg);
+            }
+            if (requiredPermission != null) {
+                Log.w(TAG, "Can't broadcast sticky intent " + intent
+                        + " and enforce permission " + requiredPermission);
+                return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
+            }
+            if (intent.getComponent() != null) {
+                throw new SecurityException(
+                        "Sticky broadcasts can't target a specific component");
+            }
+            ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
+            if (list == null) {
+                list = new ArrayList<Intent>();
+                mStickyBroadcasts.put(intent.getAction(), list);
+            }
+            int N = list.size();
+            int i;
+            for (i=0; i<N; i++) {
+                if (intent.filterEquals(list.get(i))) {
+                    // This sticky already exists, replace it.
+                    list.set(i, new Intent(intent));
+                    break;
+                }
+            }
+            if (i >= N) {
+                list.add(new Intent(intent));
+            }
+        }
+
+        final ContentResolver resolver = mContext.getContentResolver();
+
+        // Figure out who all will receive this broadcast.
+        List receivers = null;
+        List<BroadcastFilter> registeredReceivers = null;
+        try {
+            if (intent.getComponent() != null) {
+                // Broadcast is going to one specific receiver class...
+                ActivityInfo ai = ActivityThread.getPackageManager().
+                    getReceiverInfo(intent.getComponent(), 0);
+                if (ai != null) {
+                    receivers = new ArrayList();
+                    ResolveInfo ri = new ResolveInfo();
+                    ri.activityInfo = ai;
+                    receivers.add(ri);
+                }
+            } else {
+                // Need to resolve the intent to interested receivers...
+                if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
+                         == 0) {
+                    receivers =
+                        ActivityThread.getPackageManager().queryIntentReceivers(
+                                intent, resolvedType, PackageManager.GET_SHARED_LIBRARY_FILES);
+                }
+                registeredReceivers = mReceiverResolver.queryIntent(resolver,
+                        intent, resolvedType, false);
+            }
+        } catch (RemoteException ex) {
+            // pm is in same process, this will never happen.
+        }
+
+        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
+        if (!ordered && NR > 0) {
+            // If we are not serializing this broadcast, then send the
+            // registered receivers separately so they don't wait for the
+            // components to be launched.
+            BroadcastRecord r = new BroadcastRecord(intent, callerApp,
+                    callerPackage, callingPid, callingUid, requiredPermission,
+                    registeredReceivers, resultTo, resultCode, resultData, map,
+                    ordered);
+            if (DEBUG_BROADCAST) Log.v(
+                    TAG, "Enqueueing parallel broadcast " + r
+                    + ": prev had " + mParallelBroadcasts.size());
+            mParallelBroadcasts.add(r);
+            scheduleBroadcastsLocked();
+            registeredReceivers = null;
+            NR = 0;
+        }
+
+        // Merge into one list.
+        int ir = 0;
+        if (receivers != null) {
+            // A special case for PACKAGE_ADDED: do not allow the package
+            // being added to see this broadcast.  This prevents them from
+            // using this as a back door to get run as soon as they are
+            // installed.  Maybe in the future we want to have a special install
+            // broadcast or such for apps, but we'd like to deliberately make
+            // this decision.
+            String skipPackage = (intent.ACTION_PACKAGE_ADDED.equals(
+                    intent.getAction()) && intent.getData() != null)
+                    ? intent.getData().getSchemeSpecificPart()
+                    : null;
+            if (skipPackage != null && receivers != null) {
+                int NT = receivers.size();
+                for (int it=0; it<NT; it++) {
+                    ResolveInfo curt = (ResolveInfo)receivers.get(it);
+                    if (curt.activityInfo.packageName.equals(skipPackage)) {
+                        receivers.remove(it);
+                        it--;
+                        NT--;
+                    }
+                }
+            }
+
+            int NT = receivers != null ? receivers.size() : 0;
+            int it = 0;
+            ResolveInfo curt = null;
+            BroadcastFilter curr = null;
+            while (it < NT && ir < NR) {
+                if (curt == null) {
+                    curt = (ResolveInfo)receivers.get(it);
+                }
+                if (curr == null) {
+                    curr = registeredReceivers.get(ir);
+                }
+                if (curr.getPriority() >= curt.priority) {
+                    // Insert this broadcast record into the final list.
+                    receivers.add(it, curr);
+                    ir++;
+                    curr = null;
+                    it++;
+                    NT++;
+                } else {
+                    // Skip to the next ResolveInfo in the final list.
+                    it++;
+                    curt = null;
+                }
+            }
+        }
+        while (ir < NR) {
+            if (receivers == null) {
+                receivers = new ArrayList();
+            }
+            receivers.add(registeredReceivers.get(ir));
+            ir++;
+        }
+
+        if ((receivers != null && receivers.size() > 0)
+                || resultTo != null) {
+            BroadcastRecord r = new BroadcastRecord(intent, callerApp,
+                    callerPackage, callingPid, callingUid, requiredPermission,
+                    receivers, resultTo, resultCode, resultData, map, ordered);
+            if (DEBUG_BROADCAST) Log.v(
+                    TAG, "Enqueueing ordered broadcast " + r
+                    + ": prev had " + mOrderedBroadcasts.size());
+            if (DEBUG_BROADCAST) {
+                int seq = r.intent.getIntExtra("seq", -1);
+                Log.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
+            }
+            mOrderedBroadcasts.add(r);
+            scheduleBroadcastsLocked();
+        }
+
+        return BROADCAST_SUCCESS;
+    }
+
+    public final int broadcastIntent(IApplicationThread caller,
+            Intent intent, String resolvedType, IIntentReceiver resultTo,
+            int resultCode, String resultData, Bundle map,
+            String requiredPermission, boolean serialized, boolean sticky) {
+        // Refuse possible leaked file descriptors
+        if (intent != null && intent.hasFileDescriptors() == true) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        synchronized(this) {
+            if (!mSystemReady) {
+                // if the caller really truly claims to know what they're doing, go
+                // ahead and allow the broadcast without launching any receivers
+                int flags = intent.getFlags();
+                if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
+                    intent = new Intent(intent);
+                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
+                    Log.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
+                            + " before boot completion");
+                    throw new IllegalStateException("Cannot broadcast before boot completed");
+                }
+            }
+            
+            final ProcessRecord callerApp = getRecordForAppLocked(caller);
+            final int callingPid = Binder.getCallingPid();
+            final int callingUid = Binder.getCallingUid();
+            final long origId = Binder.clearCallingIdentity();
+            int res = broadcastIntentLocked(callerApp,
+                    callerApp != null ? callerApp.info.packageName : null,
+                    intent, resolvedType, resultTo,
+                    resultCode, resultData, map, requiredPermission, serialized,
+                    sticky, callingPid, callingUid);
+            Binder.restoreCallingIdentity(origId);
+            return res;
+        }
+    }
+
+    int broadcastIntentInPackage(String packageName, int uid,
+            Intent intent, String resolvedType, IIntentReceiver resultTo,
+            int resultCode, String resultData, Bundle map,
+            String requiredPermission, boolean serialized, boolean sticky) {
+        synchronized(this) {
+            final long origId = Binder.clearCallingIdentity();
+            int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
+                    resultTo, resultCode, resultData, map, requiredPermission,
+                    serialized, sticky, -1, uid);
+            Binder.restoreCallingIdentity(origId);
+            return res;
+        }
+    }
+
+    public final void unbroadcastIntent(IApplicationThread caller,
+            Intent intent) {
+        // Refuse possible leaked file descriptors
+        if (intent != null && intent.hasFileDescriptors() == true) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        synchronized(this) {
+            if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
+                    != PackageManager.PERMISSION_GRANTED) {
+                String msg = "Permission Denial: unbroadcastIntent() from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid()
+                        + " requires " + android.Manifest.permission.BROADCAST_STICKY;
+                Log.w(TAG, msg);
+                throw new SecurityException(msg);
+            }
+            ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
+            if (list != null) {
+                int N = list.size();
+                int i;
+                for (i=0; i<N; i++) {
+                    if (intent.filterEquals(list.get(i))) {
+                        list.remove(i);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
+            String resultData, Bundle resultExtras, boolean resultAbort,
+            boolean explicit) {
+        if (mOrderedBroadcasts.size() == 0) {
+            if (explicit) {
+                Log.w(TAG, "finishReceiver called but no pending broadcasts");
+            }
+            return false;
+        }
+        BroadcastRecord r = mOrderedBroadcasts.get(0);
+        if (r.receiver == null) {
+            if (explicit) {
+                Log.w(TAG, "finishReceiver called but none active");
+            }
+            return false;
+        }
+        if (r.receiver != receiver) {
+            Log.w(TAG, "finishReceiver called but active receiver is different");
+            return false;
+        }
+        int state = r.state;
+        r.state = r.IDLE;
+        if (state == r.IDLE) {
+            if (explicit) {
+                Log.w(TAG, "finishReceiver called but state is IDLE");
+            }
+        }
+        r.receiver = null;
+        r.intent.setComponent(null);
+        if (r.curApp != null) {
+            r.curApp.curReceiver = null;
+        }
+        if (r.curFilter != null) {
+            r.curFilter.receiverList.curBroadcast = null;
+        }
+        r.curFilter = null;
+        r.curApp = null;
+        r.curComponent = null;
+        r.curReceiver = null;
+        mPendingBroadcast = null;
+
+        r.resultCode = resultCode;
+        r.resultData = resultData;
+        r.resultExtras = resultExtras;
+        r.resultAbort = resultAbort;
+
+        // We will process the next receiver right now if this is finishing
+        // an app receiver (which is always asynchronous) or after we have
+        // come back from calling a receiver.
+        return state == BroadcastRecord.APP_RECEIVE
+                || state == BroadcastRecord.CALL_DONE_RECEIVE;
+    }
+
+    public void finishReceiver(IBinder who, int resultCode, String resultData,
+            Bundle resultExtras, boolean resultAbort) {
+        if (DEBUG_BROADCAST) Log.v(TAG, "Finish receiver: " + who);
+
+        // Refuse possible leaked file descriptors
+        if (resultExtras != null && resultExtras.hasFileDescriptors()) {
+            throw new IllegalArgumentException("File descriptors passed in Bundle");
+        }
+
+        boolean doNext;
+
+        final long origId = Binder.clearCallingIdentity();
+
+        synchronized(this) {
+            doNext = finishReceiverLocked(
+                who, resultCode, resultData, resultExtras, resultAbort, true);
+        }
+
+        if (doNext) {
+            processNextBroadcast(false);
+        }
+        trimApplications();
+
+        Binder.restoreCallingIdentity(origId);
+    }
+
+    private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
+        if (r.nextReceiver > 0) {
+            Object curReceiver = r.receivers.get(r.nextReceiver-1);
+            if (curReceiver instanceof BroadcastFilter) {
+                BroadcastFilter bf = (BroadcastFilter) curReceiver;
+                EventLog.writeEvent(LOG_AM_BROADCAST_DISCARD_FILTER,
+                        System.identityHashCode(r),
+                        r.intent.getAction(),
+                        r.nextReceiver - 1,
+                        System.identityHashCode(bf));
+            } else {
+                EventLog.writeEvent(LOG_AM_BROADCAST_DISCARD_APP,
+                        System.identityHashCode(r),
+                        r.intent.getAction(),
+                        r.nextReceiver - 1,
+                        ((ResolveInfo)curReceiver).toString());
+            }
+        } else {
+            Log.w(TAG, "Discarding broadcast before first receiver is invoked: "
+                    + r);
+            EventLog.writeEvent(LOG_AM_BROADCAST_DISCARD_APP,
+                    System.identityHashCode(r),
+                    r.intent.getAction(),
+                    r.nextReceiver,
+                    "NONE");
+        }
+    }
+
+    private final void broadcastTimeout() {
+        synchronized (this) {
+            if (mOrderedBroadcasts.size() == 0) {
+                return;
+            }
+            long now = SystemClock.uptimeMillis();
+            BroadcastRecord r = mOrderedBroadcasts.get(0);
+            if ((r.startTime+BROADCAST_TIMEOUT) > now) {
+                if (DEBUG_BROADCAST) Log.v(TAG,
+                        "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
+                        + (r.startTime + BROADCAST_TIMEOUT));
+                Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
+                mHandler.sendMessageAtTime(msg, r.startTime+BROADCAST_TIMEOUT);
+                return;
+            }
+
+            Log.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
+            r.startTime = now;
+            r.anrCount++;
+
+            // Current receiver has passed its expiration date.
+            if (r.nextReceiver <= 0) {
+                Log.w(TAG, "Timeout on receiver with nextReceiver <= 0");
+                return;
+            }
+
+            ProcessRecord app = null;
+
+            Object curReceiver = r.receivers.get(r.nextReceiver-1);
+            Log.w(TAG, "Receiver during timeout: " + curReceiver);
+            logBroadcastReceiverDiscard(r);
+            if (curReceiver instanceof BroadcastFilter) {
+                BroadcastFilter bf = (BroadcastFilter)curReceiver;
+                if (bf.receiverList.pid != 0
+                        && bf.receiverList.pid != MY_PID) {
+                    synchronized (this.mPidsSelfLocked) {
+                        app = this.mPidsSelfLocked.get(
+                                bf.receiverList.pid);
+                    }
+                }
+            } else {
+                app = r.curApp;
+            }
+            
+            if (app != null) {
+                appNotRespondingLocked(app, null, "Broadcast of " + r.intent.toString());
+            }
+
+            if (mPendingBroadcast == r) {
+                mPendingBroadcast = null;
+            }
+
+            // Move on to the next receiver.
+            finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
+                    r.resultExtras, r.resultAbort, true);
+            scheduleBroadcastsLocked();
+        }
+    }
+
+    private final void processCurBroadcastLocked(BroadcastRecord r,
+            ProcessRecord app) throws RemoteException {
+        if (app.thread == null) {
+            throw new RemoteException();
+        }
+        r.receiver = app.thread.asBinder();
+        r.curApp = app;
+        app.curReceiver = r;
+        updateLRUListLocked(app, true);
+
+        // Tell the application to launch this receiver.
+        r.intent.setComponent(r.curComponent);
+
+        boolean started = false;
+        try {
+            if (DEBUG_BROADCAST) Log.v(TAG,
+                    "Delivering to component " + r.curComponent
+                    + ": " + r);
+            app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
+                    r.resultCode, r.resultData, r.resultExtras, r.ordered);
+            started = true;
+        } finally {
+            if (!started) {
+                r.receiver = null;
+                r.curApp = null;
+                app.curReceiver = null;
+            }
+        }
+
+    }
+
+    static void performReceive(ProcessRecord app, IIntentReceiver receiver,
+            Intent intent, int resultCode, String data,
+            Bundle extras, boolean ordered) throws RemoteException {
+        if (app != null && app.thread != null) {
+            // If we have an app thread, do the call through that so it is
+            // correctly ordered with other one-way calls.
+            app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
+                    data, extras, ordered);
+        } else {
+            receiver.performReceive(intent, resultCode, data, extras, ordered);
+        }
+    }
+    
+    private final void deliverToRegisteredReceiver(BroadcastRecord r,
+            BroadcastFilter filter, boolean ordered) {
+        boolean skip = false;
+        if (filter.requiredPermission != null) {
+            int perm = checkComponentPermission(filter.requiredPermission,
+                    r.callingPid, r.callingUid, -1);
+            if (perm != PackageManager.PERMISSION_GRANTED) {
+                Log.w(TAG, "Permission Denial: broadcasting "
+                        + r.intent.toString()
+                        + " from " + r.callerPackage + " (pid="
+                        + r.callingPid + ", uid=" + r.callingUid + ")"
+                        + " requires " + filter.requiredPermission
+                        + " due to registered receiver " + filter);
+                skip = true;
+            }
+        }
+        if (r.requiredPermission != null) {
+            int perm = checkComponentPermission(r.requiredPermission,
+                    filter.receiverList.pid, filter.receiverList.uid, -1);
+            if (perm != PackageManager.PERMISSION_GRANTED) {
+                Log.w(TAG, "Permission Denial: receiving "
+                        + r.intent.toString()
+                        + " to " + filter.receiverList.app
+                        + " (pid=" + filter.receiverList.pid
+                        + ", uid=" + filter.receiverList.uid + ")"
+                        + " requires " + r.requiredPermission
+                        + " due to sender " + r.callerPackage
+                        + " (uid " + r.callingUid + ")");
+                skip = true;
+            }
+        }
+
+        if (!skip) {
+            // If this is not being sent as an ordered broadcast, then we
+            // don't want to touch the fields that keep track of the current
+            // state of ordered broadcasts.
+            if (ordered) {
+                r.receiver = filter.receiverList.receiver.asBinder();
+                r.curFilter = filter;
+                filter.receiverList.curBroadcast = r;
+                r.state = BroadcastRecord.CALL_IN_RECEIVE;
+            }
+            try {
+                if (DEBUG_BROADCAST) {
+                    int seq = r.intent.getIntExtra("seq", -1);
+                    Log.i(TAG, "Sending broadcast " + r.intent.getAction() + " seq=" + seq
+                            + " app=" + filter.receiverList.app);
+                }
+                performReceive(filter.receiverList.app, filter.receiverList.receiver,
+                    new Intent(r.intent), r.resultCode,
+                    r.resultData, r.resultExtras, r.ordered);
+                if (ordered) {
+                    r.state = BroadcastRecord.CALL_DONE_RECEIVE;
+                }
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failure sending broadcast " + r.intent, e);
+                if (ordered) {
+                    r.receiver = null;
+                    r.curFilter = null;
+                    filter.receiverList.curBroadcast = null;
+                }
+            }
+        }
+    }
+
+    private final void processNextBroadcast(boolean fromMsg) {
+        synchronized(this) {
+            BroadcastRecord r;
+
+            if (DEBUG_BROADCAST) Log.v(TAG, "processNextBroadcast: "
+                    + mParallelBroadcasts.size() + " broadcasts, "
+                    + mOrderedBroadcasts.size() + " serialized broadcasts");
+
+            updateCpuStats();
+            
+            if (fromMsg) {
+                mBroadcastsScheduled = false;
+            }
+
+            // First, deliver any non-serialized broadcasts right away.
+            while (mParallelBroadcasts.size() > 0) {
+                r = mParallelBroadcasts.remove(0);
+                final int N = r.receivers.size();
+                for (int i=0; i<N; i++) {
+                    Object target = r.receivers.get(i);
+                    if (DEBUG_BROADCAST)  Log.v(TAG,
+                            "Delivering non-serialized to registered "
+                            + target + ": " + r);
+                    deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
+                }
+            }
+
+            // Now take care of the next serialized one...
+
+            // If we are waiting for a process to come up to handle the next
+            // broadcast, then do nothing at this point.  Just in case, we
+            // check that the process we're waiting for still exists.
+            if (mPendingBroadcast != null) {
+                Log.i(TAG, "processNextBroadcast: waiting for "
+                        + mPendingBroadcast.curApp);
+
+                boolean isDead;
+                synchronized (mPidsSelfLocked) {
+                    isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
+                }
+                if (!isDead) {
+                    // It's still alive, so keep waiting
+                    return;
+                } else {
+                    Log.w(TAG, "pending app " + mPendingBroadcast.curApp
+                            + " died before responding to broadcast");
+                    mPendingBroadcast = null;
+                }
+            }
+
+            do {
+                if (mOrderedBroadcasts.size() == 0) {
+                    // No more broadcasts pending, so all done!
+                    scheduleAppGcsLocked();
+                    return;
+                }
+                r = mOrderedBroadcasts.get(0);
+                boolean forceReceive = false;
+
+                // Ensure that even if something goes awry with the timeout
+                // detection, we catch "hung" broadcasts here, discard them,
+                // and continue to make progress.  
+                int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
+                long now = SystemClock.uptimeMillis();
+                if (r.dispatchTime > 0) {
+                    if ((numReceivers > 0) &&
+                            (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
+                        Log.w(TAG, "Hung broadcast discarded after timeout failure:"
+                                + " now=" + now
+                                + " dispatchTime=" + r.dispatchTime
+                                + " startTime=" + r.startTime
+                                + " intent=" + r.intent
+                                + " numReceivers=" + numReceivers
+                                + " nextReceiver=" + r.nextReceiver
+                                + " state=" + r.state);
+                        broadcastTimeout(); // forcibly finish this broadcast
+                        forceReceive = true;
+                        r.state = BroadcastRecord.IDLE;
+                    }
+                }
+
+                if (r.state != BroadcastRecord.IDLE) {
+                    if (DEBUG_BROADCAST) Log.d(TAG,
+                            "processNextBroadcast() called when not idle (state="
+                            + r.state + ")");
+                    return;
+                }
+
+                if (r.receivers == null || r.nextReceiver >= numReceivers
+                        || r.resultAbort || forceReceive) {
+                    // No more receivers for this broadcast!  Send the final
+                    // result if requested...
+                    if (r.resultTo != null) {
+                        try {
+                            if (DEBUG_BROADCAST) {
+                                int seq = r.intent.getIntExtra("seq", -1);
+                                Log.i(TAG, "Finishing broadcast " + r.intent.getAction()
+                                        + " seq=" + seq + " app=" + r.callerApp);
+                            }
+                            performReceive(r.callerApp, r.resultTo,
+                                new Intent(r.intent), r.resultCode,
+                                r.resultData, r.resultExtras, false);
+                        } catch (RemoteException e) {
+                            Log.w(TAG, "Failure sending broadcast result of " + r.intent, e);
+                        }
+                    }
+                    
+                    if (DEBUG_BROADCAST) Log.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
+                    mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
+
+                    // ... and on to the next...
+                    mOrderedBroadcasts.remove(0);
+                    r = null;
+                    continue;
+                }
+            } while (r == null);
+
+            // Get the next receiver...
+            int recIdx = r.nextReceiver++;
+
+            // Keep track of when this receiver started, and make sure there
+            // is a timeout message pending to kill it if need be.
+            r.startTime = SystemClock.uptimeMillis();
+            if (recIdx == 0) {
+                r.dispatchTime = r.startTime;
+
+                if (DEBUG_BROADCAST) Log.v(TAG,
+                        "Submitting BROADCAST_TIMEOUT_MSG for "
+                        + (r.startTime + BROADCAST_TIMEOUT));
+                Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
+                mHandler.sendMessageAtTime(msg, r.startTime+BROADCAST_TIMEOUT);
+            }
+
+            Object nextReceiver = r.receivers.get(recIdx);
+            if (nextReceiver instanceof BroadcastFilter) {
+                // Simple case: this is a registered receiver who gets
+                // a direct call.
+                BroadcastFilter filter = (BroadcastFilter)nextReceiver;
+                if (DEBUG_BROADCAST)  Log.v(TAG,
+                        "Delivering serialized to registered "
+                        + filter + ": " + r);
+                deliverToRegisteredReceiver(r, filter, r.ordered);
+                if (r.receiver == null || !r.ordered) {
+                    // The receiver has already finished, so schedule to
+                    // process the next one.
+                    r.state = BroadcastRecord.IDLE;
+                    scheduleBroadcastsLocked();
+                }
+                return;
+            }
+
+            // Hard case: need to instantiate the receiver, possibly
+            // starting its application process to host it.
+
+            ResolveInfo info =
+                (ResolveInfo)nextReceiver;
+
+            boolean skip = false;
+            int perm = checkComponentPermission(info.activityInfo.permission,
+                    r.callingPid, r.callingUid,
+                    info.activityInfo.exported
+                            ? -1 : info.activityInfo.applicationInfo.uid);
+            if (perm != PackageManager.PERMISSION_GRANTED) {
+                Log.w(TAG, "Permission Denial: broadcasting "
+                        + r.intent.toString()
+                        + " from " + r.callerPackage + " (pid=" + r.callingPid
+                        + ", uid=" + r.callingUid + ")"
+                        + " requires " + info.activityInfo.permission
+                        + " due to receiver " + info.activityInfo.packageName
+                        + "/" + info.activityInfo.name);
+                skip = true;
+            }
+            if (r.callingUid != Process.SYSTEM_UID &&
+                r.requiredPermission != null) {
+                try {
+                    perm = ActivityThread.getPackageManager().
+                            checkPermission(r.requiredPermission,
+                                    info.activityInfo.applicationInfo.packageName);
+                } catch (RemoteException e) {
+                    perm = PackageManager.PERMISSION_DENIED;
+                }
+                if (perm != PackageManager.PERMISSION_GRANTED) {
+                    Log.w(TAG, "Permission Denial: receiving "
+                            + r.intent + " to "
+                            + info.activityInfo.applicationInfo.packageName
+                            + " requires " + r.requiredPermission
+                            + " due to sender " + r.callerPackage
+                            + " (uid " + r.callingUid + ")");
+                    skip = true;
+                }
+            }
+            if (r.curApp != null && r.curApp.crashing) {
+                // If the target process is crashing, just skip it.
+                skip = true;
+            }
+
+            if (skip) {
+                r.receiver = null;
+                r.curFilter = null;
+                r.state = BroadcastRecord.IDLE;
+                scheduleBroadcastsLocked();
+                return;
+            }
+
+            r.state = BroadcastRecord.APP_RECEIVE;
+            String targetProcess = info.activityInfo.processName;
+            r.curComponent = new ComponentName(
+                    info.activityInfo.applicationInfo.packageName,
+                    info.activityInfo.name);
+            r.curReceiver = info.activityInfo;
+
+            // Is this receiver's application already running?
+            ProcessRecord app = getProcessRecordLocked(targetProcess,
+                    info.activityInfo.applicationInfo.uid);
+            if (app != null && app.thread != null) {
+                try {
+                    processCurBroadcastLocked(r, app);
+                    return;
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Exception when sending broadcast to "
+                          + r.curComponent, e);
+                }
+
+                // If a dead object exception was thrown -- fall through to
+                // restart the application.
+            }
+
+            // Not running -- get it started, and enqueue this history record
+            // to be executed when the app comes up.
+            if ((r.curApp=startProcessLocked(targetProcess,
+                    info.activityInfo.applicationInfo, true,
+                    r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
+                    "broadcast", r.curComponent)) == null) {
+                // Ah, this recipient is unavailable.  Finish it if necessary,
+                // and mark the broadcast record as ready for the next.
+                Log.w(TAG, "Unable to launch app "
+                        + info.activityInfo.applicationInfo.packageName + "/"
+                        + info.activityInfo.applicationInfo.uid + " for broadcast "
+                        + r.intent + ": process is bad");
+                logBroadcastReceiverDiscard(r);
+                finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
+                        r.resultExtras, r.resultAbort, true);
+                scheduleBroadcastsLocked();
+                r.state = BroadcastRecord.IDLE;
+                return;
+            }
+
+            mPendingBroadcast = r;
+        }
+    }
+
+    // =========================================================
+    // INSTRUMENTATION
+    // =========================================================
+
+    public boolean startInstrumentation(ComponentName className,
+            String profileFile, int flags, Bundle arguments,
+            IInstrumentationWatcher watcher) {
+        // Refuse possible leaked file descriptors
+        if (arguments != null && arguments.hasFileDescriptors()) {
+            throw new IllegalArgumentException("File descriptors passed in Bundle");
+        }
+
+        synchronized(this) {
+            InstrumentationInfo ii = null;
+            ApplicationInfo ai = null;
+            try {
+                ii = mContext.getPackageManager().getInstrumentationInfo(
+                    className, 0);
+                ai = mContext.getPackageManager().getApplicationInfo(
+                    ii.targetPackage, PackageManager.GET_SHARED_LIBRARY_FILES);
+            } catch (PackageManager.NameNotFoundException e) {
+            }
+            if (ii == null) {
+                reportStartInstrumentationFailure(watcher, className,
+                        "Unable to find instrumentation info for: " + className);
+                return false;
+            }
+            if (ai == null) {
+                reportStartInstrumentationFailure(watcher, className,
+                        "Unable to find instrumentation target package: " + ii.targetPackage);
+                return false;
+            }
+
+            int match = mContext.getPackageManager().checkSignatures(
+                    ii.targetPackage, ii.packageName);
+            if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
+                String msg = "Permission Denial: starting instrumentation "
+                        + className + " from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingPid()
+                        + " not allowed because package " + ii.packageName
+                        + " does not have a signature matching the target "
+                        + ii.targetPackage;
+                reportStartInstrumentationFailure(watcher, className, msg);
+                throw new SecurityException(msg);
+            }
+
+            final long origId = Binder.clearCallingIdentity();
+            uninstallPackageLocked(ii.targetPackage, -1, true);
+            ProcessRecord app = addAppLocked(ai);
+            app.instrumentationClass = className;
+            app.instrumentationProfileFile = profileFile;
+            app.instrumentationArguments = arguments;
+            app.instrumentationWatcher = watcher;
+            app.instrumentationResultClass = className;
+            Binder.restoreCallingIdentity(origId);
+        }
+
+        return true;
+    }
+    
+    /**
+     * Report errors that occur while attempting to start Instrumentation.  Always writes the 
+     * error to the logs, but if somebody is watching, send the report there too.  This enables
+     * the "am" command to report errors with more information.
+     * 
+     * @param watcher The IInstrumentationWatcher.  Null if there isn't one.
+     * @param cn The component name of the instrumentation.
+     * @param report The error report.
+     */
+    private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher, 
+            ComponentName cn, String report) {
+        Log.w(TAG, report);
+        try {
+            if (watcher != null) {
+                Bundle results = new Bundle();
+                results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
+                results.putString("Error", report);
+                watcher.instrumentationStatus(cn, -1, results);
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+        }
+    }
+
+    void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
+        if (app.instrumentationWatcher != null) {
+            try {
+                // NOTE:  IInstrumentationWatcher *must* be oneway here
+                app.instrumentationWatcher.instrumentationFinished(
+                    app.instrumentationClass,
+                    resultCode,
+                    results);
+            } catch (RemoteException e) {
+            }
+        }
+        app.instrumentationWatcher = null;
+        app.instrumentationClass = null;
+        app.instrumentationProfileFile = null;
+        app.instrumentationArguments = null;
+
+        uninstallPackageLocked(app.processName, -1, false);
+    }
+
+    public void finishInstrumentation(IApplicationThread target,
+            int resultCode, Bundle results) {
+        // Refuse possible leaked file descriptors
+        if (results != null && results.hasFileDescriptors()) {
+            throw new IllegalArgumentException("File descriptors passed in Intent");
+        }
+
+        synchronized(this) {
+            ProcessRecord app = getRecordForAppLocked(target);
+            if (app == null) {
+                Log.w(TAG, "finishInstrumentation: no app for " + target);
+                return;
+            }
+            final long origId = Binder.clearCallingIdentity();
+            finishInstrumentationLocked(app, resultCode, results);
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    // =========================================================
+    // CONFIGURATION
+    // =========================================================
+    
+    public ConfigurationInfo getDeviceConfigurationInfo() {
+        ConfigurationInfo config = new ConfigurationInfo();
+        synchronized (this) {
+            config.reqTouchScreen = mConfiguration.touchscreen;
+            config.reqKeyboardType = mConfiguration.keyboard;
+            config.reqNavigation = mConfiguration.navigation;
+            if (mConfiguration.navigation != Configuration.NAVIGATION_NONAV) {
+                config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
+            }
+            if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED) {
+                config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
+            }
+        }
+        return config;
+    }
+
+    public Configuration getConfiguration() {
+        Configuration ci;
+        synchronized(this) {
+            ci = new Configuration(mConfiguration);
+        }
+        return ci;
+    }
+
+    public void updateConfiguration(Configuration values) {
+        enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
+                "updateConfiguration()");
+
+        synchronized(this) {
+            if (values == null && mWindowManager != null) {
+                // sentinel: fetch the current configuration from the window manager
+                values = mWindowManager.computeNewConfiguration();
+            }
+            
+            final long origId = Binder.clearCallingIdentity();
+            updateConfigurationLocked(values, null);
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    /**
+     * Do either or both things: (1) change the current configuration, and (2)
+     * make sure the given activity is running with the (now) current
+     * configuration.  Returns true if the activity has been left running, or
+     * false if <var>starting</var> is being destroyed to match the new
+     * configuration.
+     */
+    public boolean updateConfigurationLocked(Configuration values,
+            HistoryRecord starting) {
+        int changes = 0;
+        
+        boolean kept = true;
+        
+        if (values != null) {
+            Configuration newConfig = new Configuration(mConfiguration);
+            changes = newConfig.updateFrom(values);
+            if (changes != 0) {
+                if (DEBUG_SWITCH) {
+                    Log.i(TAG, "Updating configuration to: " + values);
+                }
+                
+                EventLog.writeEvent(LOG_CONFIGURATION_CHANGED, changes);
+
+                if (values.locale != null) {
+                    saveLocaleLocked(values.locale, 
+                                     !values.locale.equals(mConfiguration.locale),
+                                     values.userSetLocale);
+                }
+
+                mConfiguration = newConfig;
+
+                Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
+                msg.obj = new Configuration(mConfiguration);
+                mHandler.sendMessage(msg);
+        
+                final int N = mLRUProcesses.size();
+                for (int i=0; i<N; i++) {
+                    ProcessRecord app = mLRUProcesses.get(i);
+                    try {
+                        if (app.thread != null) {
+                            app.thread.scheduleConfigurationChanged(mConfiguration);
+                        }
+                    } catch (Exception e) {
+                    }
+                }
+                Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
+                broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
+                        null, false, false, MY_PID, Process.SYSTEM_UID);
+            }
+        }
+        
+        if (changes != 0 && starting == null) {
+            // If the configuration changed, and the caller is not already
+            // in the process of starting an activity, then find the top
+            // activity to check if its configuration needs to change.
+            starting = topRunningActivityLocked(null);
+        }
+        
+        if (starting != null) {
+            kept = ensureActivityConfigurationLocked(starting, changes);
+            if (kept) {
+                // If this didn't result in the starting activity being
+                // destroyed, then we need to make sure at this point that all
+                // other activities are made visible.
+                if (DEBUG_SWITCH) Log.i(TAG, "Config didn't destroy " + starting
+                        + ", ensuring others are correct.");
+                ensureActivitiesVisibleLocked(starting, changes);
+            }
+        }
+        
+        return kept;
+    }
+
+    private final boolean relaunchActivityLocked(HistoryRecord r,
+            int changes, boolean andResume) {
+        List<ResultInfo> results = null;
+        List<Intent> newIntents = null;
+        if (andResume) {
+            results = r.results;
+            newIntents = r.newIntents;
+        }
+        if (DEBUG_SWITCH) Log.v(TAG, "Relaunching: " + r
+                + " with results=" + results + " newIntents=" + newIntents
+                + " andResume=" + andResume);
+        EventLog.writeEvent(andResume ? LOG_AM_RELAUNCH_RESUME_ACTIVITY
+                : LOG_AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
+                r.task.taskId, r.shortComponentName);
+        
+        r.startFreezingScreenLocked(r.app, 0);
+        
+        try {
+            if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting resumed " + r);
+            r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
+                    changes, !andResume);
+            // Note: don't need to call pauseIfSleepingLocked() here, because
+            // the caller will only pass in 'andResume' if this activity is
+            // currently resumed, which implies we aren't sleeping.
+        } catch (RemoteException e) {
+            return false;
+        }
+
+        if (andResume) {
+            r.results = null;
+            r.newIntents = null;
+        }
+
+        return true;
+    }
+
+    /**
+     * Make sure the given activity matches the current configuration.  Returns
+     * false if the activity had to be destroyed.  Returns true if the
+     * configuration is the same, or the activity will remain running as-is
+     * for whatever reason.  Ensures the HistoryRecord is updated with the
+     * correct configuration and all other bookkeeping is handled.
+     */
+    private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
+            int globalChanges) {
+        if (DEBUG_SWITCH) Log.i(TAG, "Ensuring correct configuration: " + r);
+        
+        // Short circuit: if the two configurations are the exact same
+        // object (the common case), then there is nothing to do.
+        Configuration newConfig = mConfiguration;
+        if (r.configuration == newConfig) {
+            if (DEBUG_SWITCH) Log.i(TAG, "Configuration unchanged in " + r);
+            return true;
+        }
+        
+        // We don't worry about activities that are finishing.
+        if (r.finishing) {
+            if (DEBUG_SWITCH) Log.i(TAG,
+                    "Configuration doesn't matter in finishing " + r);
+            r.stopFreezingScreenLocked(false);
+            return true;
+        }
+        
+        // Okay we now are going to make this activity have the new config.
+        // But then we need to figure out how it needs to deal with that.
+        Configuration oldConfig = r.configuration;
+        r.configuration = newConfig;
+        
+        // If the activity isn't currently running, just leave the new
+        // configuration and it will pick that up next time it starts.
+        if (r.app == null || r.app.thread == null) {
+            if (DEBUG_SWITCH) Log.i(TAG,
+                    "Configuration doesn't matter not running " + r);
+            r.stopFreezingScreenLocked(false);
+            return true;
+        }
+        
+        // If the activity isn't persistent, there is a chance we will
+        // need to restart it.
+        if (!r.persistent) {
+
+            // Figure out what has changed between the two configurations.
+            int changes = oldConfig.diff(newConfig);
+            if (DEBUG_SWITCH) {
+                Log.i(TAG, "Checking to restart " + r.info.name + ": changed=0x"
+                        + Integer.toHexString(changes) + ", handles=0x"
+                        + Integer.toHexString(r.info.configChanges));
+            }
+            if ((changes&(~r.info.configChanges)) != 0) {
+                // Aha, the activity isn't handling the change, so DIE DIE DIE.
+                r.configChangeFlags |= changes;
+                r.startFreezingScreenLocked(r.app, globalChanges);
+                if (r.app == null || r.app.thread == null) {
+                    if (DEBUG_SWITCH) Log.i(TAG, "Switch is destroying non-running " + r);
+                    destroyActivityLocked(r, true);
+                } else if (r.state == ActivityState.PAUSING) {
+                    // A little annoying: we are waiting for this activity to
+                    // finish pausing.  Let's not do anything now, but just
+                    // flag that it needs to be restarted when done pausing.
+                    r.configDestroy = true;
+                    return true;
+                } else if (r.state == ActivityState.RESUMED) {
+                    // Try to optimize this case: the configuration is changing
+                    // and we need to restart the top, resumed activity.
+                    // Instead of doing the normal handshaking, just say
+                    // "restart!".
+                    if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting resumed " + r);
+                    relaunchActivityLocked(r, r.configChangeFlags, true);
+                    r.configChangeFlags = 0;
+                } else {
+                    if (DEBUG_SWITCH) Log.i(TAG, "Switch is restarting non-resumed " + r);
+                    relaunchActivityLocked(r, r.configChangeFlags, false);
+                    r.configChangeFlags = 0;
+                }
+                
+                // All done...  tell the caller we weren't able to keep this
+                // activity around.
+                return false;
+            }
+        }
+        
+        // Default case: the activity can handle this new configuration, so
+        // hand it over.  Note that we don't need to give it the new
+        // configuration, since we always send configuration changes to all
+        // process when they happen so it can just use whatever configuration
+        // it last got.
+        if (r.app != null && r.app.thread != null) {
+            try {
+                r.app.thread.scheduleActivityConfigurationChanged(r);
+            } catch (RemoteException e) {
+                // If process died, whatever.
+            }
+        }
+        r.stopFreezingScreenLocked(false);
+        
+        return true;
+    }
+    
+    /**
+     * Save the locale.  You must be inside a synchronized (this) block.
+     */
+    private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
+        if(isDiff) {
+            SystemProperties.set("user.language", l.getLanguage());
+            SystemProperties.set("user.region", l.getCountry());
+        } 
+
+        if(isPersist) {
+            SystemProperties.set("persist.sys.language", l.getLanguage());
+            SystemProperties.set("persist.sys.country", l.getCountry());
+            SystemProperties.set("persist.sys.localevar", l.getVariant());
+        }
+    }
+
+    // =========================================================
+    // LIFETIME MANAGEMENT
+    // =========================================================
+
+    private final int computeOomAdjLocked(
+        ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
+        if (mAdjSeq == app.adjSeq) {
+            // This adjustment has already been computed.
+            return app.curAdj;
+        }
+
+        if (app.thread == null) {
+            app.adjSeq = mAdjSeq;
+            return (app.curAdj=EMPTY_APP_ADJ);
+        }
+
+        app.isForeground = false;
+
+        // Right now there are three interesting states: it is
+        // either the foreground app, background with activities,
+        // or background without activities.
+        int adj;
+        int N;
+        if (app == TOP_APP || app.instrumentationClass != null
+                || app.persistentActivities > 0) {
+            // The last app on the list is the foreground app.
+            adj = FOREGROUND_APP_ADJ;
+            app.isForeground = true;
+        } else if (app.curReceiver != null ||
+                (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
+            // An app that is currently receiving a broadcast also
+            // counts as being in the foreground.
+            adj = FOREGROUND_APP_ADJ;
+        } else if (app.executingServices.size() > 0) {
+            // An app that is currently executing a service callback also
+            // counts as being in the foreground.
+            adj = FOREGROUND_APP_ADJ;
+        } else if (app.foregroundServices || app.forcingToForeground != null) {
+            // The user is aware of this app, so make it visible.
+            adj = VISIBLE_APP_ADJ;
+        } else if ((N=app.activities.size()) != 0) {
+            // This app is in the background with paused activities.
+            adj = hiddenAdj;
+            for (int j=0; j<N; j++) {
+                if (((HistoryRecord)app.activities.get(j)).visible) {
+                    // This app has a visible activity!
+                    adj = VISIBLE_APP_ADJ;
+                    break;
+                }
+            }
+        } else {
+            // A very not-needed process.
+            adj = EMPTY_APP_ADJ;
+        }
+
+        // By default, we use the computed adjusted.  It may be changed if
+        // there are applications dependent on our services or providers, but
+        // this gives us a baseline and makes sure we don't get into an
+        // infinite recursion.
+        app.adjSeq = mAdjSeq;
+        app.curRawAdj = adj;
+        app.curAdj = adj <= app.maxAdj ? adj : app.maxAdj;
+
+        if (app.services.size() != 0 && adj > FOREGROUND_APP_ADJ) {
+            // If this process has active services running in it, we would
+            // like to avoid killing it unless it would prevent the current
+            // application from running.
+            if (adj > hiddenAdj) {
+                adj = hiddenAdj;
+            }
+            final long now = SystemClock.uptimeMillis();
+            // This process is more important if the top activity is
+            // bound to the service.
+            Iterator jt = app.services.iterator();
+            while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
+                ServiceRecord s = (ServiceRecord)jt.next();
+                if (s.startRequested) {
+                    if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
+                        // This service has seen some activity within
+                        // recent memory, so we will keep its process ahead
+                        // of the background processes.
+                        if (adj > SECONDARY_SERVER_ADJ) {
+                            adj = SECONDARY_SERVER_ADJ;
+                        }
+                    } else {
+                        // This service has been inactive for too long, just
+                        // put it with the rest of the background processes.
+                        if (adj > hiddenAdj) {
+                            adj = hiddenAdj;
+                        }
+                    }
+                }
+                if (s.connections.size() > 0 && adj > FOREGROUND_APP_ADJ) {
+                    Iterator<ConnectionRecord> kt
+                            = s.connections.values().iterator();
+                    while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
+                        // XXX should compute this based on the max of
+                        // all connected clients.
+                        ConnectionRecord cr = kt.next();
+                        if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
+                            ProcessRecord client = cr.binding.client;
+                            int myHiddenAdj = hiddenAdj;
+                            if (myHiddenAdj > client.hiddenAdj) {
+                                if (client.hiddenAdj > VISIBLE_APP_ADJ) {
+                                    myHiddenAdj = client.hiddenAdj;
+                                } else {
+                                    myHiddenAdj = VISIBLE_APP_ADJ;
+                                }
+                            }
+                            int clientAdj = computeOomAdjLocked(
+                                client, myHiddenAdj, TOP_APP);
+                            if (adj > clientAdj) {
+                                adj = clientAdj > VISIBLE_APP_ADJ
+                                        ? clientAdj : VISIBLE_APP_ADJ;
+                            }
+                        }
+                        HistoryRecord a = cr.activity;
+                        //if (a != null) {
+                        //    Log.i(TAG, "Connection to " + a ": state=" + a.state);
+                        //}
+                        if (a != null && adj > FOREGROUND_APP_ADJ &&
+                                (a.state == ActivityState.RESUMED
+                                 || a.state == ActivityState.PAUSING)) {
+                            adj = FOREGROUND_APP_ADJ;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (app.pubProviders.size() != 0 && adj > FOREGROUND_APP_ADJ) {
+            // If this process has published any content providers, then
+            // its adjustment makes it at least as important as any of the
+            // processes using those providers, and no less important than
+            // CONTENT_PROVIDER_ADJ, which is just shy of EMPTY.
+            if (adj > CONTENT_PROVIDER_ADJ) {
+                adj = CONTENT_PROVIDER_ADJ;
+            }
+            Iterator jt = app.pubProviders.values().iterator();
+            while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
+                ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
+                if (cpr.clients.size() != 0) {
+                    Iterator<ProcessRecord> kt = cpr.clients.iterator();
+                    while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
+                        ProcessRecord client = kt.next();
+                        int myHiddenAdj = hiddenAdj;
+                        if (myHiddenAdj > client.hiddenAdj) {
+                            if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
+                                myHiddenAdj = client.hiddenAdj;
+                            } else {
+                                myHiddenAdj = FOREGROUND_APP_ADJ;
+                            }
+                        }
+                        int clientAdj = computeOomAdjLocked(
+                            client, myHiddenAdj, TOP_APP);
+                        if (adj > clientAdj) {
+                            adj = clientAdj > FOREGROUND_APP_ADJ
+                            ? clientAdj : FOREGROUND_APP_ADJ;
+                        }
+                    }
+                }
+                // If the provider has external (non-framework) process
+                // dependencies, ensure that its adjustment is at least
+                // FOREGROUND_APP_ADJ.
+                if (cpr.externals != 0) {
+                    if (adj > FOREGROUND_APP_ADJ) {
+                        adj = FOREGROUND_APP_ADJ;
+                    }
+                }
+            }
+        }
+
+        app.curRawAdj = adj;
+        
+        //Log.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
+        //      " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
+        if (adj > app.maxAdj) {
+            adj = app.maxAdj;
+        }
+
+        app.curAdj = adj;
+
+        return adj;
+    }
+
+    /**
+     * Ask a given process to GC right now.
+     */
+    final void performAppGcLocked(ProcessRecord app) {
+        try {
+            app.lastRequestedGc = SystemClock.uptimeMillis();
+            if (app.thread != null) {
+                app.thread.processInBackground();
+            }
+        } catch (Exception e) {
+            // whatever.
+        }
+    }
+    
+    /**
+     * Returns true if things are idle enough to perform GCs.
+     */
+    private final boolean canGcNow() {
+        return mParallelBroadcasts.size() == 0
+                && mOrderedBroadcasts.size() == 0
+                && (mSleeping || (mResumedActivity != null &&
+                        mResumedActivity.idle));
+    }
+    
+    /**
+     * Perform GCs on all processes that are waiting for it, but only
+     * if things are idle.
+     */
+    final void performAppGcsLocked() {
+        final int N = mProcessesToGc.size();
+        if (N <= 0) {
+            return;
+        }
+        if (canGcNow()) {
+            while (mProcessesToGc.size() > 0) {
+                ProcessRecord proc = mProcessesToGc.remove(0);
+                if (proc.curRawAdj > VISIBLE_APP_ADJ) {
+                    // To avoid spamming the system, we will GC processes one
+                    // at a time, waiting a few seconds between each.
+                    performAppGcLocked(proc);
+                    scheduleAppGcsLocked();
+                    return;
+                }
+            }
+        }
+    }
+    
+    /**
+     * If all looks good, perform GCs on all processes waiting for them.
+     */
+    final void performAppGcsIfAppropriateLocked() {
+        if (canGcNow()) {
+            performAppGcsLocked();
+            return;
+        }
+        // Still not idle, wait some more.
+        scheduleAppGcsLocked();
+    }
+
+    /**
+     * Schedule the execution of all pending app GCs.
+     */
+    final void scheduleAppGcsLocked() {
+        mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
+        Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
+        mHandler.sendMessageDelayed(msg, GC_TIMEOUT);
+    }
+    
+    /**
+     * Set up to ask a process to GC itself.  This will either do it
+     * immediately, or put it on the list of processes to gc the next
+     * time things are idle.
+     */
+    final void scheduleAppGcLocked(ProcessRecord app) {
+        long now = SystemClock.uptimeMillis();
+        if ((app.lastRequestedGc+5000) > now) {
+            return;
+        }
+        if (!mProcessesToGc.contains(app)) {
+            mProcessesToGc.add(app);
+            scheduleAppGcsLocked();
+        }
+    }
+
+    private final boolean updateOomAdjLocked(
+        ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
+        app.hiddenAdj = hiddenAdj;
+
+        if (app.thread == null) {
+            return true;
+        }
+
+        int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP);
+
+        //Log.i(TAG, "Computed adj " + adj + " for app " + app.processName);
+        //Thread priority adjustment is disabled out to see
+        //how the kernel scheduler performs.
+        if (false) {
+            if (app.pid != 0 && app.isForeground != app.setIsForeground) {
+                app.setIsForeground = app.isForeground;
+                if (app.pid != MY_PID) {
+                    if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(TAG, "Setting priority of " + app
+                            + " to " + (app.isForeground
+                            ? Process.THREAD_PRIORITY_FOREGROUND
+                            : Process.THREAD_PRIORITY_DEFAULT));
+                    try {
+                        Process.setThreadPriority(app.pid, app.isForeground
+                                ? Process.THREAD_PRIORITY_FOREGROUND
+                                : Process.THREAD_PRIORITY_DEFAULT);
+                    } catch (RuntimeException e) {
+                        Log.w(TAG, "Exception trying to set priority of application thread "
+                                + app.pid, e);
+                    }
+                }
+            }
+        }
+        if (app.pid != 0 && app.pid != MY_PID) {
+            if (app.curRawAdj != app.setRawAdj) {
+                if (app.curRawAdj > FOREGROUND_APP_ADJ
+                        && app.setRawAdj <= FOREGROUND_APP_ADJ) {
+                    // If this app is transitioning from foreground to
+                    // non-foreground, have it do a gc.
+                    scheduleAppGcLocked(app);
+                } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
+                        && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
+                    // Likewise do a gc when an app is moving in to the
+                    // background (such as a service stopping).
+                    scheduleAppGcLocked(app);
+                }
+                app.setRawAdj = app.curRawAdj;
+            }
+            if (adj != app.setAdj) {
+                if (Process.setOomAdj(app.pid, adj)) {
+                    if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Log.v(
+                        TAG, "Set app " + app.processName +
+                        " oom adj to " + adj);
+                    app.setAdj = adj;
+                } else {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    private final HistoryRecord resumedAppLocked() {
+        HistoryRecord resumedActivity = mResumedActivity;
+        if (resumedActivity == null || resumedActivity.app == null) {
+            resumedActivity = mPausingActivity;
+            if (resumedActivity == null || resumedActivity.app == null) {
+                resumedActivity = topRunningActivityLocked(null);
+            }
+        }
+        return resumedActivity;
+    }
+
+    private final boolean updateOomAdjLocked(ProcessRecord app) {
+        final HistoryRecord TOP_ACT = resumedAppLocked();
+        final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
+        int curAdj = app.curAdj;
+        final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
+            && app.curAdj <= HIDDEN_APP_MAX_ADJ;
+
+        mAdjSeq++;
+
+        final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
+        if (res) {
+            final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
+                && app.curAdj <= HIDDEN_APP_MAX_ADJ;
+            if (nowHidden != wasHidden) {
+                // Changed to/from hidden state, so apps after it in the LRU
+                // list may also be changed.
+                updateOomAdjLocked();
+            }
+        }
+        return res;
+    }
+
+    private final boolean updateOomAdjLocked() {
+        boolean didOomAdj = true;
+        final HistoryRecord TOP_ACT = resumedAppLocked();
+        final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
+
+        if (false) {
+            RuntimeException e = new RuntimeException();
+            e.fillInStackTrace();
+            Log.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
+        }
+
+        mAdjSeq++;
+
+        // First try updating the OOM adjustment for each of the
+        // application processes based on their current state.
+        int i = mLRUProcesses.size();
+        int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
+        while (i > 0) {
+            i--;
+            ProcessRecord app = mLRUProcesses.get(i);
+            if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
+                if (curHiddenAdj < HIDDEN_APP_MAX_ADJ
+                    && app.curAdj == curHiddenAdj) {
+                    curHiddenAdj++;
+                }
+            } else {
+                didOomAdj = false;
+            }
+        }
+
+        // todo: for now pretend like OOM ADJ didn't work, because things
+        // aren't behaving as expected on Linux -- it's not killing processes.
+        return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
+    }
+
+    private final void trimApplications() {
+        synchronized (this) {
+            int i;
+
+            // First remove any unused application processes whose package
+            // has been removed.
+            for (i=mRemovedProcesses.size()-1; i>=0; i--) {
+                final ProcessRecord app = mRemovedProcesses.get(i);
+                if (app.activities.size() == 0
+                        && app.curReceiver == null && app.services.size() == 0) {
+                    Log.i(
+                        TAG, "Exiting empty application process "
+                        + app.processName + " ("
+                        + (app.thread != null ? app.thread.asBinder() : null)
+                        + ")\n");
+                    if (app.pid > 0 && app.pid != MY_PID) {
+                        Process.killProcess(app.pid);
+                    } else {
+                        try {
+                            app.thread.scheduleExit();
+                        } catch (Exception e) {
+                            // Ignore exceptions.
+                        }
+                    }
+                    cleanUpApplicationRecordLocked(app, false, -1);
+                    mRemovedProcesses.remove(i);
+                    
+                    if (app.persistent) {
+                        if (app.persistent) {
+                            addAppLocked(app.info);
+                        }
+                    }
+                }
+            }
+
+            // Now try updating the OOM adjustment for each of the
+            // application processes based on their current state.
+            // If the setOomAdj() API is not supported, then go with our
+            // back-up plan...
+            if (!updateOomAdjLocked()) {
+
+                // Count how many processes are running services.
+                int numServiceProcs = 0;
+                for (i=mLRUProcesses.size()-1; i>=0; i--) {
+                    final ProcessRecord app = mLRUProcesses.get(i);
+
+                    if (app.persistent || app.services.size() != 0
+                            || app.curReceiver != null
+                            || app.persistentActivities > 0) {
+                        // Don't count processes holding services against our
+                        // maximum process count.
+                        if (localLOGV) Log.v(
+                            TAG, "Not trimming app " + app + " with services: "
+                            + app.services);
+                        numServiceProcs++;
+                    }
+                }
+
+                int curMaxProcs = mProcessLimit;
+                if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
+                if (mAlwaysFinishActivities) {
+                    curMaxProcs = 1;
+                }
+                curMaxProcs += numServiceProcs;
+
+                // Quit as many processes as we can to get down to the desired
+                // process count.  First remove any processes that no longer
+                // have activites running in them.
+                for (   i=0;
+                        i<mLRUProcesses.size()
+                            && mLRUProcesses.size() > curMaxProcs;
+                        i++) {
+                    final ProcessRecord app = mLRUProcesses.get(i);
+                    // Quit an application only if it is not currently
+                    // running any activities.
+                    if (!app.persistent && app.activities.size() == 0
+                            && app.curReceiver == null && app.services.size() == 0) {
+                        Log.i(
+                            TAG, "Exiting empty application process "
+                            + app.processName + " ("
+                            + (app.thread != null ? app.thread.asBinder() : null)
+                            + ")\n");
+                        if (app.pid > 0 && app.pid != MY_PID) {
+                            Process.killProcess(app.pid);
+                        } else {
+                            try {
+                                app.thread.scheduleExit();
+                            } catch (Exception e) {
+                                // Ignore exceptions.
+                            }
+                        }
+                        // todo: For now we assume the application is not buggy
+                        // or evil, and will quit as a result of our request.
+                        // Eventually we need to drive this off of the death
+                        // notification, and kill the process if it takes too long.
+                        cleanUpApplicationRecordLocked(app, false, i);
+                        i--;
+                    }
+                }
+
+                // If we still have too many processes, now from the least
+                // recently used process we start finishing activities.
+                if (Config.LOGV) Log.v(
+                    TAG, "*** NOW HAVE " + mLRUProcesses.size() +
+                    " of " + curMaxProcs + " processes");
+                for (   i=0;
+                        i<mLRUProcesses.size()
+                            && mLRUProcesses.size() > curMaxProcs;
+                        i++) {
+                    final ProcessRecord app = mLRUProcesses.get(i);
+                    // Quit the application only if we have a state saved for
+                    // all of its activities.
+                    boolean canQuit = !app.persistent && app.curReceiver == null
+                        && app.services.size() == 0
+                        && app.persistentActivities == 0;
+                    int NUMA = app.activities.size();
+                    int j;
+                    if (Config.LOGV) Log.v(
+                        TAG, "Looking to quit " + app.processName);
+                    for (j=0; j<NUMA && canQuit; j++) {
+                        HistoryRecord r = (HistoryRecord)app.activities.get(j);
+                        if (Config.LOGV) Log.v(
+                            TAG, "  " + r.intent.getComponent().flattenToShortString()
+                            + ": frozen=" + r.haveState + ", visible=" + r.visible);
+                        canQuit = (r.haveState || !r.stateNotNeeded)
+                                && !r.visible && r.stopped;
+                    }
+                    if (canQuit) {
+                        // Finish all of the activities, and then the app itself.
+                        for (j=0; j<NUMA; j++) {
+                            HistoryRecord r = (HistoryRecord)app.activities.get(j);
+                            if (!r.finishing) {
+                                destroyActivityLocked(r, false);
+                            }
+                            r.resultTo = null;
+                        }
+                        Log.i(TAG, "Exiting application process "
+                              + app.processName + " ("
+                              + (app.thread != null ? app.thread.asBinder() : null)
+                              + ")\n");
+                        if (app.pid > 0 && app.pid != MY_PID) {
+                            Process.killProcess(app.pid);
+                        } else {
+                            try {
+                                app.thread.scheduleExit();
+                            } catch (Exception e) {
+                                // Ignore exceptions.
+                            }
+                        }
+                        // todo: For now we assume the application is not buggy
+                        // or evil, and will quit as a result of our request.
+                        // Eventually we need to drive this off of the death
+                        // notification, and kill the process if it takes too long.
+                        cleanUpApplicationRecordLocked(app, false, i);
+                        i--;
+                        //dump();
+                    }
+                }
+
+            }
+
+            int curMaxActivities = MAX_ACTIVITIES;
+            if (mAlwaysFinishActivities) {
+                curMaxActivities = 1;
+            }
+
+            // Finally, if there are too many activities now running, try to
+            // finish as many as we can to get back down to the limit.
+            for (   i=0;
+                    i<mLRUActivities.size()
+                        && mLRUActivities.size() > curMaxActivities;
+                    i++) {
+                final HistoryRecord r
+                    = (HistoryRecord)mLRUActivities.get(i);
+
+                // We can finish this one if we have its icicle saved and
+                // it is not persistent.
+                if ((r.haveState || !r.stateNotNeeded) && !r.visible
+                        && r.stopped && !r.persistent && !r.finishing) {
+                    final int origSize = mLRUActivities.size();
+                    destroyActivityLocked(r, true);
+
+                    // This will remove it from the LRU list, so keep
+                    // our index at the same value.  Note that this check to
+                    // see if the size changes is just paranoia -- if
+                    // something unexpected happens, we don't want to end up
+                    // in an infinite loop.
+                    if (origSize > mLRUActivities.size()) {
+                        i--;
+                    }
+                }
+            }
+        }
+    }
+
+    /** This method sends the specified signal to each of the persistent apps */
+    public void signalPersistentProcesses(int sig) throws RemoteException {
+        if (sig != Process.SIGNAL_USR1) {
+            throw new SecurityException("Only SIGNAL_USR1 is allowed");
+        }
+
+        synchronized (this) {
+            if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
+                    != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Requires permission "
+                        + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
+            }
+
+            for (int i = mLRUProcesses.size() - 1 ; i >= 0 ; i--) {
+                ProcessRecord r = mLRUProcesses.get(i);
+                if (r.thread != null && r.persistent) {
+                    Process.sendSignal(r.pid, sig);
+                }
+            }
+        }
+    }
+
+    /** In this method we try to acquire our lock to make sure that we have not deadlocked */
+    public void monitor() {
+        synchronized (this) { }
+    }
+}
diff --git a/services/java/com/android/server/am/ActivityResult.java b/services/java/com/android/server/am/ActivityResult.java
new file mode 100644
index 0000000..3cc2725
--- /dev/null
+++ b/services/java/com/android/server/am/ActivityResult.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.ResultInfo;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * Pending result information to send back to an activity.
+ */
+class ActivityResult extends ResultInfo {
+    final HistoryRecord mFrom;
+    
+    public ActivityResult(HistoryRecord from, String resultWho,
+            int requestCode, int resultCode, Intent data) {
+        super(resultWho, requestCode, resultCode, data);
+        mFrom = from;
+    }
+}
diff --git a/services/java/com/android/server/am/AppBindRecord.java b/services/java/com/android/server/am/AppBindRecord.java
new file mode 100644
index 0000000..ce6f6dc
--- /dev/null
+++ b/services/java/com/android/server/am/AppBindRecord.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ * An association between a service and one of its client applications.
+ */
+class AppBindRecord {
+    final ServiceRecord service;    // The running service.
+    final IntentBindRecord intent;  // The intent we are bound to.
+    final ProcessRecord client; // Who has started/bound the service.
+
+    final HashSet<ConnectionRecord> connections = new HashSet<ConnectionRecord>();
+                                    // All ConnectionRecord for this client.
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + this);
+        pw.println(prefix + "service=" + service);
+        pw.println(prefix + "client=" + client);
+        if (connections.size() > 0) {
+            pw.println(prefix + "Per-process Connections:");
+            Iterator<ConnectionRecord> it = connections.iterator();
+            while (it.hasNext()) {
+                ConnectionRecord c = it.next();
+                pw.println(prefix + "  " + c);
+            }
+        }
+    }
+
+    AppBindRecord(ServiceRecord _service, IntentBindRecord _intent,
+            ProcessRecord _client) {
+        service = _service;
+        intent = _intent;
+        client = _client;
+    }
+
+    public String toString() {
+        return "AppBindRecord{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + service.shortName + ":" + client.processName + "}";
+    }
+}
diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java
new file mode 100644
index 0000000..3fcfad0
--- /dev/null
+++ b/services/java/com/android/server/am/AppErrorDialog.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Handler;
+import android.os.Message;
+
+class AppErrorDialog extends BaseErrorDialog {
+    private final AppErrorResult mResult;
+    private final ProcessRecord mProc;
+
+    // Event 'what' codes
+    static final int FORCE_QUIT = 0;
+    static final int DEBUG = 1;
+
+    // 5-minute timeout, then we automatically dismiss the crash dialog
+    static final long DISMISS_TIMEOUT = 1000 * 60 * 5;
+    
+    public AppErrorDialog(Context context, AppErrorResult result,
+            ProcessRecord app, int flags,
+            String shortMsg, String longMsg) {
+        super(context);
+        
+        Resources res = context.getResources();
+        
+        mProc = app;
+        mResult = result;
+        CharSequence name;
+        if ((app.pkgList.size() == 1) &&
+                (name=context.getPackageManager().getApplicationLabel(app.info)) != null) {
+            setMessage(res.getString(
+                    com.android.internal.R.string.aerr_application,
+                    name.toString(), app.info.processName));
+        } else {
+            name = app.processName;
+            setMessage(res.getString(
+                    com.android.internal.R.string.aerr_process,
+                    name.toString()));
+        }
+
+        setCancelable(false);
+
+        setButton(res.getText(com.android.internal.R.string.force_close),
+                    mHandler.obtainMessage(FORCE_QUIT));
+        if ((flags&1) != 0) {
+            setButton(res.getText(com.android.internal.R.string.debug),
+                    mHandler.obtainMessage(DEBUG));
+        }
+        setTitle(res.getText(com.android.internal.R.string.aerr_title));
+        getWindow().addFlags(FLAG_SYSTEM_ERROR);
+        getWindow().setTitle("Application Error: " + app.info.processName);
+
+        // After the timeout, pretend the user clicked the quit button
+        mHandler.sendMessageDelayed(
+                mHandler.obtainMessage(FORCE_QUIT),
+                DISMISS_TIMEOUT);
+    }
+    
+    public void onStop() {
+    }
+
+    private final Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            synchronized (mProc) {
+                if (mProc != null && mProc.crashDialog == AppErrorDialog.this) {
+                    mProc.crashDialog = null;
+                }
+            }
+            mResult.set(msg.what);
+
+            // If this is a timeout we won't be automatically closed, so go
+            // ahead and explicitly dismiss ourselves just in case.
+            dismiss();
+        }
+    };
+}
diff --git a/services/java/com/android/server/am/AppErrorResult.java b/services/java/com/android/server/am/AppErrorResult.java
new file mode 100644
index 0000000..ebfcfe2
--- /dev/null
+++ b/services/java/com/android/server/am/AppErrorResult.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+
+class AppErrorResult {
+    public void set(int res) {
+        synchronized (this) {
+            mHasResult = true;
+            mResult = res;
+            notifyAll();
+        }
+    }
+
+    public int get() {
+        synchronized (this) {
+            while (!mHasResult) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+        return mResult;
+    }
+
+    boolean mHasResult = false;
+    int mResult;
+}
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java
new file mode 100644
index 0000000..7390ed0
--- /dev/null
+++ b/services/java/com/android/server/am/AppNotRespondingDialog.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Process;
+import android.util.Log;
+
+class AppNotRespondingDialog extends BaseErrorDialog {
+    private final ActivityManagerService mService;
+    private final ProcessRecord mProc;
+    
+    public AppNotRespondingDialog(ActivityManagerService service, Context context,
+            ProcessRecord app, HistoryRecord activity) {
+        super(context);
+        
+        mService = service;
+        mProc = app;
+        Resources res = context.getResources();
+        
+        setCancelable(false);
+
+        int resid;
+        CharSequence name1 = activity != null
+                ? activity.info.loadLabel(context.getPackageManager())
+                : null;
+        CharSequence name2 = null;
+        if ((app.pkgList.size() == 1) &&
+                (name2=context.getPackageManager().getApplicationLabel(app.info)) != null) {
+            if (name1 != null) {
+                resid = com.android.internal.R.string.anr_activity_application;
+            } else {
+                name1 = name2;
+                name2 = app.processName;
+                resid = com.android.internal.R.string.anr_application_process;
+            }
+        } else {
+            if (name1 != null) {
+                name2 = app.processName;
+                resid = com.android.internal.R.string.anr_activity_process;
+            } else {
+                name1 = app.processName;
+                resid = com.android.internal.R.string.anr_process;
+            }
+        }
+
+        setMessage(name2 != null
+                ? res.getString(resid, name1.toString(), name2.toString())
+                : res.getString(resid, name1.toString()));
+
+        setButton(res.getText(com.android.internal.R.string.force_close),
+                mHandler.obtainMessage(1));
+        setButton2(res.getText(com.android.internal.R.string.wait),
+                mHandler.obtainMessage(2));
+        setTitle(res.getText(com.android.internal.R.string.anr_title));
+        getWindow().addFlags(FLAG_SYSTEM_ERROR);
+        getWindow().setTitle("Application Not Responding: " + app.info.processName);
+    }
+
+    public void onStop() {
+    }
+
+    private final Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case 1:
+                    // Kill the application.
+                    mService.killAppAtUsersRequest(mProc,
+                            AppNotRespondingDialog.this, true);
+                    break;
+                case 2:
+                    // Continue waiting for the application.
+                    synchronized (mService) {
+                        ProcessRecord app = mProc;
+                        app.notResponding = false;
+                        app.notRespondingReport = null;
+                        if (app.anrDialog == AppNotRespondingDialog.this) {
+                            app.anrDialog = null;
+                        }
+                    }
+                    break;
+            }
+        }
+    };
+}
diff --git a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
new file mode 100644
index 0000000..0992d4d
--- /dev/null
+++ b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+
+class AppWaitingForDebuggerDialog extends BaseErrorDialog {
+    final ActivityManagerService mService;
+    final ProcessRecord mProc;
+    private CharSequence mAppName;
+    
+    public AppWaitingForDebuggerDialog(ActivityManagerService service,
+            Context context, ProcessRecord app) {
+        super(context);
+        mService = service;
+        mProc = app;
+        mAppName = context.getPackageManager().getApplicationLabel(app.info);
+
+        setCancelable(false);
+
+        StringBuilder text = new StringBuilder();
+        if (mAppName != null && mAppName.length() > 0) {
+            text.append("Application ");
+            text.append(mAppName);
+            text.append(" (process ");
+            text.append(app.processName);
+            text.append(")");
+        } else {
+            text.append("Process ");
+            text.append(app.processName);
+        }
+
+        text.append(" is waiting for the debugger to attach.");
+
+        setMessage(text.toString());
+        setButton("Force Close", mHandler.obtainMessage(1, app));
+        setTitle("Waiting For Debugger");
+        getWindow().setTitle("Waiting For Debugger: " + app.info.processName);
+    }
+    
+    public void onStop() {
+    }
+
+    private final Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case 1:
+                    // Kill the application.
+                    mService.killAppAtUsersRequest(mProc,
+                            AppWaitingForDebuggerDialog.this, true);
+                    break;
+            }
+        }
+    };
+}
diff --git a/services/java/com/android/server/am/BaseErrorDialog.java b/services/java/com/android/server/am/BaseErrorDialog.java
new file mode 100644
index 0000000..bed2768
--- /dev/null
+++ b/services/java/com/android/server/am/BaseErrorDialog.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import com.android.internal.R;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+import android.widget.Button;
+
+class BaseErrorDialog extends AlertDialog {
+    public BaseErrorDialog(Context context) {
+        super(context, com.android.internal.R.style.Theme_Dialog_AppError);
+
+        getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
+        getWindow().setTitle("Error Dialog");
+        setIcon(R.drawable.ic_dialog_alert);
+    }
+
+    public void onStart() {
+        super.onStart();
+        setEnabled(false);
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(0), 1000);
+    }
+
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (mConsuming) {
+            //Log.i(TAG, "Consuming: " + event);
+            return true;
+        }
+        //Log.i(TAG, "Dispatching: " + event);
+        return super.dispatchKeyEvent(event);
+    }
+
+    private void setEnabled(boolean enabled) {
+        Button b = (Button)findViewById(R.id.button1);
+        if (b != null) {
+            b.setEnabled(enabled);
+        }
+        b = (Button)findViewById(R.id.button2);
+        if (b != null) {
+            b.setEnabled(enabled);
+        }
+    }
+
+    private Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            if (msg.what == 0) {
+                mConsuming = false;
+                setEnabled(true);
+            }
+        }
+    };
+
+    private boolean mConsuming = true;
+}
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
new file mode 100644
index 0000000..27d0401
--- /dev/null
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2006-2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.os.BatteryStatsImpl;
+
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Process;
+import android.os.ServiceManager;
+import android.util.PrintWriterPrinter;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * All information we are collecting about things that can happen that impact
+ * battery life.
+ */
+public final class BatteryStatsService extends IBatteryStats.Stub {
+    static IBatteryStats sService;
+    
+    final BatteryStatsImpl mStats;
+    Context mContext;
+    
+    BatteryStatsService(String filename) {
+        mStats = new BatteryStatsImpl(filename);
+    }
+    
+    public void publish(Context context) {
+        mContext = context;
+        ServiceManager.addService("batteryinfo", asBinder());
+    }
+    
+    public static IBatteryStats getService() {
+        if (sService != null) {
+            return sService;
+        }
+        IBinder b = ServiceManager.getService("batteryinfo");
+        sService = asInterface(b);
+        return sService;
+    }
+    
+    /**
+     * @return the current statistics object, which may be modified
+     * to reflect events that affect battery usage.  You must lock the
+     * stats object before doing anything with it.
+     */
+    public BatteryStatsImpl getActiveStatistics() {
+        return mStats;
+    }
+    
+    public byte[] getStatistics() {
+        mContext.enforceCallingPermission(
+                android.Manifest.permission.BATTERY_STATS, null);
+        //Log.i("foo", "SENDING BATTERY INFO:");
+        //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo"));
+        Parcel out = Parcel.obtain();
+        mStats.writeToParcel(out, 0);
+        byte[] data = out.marshall();
+        out.recycle();
+        return data;
+    }
+    
+    public void noteStartWakelock(int uid, String name, int type) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.getUidStatsLocked(uid).noteStartWakeLocked(name, type);
+        }
+    }
+
+    public void noteStopWakelock(int uid, String name, int type) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.getUidStatsLocked(uid).noteStopWakeLocked(name, type);
+        }
+    }
+
+    public void noteStartSensor(int uid, int sensor) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.getUidStatsLocked(uid).noteStartSensor(sensor);
+        }
+    }
+    
+    public void noteStopSensor(int uid, int sensor) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.getUidStatsLocked(uid).noteStopSensor(sensor);
+        }
+    }
+    
+    public void noteStartGps(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteStartGps(uid);
+        }
+    }
+    
+    public void noteStopGps(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteStopGps(uid);
+        }
+    }
+        
+    public void noteScreenOn() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteScreenOnLocked();
+        }
+    }
+    
+    public void noteScreenOff() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteScreenOffLocked();
+        }
+    }
+
+    public void notePhoneOn() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.notePhoneOnLocked();
+        }
+    }
+    
+    public void notePhoneOff() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.notePhoneOffLocked();
+        }
+    }
+
+    public boolean isOnBattery() {
+        return mStats.isOnBattery();
+    }
+    
+    public void setOnBattery(boolean onBattery) {
+        enforceCallingPermission();
+        mStats.setOnBattery(onBattery);
+    }
+    
+    public long getAwakeTimeBattery() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.BATTERY_STATS, null);
+        return mStats.getAwakeTimeBattery();
+    }
+
+    public long getAwakeTimePlugged() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.BATTERY_STATS, null);
+        return mStats.getAwakeTimePlugged();
+    }
+
+    public void enforceCallingPermission() {
+        if (Binder.getCallingPid() == Process.myPid()) {
+            return;
+        }
+        mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
+                Binder.getCallingPid(), Binder.getCallingUid(), null);
+    }
+    
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        synchronized (mStats) {
+            boolean isCheckin = false;
+            if (args != null) {
+                for (String arg : args) {
+                    if ("-c".equals(arg)) {
+                        isCheckin = true;
+                        break;
+                    }
+                }
+            }
+            if (isCheckin) mStats.dumpCheckinLocked(pw, args);
+            else mStats.dumpLocked(new PrintWriterPrinter(pw));
+        }
+    }
+}
diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java
new file mode 100644
index 0000000..cd7f720
--- /dev/null
+++ b/services/java/com/android/server/am/BroadcastFilter.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.content.IntentFilter;
+import android.util.PrintWriterPrinter;
+
+import java.io.PrintWriter;
+
+class BroadcastFilter extends IntentFilter {
+    // Back-pointer to the list this filter is in.
+    final ReceiverList receiverList;
+    final String requiredPermission;
+
+    BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
+            String _requiredPermission) {
+        super(_filter);
+        receiverList = _receiverList;
+        requiredPermission = _requiredPermission;
+    }
+    
+    public void dumpLocal(PrintWriter pw, String prefix) {
+        super.dump(new PrintWriterPrinter(pw), prefix);
+    }
+    
+    public void dump(PrintWriter pw, String prefix) {
+        dumpLocal(pw, prefix);
+        pw.println(prefix + "requiredPermission=" + requiredPermission);
+        receiverList.dumpLocal(pw, prefix);
+    }
+    
+    public String toString() {
+        return "BroadcastFilter{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + receiverList + "}";
+    }
+}
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
new file mode 100644
index 0000000..4057ae8
--- /dev/null
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.IIntentReceiver;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ResolveInfo;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.SystemClock;
+import android.util.PrintWriterPrinter;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * An active intent broadcast.
+ */
+class BroadcastRecord extends Binder {
+    final Intent intent;    // the original intent that generated us
+    final ProcessRecord callerApp; // process that sent this
+    final String callerPackage; // who sent this
+    final int callingPid;   // the pid of who sent this
+    final int callingUid;   // the uid of who sent this
+    String requiredPermission; // a permission the caller has required
+    final List receivers;   // contains BroadcastFilter and ResolveInfo
+    final IIntentReceiver resultTo; // who receives final result if non-null
+    long dispatchTime;      // when dispatch started on this set of receivers
+    long startTime;         // when current receiver started for timeouts.
+    int resultCode;         // current result code value.
+    String resultData;      // current result data value.
+    Bundle resultExtras;    // current result extra data values.
+    boolean resultAbort;    // current result abortBroadcast value.
+    boolean ordered;        // serialize the send to receivers?
+    int nextReceiver;       // next receiver to be executed.
+    IBinder receiver;       // who is currently running, null if none.
+    int state;
+    int anrCount;           // has this broadcast record hit any ANRs?
+
+    static final int IDLE = 0;
+    static final int APP_RECEIVE = 1;
+    static final int CALL_IN_RECEIVE = 2;
+    static final int CALL_DONE_RECEIVE = 3;
+
+    // The following are set when we are calling a receiver (one that
+    // was found in our list of registered receivers).
+    BroadcastFilter curFilter;
+
+    // The following are set only when we are launching a receiver (one
+    // that was found by querying the package manager).
+    ProcessRecord curApp;       // hosting application of current receiver.
+    ComponentName curComponent; // the receiver class that is currently running.
+    ActivityInfo curReceiver;   // info about the receiver that is currently running.
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + this);
+        pw.println(prefix + intent);
+        pw.println(prefix + "proc=" + callerApp);
+        pw.println(prefix + "caller=" + callerPackage
+                + " callingPid=" + callingPid
+                + " callingUid=" + callingUid);
+        pw.println(prefix + "requiredPermission=" + requiredPermission);
+        pw.println(prefix + "dispatchTime=" + dispatchTime + " ("
+                + (SystemClock.uptimeMillis()-dispatchTime) + " since now)");
+        pw.println(prefix + "startTime=" + startTime + " ("
+                + (SystemClock.uptimeMillis()-startTime) + " since now)");
+        pw.println(prefix + "anrCount=" + anrCount);
+        pw.println(prefix + "resultTo=" + resultTo
+              + " resultCode=" + resultCode + " resultData=" + resultData);
+        pw.println(prefix + "resultExtras=" + resultExtras);
+        pw.println(prefix + "resultAbort=" + resultAbort
+                + " ordered=" + ordered);
+        pw.println(prefix + "nextReceiver=" + nextReceiver
+              + " receiver=" + receiver);
+        pw.println(prefix + "curFilter=" + curFilter);
+        pw.println(prefix + "curReceiver="
+                + ((curReceiver != null) ? curReceiver : "(null)"));
+        pw.println(prefix + "curApp=" + curApp);
+        if (curApp != null) {
+            pw.println(prefix + "curComponent="
+                    + (curComponent != null ? curComponent.toShortString() : "--"));
+            pw.println(prefix + "curSourceDir=" + curReceiver.applicationInfo.sourceDir);
+        }
+        String stateStr = " (?)";
+        switch (state) {
+            case IDLE:              stateStr=" (IDLE)"; break;
+            case APP_RECEIVE:       stateStr=" (APP_RECEIVE)"; break;
+            case CALL_IN_RECEIVE:   stateStr=" (CALL_IN_RECEIVE)"; break;
+            case CALL_DONE_RECEIVE: stateStr=" (CALL_DONE_RECEIVE)"; break;
+        }
+        pw.println(prefix + "state=" + state + stateStr);
+        final int N = receivers != null ? receivers.size() : 0;
+        String p2 = prefix + "  ";
+        PrintWriterPrinter printer = new PrintWriterPrinter(pw);
+        for (int i=0; i<N; i++) {
+            Object o = receivers.get(i);
+            pw.println(prefix + "Receiver #" + i + ": " + o);
+            if (o instanceof BroadcastFilter)
+                ((BroadcastFilter)o).dump(pw, p2);
+            else if (o instanceof ResolveInfo)
+                ((ResolveInfo)o).dump(printer, p2);
+        }
+    }
+
+    BroadcastRecord(Intent _intent, ProcessRecord _callerApp, String _callerPackage,
+            int _callingPid, int _callingUid, String _requiredPermission,
+            List _receivers, IIntentReceiver _resultTo, int _resultCode,
+            String _resultData, Bundle _resultExtras, boolean _serialized) {
+        intent = _intent;
+        callerApp = _callerApp;
+        callerPackage = _callerPackage;
+        callingPid = _callingPid;
+        callingUid = _callingUid;
+        requiredPermission = _requiredPermission;
+        receivers = _receivers;
+        resultTo = _resultTo;
+        resultCode = _resultCode;
+        resultData = _resultData;
+        resultExtras = _resultExtras;
+        ordered = _serialized;
+        nextReceiver = 0;
+        state = IDLE;
+    }
+
+    public String toString() {
+        return "BroadcastRecord{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + intent.getAction() + "}";
+    }
+}
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
new file mode 100644
index 0000000..41a783f
--- /dev/null
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.IServiceConnection;
+
+import java.io.PrintWriter;
+
+/**
+ * Description of a single binding to a service.
+ */
+class ConnectionRecord {
+    final AppBindRecord binding;    // The application/service binding.
+    final HistoryRecord activity;   // If non-null, the owning activity.
+    final IServiceConnection conn;  // The client connection.
+    final int flags;                // Binding options.
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + this);
+        pw.println(prefix + "binding=" + binding);
+        pw.println(prefix + "activity=" + activity);
+        pw.println(prefix + "conn=" + conn.asBinder()
+                + " flags=0x" + Integer.toHexString(flags));
+    }
+    
+    ConnectionRecord(AppBindRecord _binding, HistoryRecord _activity,
+               IServiceConnection _conn, int _flags) {
+        binding = _binding;
+        activity = _activity;
+        conn = _conn;
+        flags = _flags;
+    }
+
+    public String toString() {
+        return "ConnectionRecord{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + binding.service.shortName
+            + ":@" + Integer.toHexString(System.identityHashCode(conn.asBinder())) + "}";
+    }
+}
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
new file mode 100644
index 0000000..9f37c14
--- /dev/null
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.IActivityManager.ContentProviderHolder;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ProviderInfo;
+import android.os.Process;
+
+import java.io.PrintWriter;
+import java.util.HashSet;
+
+class ContentProviderRecord extends ContentProviderHolder {
+    // All attached clients
+    final HashSet<ProcessRecord> clients = new HashSet<ProcessRecord>();
+    final int uid;
+    final ApplicationInfo appInfo;
+    int externals;     // number of non-framework processes supported by this provider
+    ProcessRecord app; // if non-null, hosting application
+    ProcessRecord launchingApp; // if non-null, waiting for this app to be launched.
+
+    public ContentProviderRecord(ProviderInfo _info, ApplicationInfo ai) {
+        super(_info);
+        uid = ai.uid;
+        appInfo = ai;
+        noReleaseNeeded = uid == 0 || uid == Process.SYSTEM_UID;
+    }
+
+    public ContentProviderRecord(ContentProviderRecord cpr) {
+        super(cpr.info);
+        uid = cpr.uid;
+        appInfo = cpr.appInfo;
+        noReleaseNeeded = cpr.noReleaseNeeded;
+    }
+
+    public boolean canRunHere(ProcessRecord app) {
+        return (info.multiprocess || info.processName.equals(app.processName))
+                && (uid == Process.SYSTEM_UID || uid == app.info.uid);
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + this);
+        pw.println(prefix + "package=" + info.applicationInfo.packageName
+              + " process=" + info.processName);
+        pw.println(prefix + "app=" + app);
+        pw.println(prefix + "launchingApp=" + launchingApp);
+        pw.println(prefix + "provider=" + provider);
+        pw.println(prefix + "name=" + info.authority);
+        pw.println(prefix + "isSyncable=" + info.isSyncable);
+        pw.println(prefix + "multiprocess=" + info.multiprocess
+              + " initOrder=" + info.initOrder
+              + " uid=" + uid);
+        pw.println(prefix + "clients=" + clients);
+        pw.println(prefix + "externals=" + externals);
+    }
+
+    public String toString() {
+        return "ContentProviderRecord{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + info.name + "}";
+    }
+}
diff --git a/services/java/com/android/server/am/DeviceMonitor.java b/services/java/com/android/server/am/DeviceMonitor.java
new file mode 100644
index 0000000..ce07430
--- /dev/null
+++ b/services/java/com/android/server/am/DeviceMonitor.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.util.Log;
+
+import java.io.*;
+import java.util.Arrays;
+
+/**
+ * Monitors device resources periodically for some period of time. Useful for
+ * tracking down performance problems.
+ */
+class DeviceMonitor {
+
+    private static final String LOG_TAG = DeviceMonitor.class.getName();
+
+    /** Number of samples to take. */
+    private static final int SAMPLE_COUNT = 10;
+
+    /** Time to wait in ms between samples. */
+    private static final int INTERVAL = 1000;
+
+    /** Time to wait in ms between samples. */
+    private static final int MAX_FILES = 30;
+
+    private final byte[] buffer = new byte[1024];
+
+    /** Is the monitor currently running? */
+    private boolean running = false;
+
+    private DeviceMonitor() {
+        new Thread() {
+            public void run() {
+                monitor();
+            }
+        }.start();
+    }
+
+    /**
+     * Loops continuously. Pauses until someone tells us to start monitoring.
+     */
+    @SuppressWarnings("InfiniteLoopStatement")
+    private void monitor() {
+        while (true) {
+            waitForStart();
+
+            purge();
+
+            for (int i = 0; i < SAMPLE_COUNT; i++) {
+                try {
+                    dump();
+                } catch (IOException e) {
+                    Log.w(LOG_TAG, "Dump failed.", e);
+                }
+                pause();
+            }
+
+            stop();
+        }
+    }
+
+    private static final File PROC = new File("/proc");
+    private static final File BASE = new File("/data/anr/");
+    static {
+        if (!BASE.isDirectory() && !BASE.mkdirs()) {
+            throw new AssertionError("Couldn't create " + BASE + ".");
+        }
+    }
+
+    private static final File[] PATHS = {
+        new File(PROC, "zoneinfo"),
+        new File(PROC, "interrupts"),
+        new File(PROC, "meminfo"),
+        new File(PROC, "slabinfo"),
+    };
+
+
+    /**
+     * Deletes old files.
+     */
+    private void purge() {
+        File[] files = BASE.listFiles();
+        int count = files.length - MAX_FILES;
+        if (count > 0) {
+            Arrays.sort(files);
+            for (int i = 0; i < count; i++) {
+                if (!files[i].delete()) {
+                    Log.w(LOG_TAG, "Couldn't delete " + files[i] + ".");
+                }
+            }
+        }
+    }
+
+    /**
+     * Dumps the current device stats to a new file.
+     */
+    private void dump() throws IOException {
+        OutputStream out = new FileOutputStream(
+                new File(BASE, String.valueOf(System.currentTimeMillis())));
+        try {
+            // Copy /proc/*/stat
+            for (File processDirectory : PROC.listFiles()) {
+                if (isProcessDirectory(processDirectory)) {
+                    dump(new File(processDirectory, "stat"), out);
+                }
+            }
+
+            // Copy other files.
+            for (File file : PATHS) {
+                dump(file, out);
+            }
+        } finally {
+            closeQuietly(out);
+        }
+    }
+
+    /**
+     * Returns true if the given file represents a process directory.
+     */
+    private static boolean isProcessDirectory(File file) {
+        try {
+            Integer.parseInt(file.getName());
+            return file.isDirectory();
+        } catch (NumberFormatException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Copies from a file to an output stream.
+     */
+    private void dump(File from, OutputStream out) throws IOException {
+        writeHeader(from, out);
+        
+        FileInputStream in = null;
+        try {
+            in = new FileInputStream(from);
+            int count;
+            while ((count = in.read(buffer)) != -1) {
+                out.write(buffer, 0, count);
+            }
+        } finally {
+            closeQuietly(in);
+        }
+    }
+
+    /**
+     * Writes a header for the given file.
+     */
+    private static void writeHeader(File file, OutputStream out)
+            throws IOException {
+        String header = "*** " + file.toString() + "\n";
+        out.write(header.getBytes());
+    }
+
+    /**
+     * Closes the given resource. Logs exceptions.
+     * @param closeable
+     */
+    private static void closeQuietly(Closeable closeable) {
+        try {
+            if (closeable != null) {
+                closeable.close();
+            }
+        } catch (IOException e) {
+            Log.w(LOG_TAG, e);
+        }
+    }
+
+    /**
+     * Pauses momentarily before we start the next dump.
+     */
+    private void pause() {
+        try {
+            Thread.sleep(INTERVAL);
+        } catch (InterruptedException e) { /* ignore */ }
+    }
+
+    /**
+     * Stops dumping.
+     */
+    private synchronized void stop() {
+        running = false;        
+    }
+
+    /**
+     * Waits until someone starts us.
+     */
+    private synchronized void waitForStart() {
+        while (!running) {
+            try {
+                wait();
+            } catch (InterruptedException e) { /* ignore */ }
+        }
+    }
+
+    /**
+     * Instructs the monitoring to start if it hasn't already.
+     */
+    private synchronized void startMonitoring() {
+        if (!running) {
+            running = true;
+            notifyAll();
+        }
+    }
+
+    private static DeviceMonitor instance = new DeviceMonitor();
+
+    /**
+     * Starts monitoring if it hasn't started already.
+     */
+    static void start() {
+        instance.startMonitoring();
+    }
+}
diff --git a/services/java/com/android/server/am/FactoryErrorDialog.java b/services/java/com/android/server/am/FactoryErrorDialog.java
new file mode 100644
index 0000000..2e25474
--- /dev/null
+++ b/services/java/com/android/server/am/FactoryErrorDialog.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+
+class FactoryErrorDialog extends BaseErrorDialog {
+    public FactoryErrorDialog(Context context, CharSequence msg) {
+        super(context);
+        setCancelable(false);
+        setTitle(context.getText(com.android.internal.R.string.factorytest_failed));
+        setMessage(msg);
+        setButton(context.getText(com.android.internal.R.string.factorytest_reboot),
+                mHandler.obtainMessage(0));
+        getWindow().setTitle("Factory Error");
+    }
+    
+    public void onStop() {
+    }
+
+    private final Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            throw new RuntimeException("Rebooting from failed factory test");
+        }
+    };
+}
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
new file mode 100644
index 0000000..b407208
--- /dev/null
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import com.android.server.AttributeCache;
+import com.android.server.am.ActivityManagerService.ActivityState;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.Process;
+import android.os.SystemClock;
+import android.util.EventLog;
+import android.util.Log;
+import android.view.IApplicationToken;
+
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashSet;
+
+/**
+ * An entry in the history stack, representing an activity.
+ */
+class HistoryRecord extends IApplicationToken.Stub {
+    final ActivityManagerService service; // owner
+    final ActivityInfo info; // all about me
+    final int launchedFromUid; // always the uid who started the activity.
+    final Intent intent;    // the original intent that generated us
+    final ComponentName realActivity;  // the intent component, or target of an alias.
+    final String shortComponentName; // the short component name of the intent
+    final String resolvedType; // as per original caller;
+    final String packageName; // the package implementing intent's component
+    final String processName; // process where this component wants to run
+    final String taskAffinity; // as per ActivityInfo.taskAffinity
+    final boolean stateNotNeeded; // As per ActivityInfo.flags
+    final boolean fullscreen;     // covers the full screen?
+    final String baseDir;   // where activity source (resources etc) located
+    final String resDir;   // where public activity source (public resources etc) located
+    final String dataDir;   // where activity data should go
+    CharSequence nonLocalizedLabel;  // the label information from the package mgr.
+    int labelRes;           // the label information from the package mgr.
+    int icon;               // resource identifier of activity's icon.
+    int theme;              // resource identifier of activity's theme.
+    TaskRecord task;        // the task this is in.
+    long startTime;         // when we starting launching this activity
+    Configuration configuration; // configuration activity was last running in
+    HistoryRecord resultTo; // who started this entry, so will get our reply
+    final String resultWho; // additional identifier for use by resultTo.
+    final int requestCode;  // code given by requester (resultTo)
+    ArrayList results;      // pending ActivityResult objs we have received
+    HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
+    ArrayList newIntents;   // any pending new intents for single-top mode
+    HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
+    HashSet<UriPermission> readUriPermissions; // special access to reading uris.
+    HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
+    ProcessRecord app;  // if non-null, hosting application
+    Bitmap thumbnail;       // icon representation of paused screen
+    CharSequence description; // textual description of paused screen
+    ActivityManagerService.ActivityState state;    // current state we are in
+    Bundle  icicle;         // last saved activity state
+    boolean frontOfTask;    // is this the root activity of its task?
+    boolean launchFailed;   // set if a launched failed, to abort on 2nd try
+    boolean haveState;      // have we gotten the last activity state?
+    boolean stopped;        // is activity pause finished?
+    boolean finishing;      // activity in pending finish list?
+    boolean configDestroy;  // need to destroy due to config change?
+    int configChangeFlags;  // which config values have changed
+    boolean keysPaused;     // has key dispatching been paused for it?
+    boolean inHistory;      // are we in the history stack?
+    boolean persistent;     // requested to be persistent?
+    int launchMode;         // the launch mode activity attribute.
+    boolean visible;        // does this activity's window need to be shown?
+    boolean waitingVisible; // true if waiting for a new act to become vis
+    boolean nowVisible;     // is this activity's window visible?
+    boolean thumbnailNeeded;// has someone requested a thumbnail?
+    boolean idle;           // has the activity gone idle?
+    boolean hasBeenLaunched;// has this activity ever been launched?
+    boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + this);
+        pw.println(prefix + "packageName=" + packageName
+              + " processName=" + processName);
+        pw.println(prefix + "app=" + app);
+        pw.println(prefix + "launchedFromUid=" + launchedFromUid);
+        pw.println(prefix + intent);
+        pw.println(prefix + "frontOfTask=" + frontOfTask + " task=" + task);
+        pw.println(prefix + "taskAffinity=" + taskAffinity);
+        pw.println(prefix + "realActivity=" + realActivity);
+        pw.println(prefix + "dir=" + baseDir + " res=" + resDir + " data=" + dataDir);
+        pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
+                + " icon=0x" + Integer.toHexString(icon)
+                + " theme=0x" + Integer.toHexString(theme));
+        pw.println(prefix + "configuration=" + configuration);
+        pw.println(prefix + "resultTo=" + resultTo
+              + " resultWho=" + resultWho + " resultCode=" + requestCode);
+        pw.println(prefix + "results=" + results);
+        pw.println(prefix + "pendingResults=" + pendingResults);
+        pw.println(prefix + "readUriPermissions=" + readUriPermissions);
+        pw.println(prefix + "writeUriPermissions=" + writeUriPermissions);
+        pw.println(prefix + "launchFailed=" + launchFailed
+              + " haveState=" + haveState + " icicle=" + icicle);
+        pw.println(prefix + "state=" + state
+              + " stopped=" + stopped + " finishing=" + finishing);
+        pw.println(prefix + "keysPaused=" + keysPaused
+              + " inHistory=" + inHistory + " persistent=" + persistent
+              + " launchMode=" + launchMode);
+        pw.println(prefix + "fullscreen=" + fullscreen
+              + " visible=" + visible
+              + " frozenBeforeDestroy=" + frozenBeforeDestroy
+              + " thumbnailNeeded=" + thumbnailNeeded + " idle=" + idle);
+        pw.println(prefix + "waitingVisible=" + waitingVisible
+              + " nowVisible=" + nowVisible);
+        pw.println(prefix + "configDestroy=" + configDestroy
+                + " configChangeFlags=" + Integer.toHexString(configChangeFlags));
+        pw.println(prefix + "connections=" + connections);
+    }
+
+    HistoryRecord(ActivityManagerService _service, ProcessRecord _caller,
+            int _launchedFromUid, Intent _intent, String _resolvedType,
+            ActivityInfo aInfo, Configuration _configuration,
+            HistoryRecord _resultTo, String _resultWho, int _reqCode) {
+        service = _service;
+        info = aInfo;
+        launchedFromUid = _launchedFromUid;
+        intent = _intent;
+        shortComponentName = _intent.getComponent().flattenToShortString();
+        resolvedType = _resolvedType;
+        configuration = _configuration;
+        resultTo = _resultTo;
+        resultWho = _resultWho;
+        requestCode = _reqCode;
+        state = ActivityManagerService.ActivityState.INITIALIZING;
+        frontOfTask = false;
+        launchFailed = false;
+        haveState = false;
+        stopped = false;
+        finishing = false;
+        configDestroy = false;
+        keysPaused = false;
+        inHistory = false;
+        persistent = false;
+        visible = true;
+        waitingVisible = false;
+        nowVisible = false;
+        thumbnailNeeded = false;
+        idle = false;
+        hasBeenLaunched = false;
+
+        if (aInfo != null) {
+            if (aInfo.targetActivity == null
+                    || aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE
+                    || aInfo.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
+                realActivity = _intent.getComponent();
+            } else {
+                realActivity = new ComponentName(aInfo.packageName,
+                        aInfo.targetActivity);
+            }
+            taskAffinity = aInfo.taskAffinity;
+            stateNotNeeded = (aInfo.flags&
+                    ActivityInfo.FLAG_STATE_NOT_NEEDED) != 0;
+            baseDir = aInfo.applicationInfo.sourceDir;
+            resDir = aInfo.applicationInfo.publicSourceDir;
+            dataDir = aInfo.applicationInfo.dataDir;
+            nonLocalizedLabel = aInfo.nonLocalizedLabel;
+            labelRes = aInfo.labelRes;
+            if (nonLocalizedLabel == null && labelRes == 0) {
+                ApplicationInfo app = aInfo.applicationInfo;
+                nonLocalizedLabel = app.nonLocalizedLabel;
+                labelRes = app.labelRes;
+            }
+            icon = aInfo.getIconResource();
+            theme = aInfo.getThemeResource();
+            if ((aInfo.flags&ActivityInfo.FLAG_MULTIPROCESS) != 0
+                    && _caller != null
+                    && (aInfo.applicationInfo.uid == Process.SYSTEM_UID
+                            || aInfo.applicationInfo.uid == _caller.info.uid)) {
+                processName = _caller.processName;
+            } else {
+                processName = aInfo.processName;
+            }
+
+            if (intent != null && (aInfo.flags & ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS) != 0) {
+                intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            }
+            
+            packageName = aInfo.applicationInfo.packageName;
+            launchMode = aInfo.launchMode;
+            
+            AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
+                    theme != 0 ? theme : android.R.style.Theme,
+                    com.android.internal.R.styleable.Window);
+            fullscreen = ent != null && !ent.array.getBoolean(
+                    com.android.internal.R.styleable.Window_windowIsFloating, false)
+                    && !ent.array.getBoolean(
+                    com.android.internal.R.styleable.Window_windowIsTranslucent, false);
+            
+        } else {
+            realActivity = null;
+            taskAffinity = null;
+            stateNotNeeded = false;
+            baseDir = null;
+            resDir = null;
+            dataDir = null;
+            processName = null;
+            packageName = null;
+            fullscreen = true;
+        }
+    }
+
+    void addResultLocked(HistoryRecord from, String resultWho,
+            int requestCode, int resultCode,
+            Intent resultData) {
+        ActivityResult r = new ActivityResult(from, resultWho,
+        		requestCode, resultCode, resultData);
+        if (results == null) {
+            results = new ArrayList();
+        }
+        results.add(r);
+    }
+
+    void removeResultsLocked(HistoryRecord from, String resultWho,
+            int requestCode) {
+        if (results != null) {
+            for (int i=results.size()-1; i>=0; i--) {
+                ActivityResult r = (ActivityResult)results.get(i);
+                if (r.mFrom != from) continue;
+                if (r.mResultWho == null) {
+                    if (resultWho != null) continue;
+                } else {
+                    if (!r.mResultWho.equals(resultWho)) continue;
+                }
+                if (r.mRequestCode != requestCode) continue;
+
+                results.remove(i);
+            }
+        }
+    }
+
+    void addNewIntentLocked(Intent intent) {
+        if (newIntents == null) {
+            newIntents = new ArrayList();
+        }
+        newIntents.add(intent);
+    }
+
+    void pauseKeyDispatchingLocked() {
+        if (!keysPaused) {
+            keysPaused = true;
+            service.mWindowManager.pauseKeyDispatching(this);
+        }
+    }
+
+    void resumeKeyDispatchingLocked() {
+        if (keysPaused) {
+            keysPaused = false;
+            service.mWindowManager.resumeKeyDispatching(this);
+        }
+    }
+
+    // IApplicationToken
+
+    public boolean mayFreezeScreenLocked(ProcessRecord app) {
+        // Only freeze the screen if this activity is currently attached to
+        // an application, and that application is not blocked or unresponding.
+        // In any other case, we can't count on getting the screen unfrozen,
+        // so it is best to leave as-is.
+        return app == null || (!app.crashing && !app.notResponding);
+    }
+    
+    public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
+        if (mayFreezeScreenLocked(app)) {
+            service.mWindowManager.startAppFreezingScreen(this, configChanges);
+        }
+    }
+    
+    public void stopFreezingScreenLocked(boolean force) {
+        if (force || frozenBeforeDestroy) {
+            frozenBeforeDestroy = false;
+            service.mWindowManager.stopAppFreezingScreen(this, force);
+        }
+    }
+    
+    public void windowsVisible() {
+        synchronized(service) {
+            if (ActivityManagerService.SHOW_ACTIVITY_START_TIME
+                    && startTime != 0) {
+                long time = SystemClock.uptimeMillis() - startTime;
+                EventLog.writeEvent(ActivityManagerService.LOG_ACTIVITY_LAUNCH_TIME,
+                        System.identityHashCode(this), shortComponentName, time);
+                Log.i(ActivityManagerService.TAG, "Displayed activity "
+                        + shortComponentName
+                        + ": " + time + " ms");
+                startTime = 0;
+            }
+            if (ActivityManagerService.DEBUG_SWITCH) Log.v(
+                    ActivityManagerService.TAG, "windowsVisible(): " + this);
+            if (!nowVisible) {
+                nowVisible = true;
+                if (!idle) {
+                    // Instead of doing the full stop routine here, let's just
+                    // hide any activities we now can, and let them stop when
+                    // the normal idle happens.
+                    service.processStoppingActivitiesLocked(false);
+                } else {
+                    // If this activity was already idle, then we now need to
+                    // make sure we perform the full stop of any activities
+                    // that are waiting to do so.  This is because we won't
+                    // do that while they are still waiting for this one to
+                    // become visible.
+                    final int N = service.mWaitingVisibleActivities.size();
+                    if (N > 0) {
+                        for (int i=0; i<N; i++) {
+                            HistoryRecord r = (HistoryRecord)
+                                service.mWaitingVisibleActivities.get(i);
+                            r.waitingVisible = false;
+                            if (ActivityManagerService.DEBUG_SWITCH) Log.v(
+                                    ActivityManagerService.TAG,
+                                    "Was waiting for visible: " + r);
+                        }
+                        service.mWaitingVisibleActivities.clear();
+                        Message msg = Message.obtain();
+                        msg.what = ActivityManagerService.IDLE_NOW_MSG;
+                        service.mHandler.sendMessage(msg);
+                    }
+                }
+                service.scheduleAppGcsLocked();
+            }
+        }
+    }
+
+    public void windowsGone() {
+        if (ActivityManagerService.DEBUG_SWITCH) Log.v(
+                ActivityManagerService.TAG, "windowsGone(): " + this);
+        nowVisible = false;
+    }
+    
+    private HistoryRecord getWaitingHistoryRecordLocked() {
+        // First find the real culprit...  if we are waiting
+        // for another app to start, then we have paused dispatching
+        // for this activity.
+        HistoryRecord r = this;
+        if (r.waitingVisible) {
+            // Hmmm, who might we be waiting for?
+            r = service.mResumedActivity;
+            if (r == null) {
+                r = service.mPausingActivity;
+            }
+            // Both of those null?  Fall back to 'this' again
+            if (r == null) {
+                r = this;
+            }
+        }
+        
+        return r;
+    }
+
+    public boolean keyDispatchingTimedOut() {
+        synchronized(service) {
+            HistoryRecord r = getWaitingHistoryRecordLocked();
+            if (r != null && r.app != null) {
+                if (r.app.debugging) {
+                    return false;
+                }
+                
+                if (r.app.instrumentationClass == null) { 
+                    service.appNotRespondingLocked(r.app, r, "keyDispatchingTimedOut");
+                } else {
+                    Bundle info = new Bundle();
+                    info.putString("shortMsg", "keyDispatchingTimedOut");
+                    info.putString("longMsg", "Timed out while dispatching key event");
+                    service.finishInstrumentationLocked(
+                            r.app, Activity.RESULT_CANCELED, info);
+                }
+            }
+            return true;
+        }
+    }
+    
+    /** Returns the key dispatching timeout for this application token. */
+    public long getKeyDispatchingTimeout() {
+        synchronized(service) {
+            HistoryRecord r = getWaitingHistoryRecordLocked();
+            if (r == null || r.app == null
+                    || r.app.instrumentationClass == null) {
+                return ActivityManagerService.KEY_DISPATCHING_TIMEOUT;
+            }
+            
+            return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT;
+        }
+    }
+
+    /**
+     * This method will return true if the activity is either visible, is becoming visible, is
+     * currently pausing, or is resumed.
+     */
+    public boolean isInterestingToUserLocked() {
+        return visible || nowVisible || state == ActivityState.PAUSING || 
+                state == ActivityState.RESUMED;
+     }
+    
+    
+    public String toString() {
+        return "HistoryRecord{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + intent.getComponent().toShortString() + "}";
+    }
+}
diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java
new file mode 100644
index 0000000..24c3943
--- /dev/null
+++ b/services/java/com/android/server/am/IntentBindRecord.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.content.Intent;
+import android.os.IBinder;
+
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * A particular Intent that has been bound to a Service.
+ */
+class IntentBindRecord {
+    /** The running service. */
+    final ServiceRecord service;
+    /** The intent that is bound.*/
+    final Intent.FilterComparison intent; // 
+    /** All apps that have bound to this Intent. */
+    final HashMap<ProcessRecord, AppBindRecord> apps
+            = new HashMap<ProcessRecord, AppBindRecord>();
+    /** Binder published from service. */
+    IBinder binder;
+    /** Set when we have initiated a request for this binder. */
+    boolean requested;
+    /** Set when we have received the requested binder. */
+    boolean received;
+    /** Set when we still need to tell the service all clients are unbound. */
+    boolean hasBound;
+    /** Set when the service's onUnbind() has asked to be told about new clients. */
+    boolean doRebind;
+    
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + this);
+        pw.println(prefix + "service=" + service);
+        pw.println(prefix + "intent=" + intent.getIntent());
+        pw.println(prefix + "binder=" + binder
+                + " requested=" + requested
+                + " received=" + received
+                + " hasBound=" + hasBound
+                + " doRebind=" + doRebind);
+        if (apps.size() > 0) {
+            pw.println(prefix + "Application Bindings:");
+            Iterator<AppBindRecord> it = apps.values().iterator();
+            while (it.hasNext()) {
+                AppBindRecord a = it.next();
+                pw.println(prefix + "Client " + a.client);
+                a.dump(pw, prefix + "  ");
+            }
+        }
+    }
+
+    IntentBindRecord(ServiceRecord _service, Intent.FilterComparison _intent) {
+        service = _service;
+        intent = _intent;
+    }
+
+    public String toString() {
+        return "IntentBindRecord{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + service.name.toShortString()
+            + ":" + intent + "}";
+    }
+}
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
new file mode 100644
index 0000000..b18aaf7
--- /dev/null
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.IActivityManager;
+import android.app.IIntentSender;
+import android.app.IIntentReceiver;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+
+class PendingIntentRecord extends IIntentSender.Stub {
+    final ActivityManagerService owner;
+    final Key key;
+    final int uid;
+    final WeakReference<PendingIntentRecord> ref;
+    boolean sent = false;
+    boolean canceled = false;
+
+    final static class Key {
+        final int type;
+        final String packageName;
+        final HistoryRecord activity;
+        final String who;
+        final int requestCode;
+        final Intent requestIntent;
+        final String requestResolvedType;
+        final int flags;
+        final int hashCode;
+        
+        private static final int ODD_PRIME_NUMBER = 37;
+        
+        Key(int _t, String _p, HistoryRecord _a, String _w,
+                int _r, Intent _i, String _it, int _f) {
+            type = _t;
+            packageName = _p;
+            activity = _a;
+            who = _w;
+            requestCode = _r;
+            requestIntent = _i;
+            requestResolvedType = _it;
+            flags = _f;
+            
+            int hash = 23;
+            hash = (ODD_PRIME_NUMBER*hash) + _f;
+            hash = (ODD_PRIME_NUMBER*hash) + _r;
+            if (_w != null) {
+                hash = (ODD_PRIME_NUMBER*hash) + _w.hashCode();
+            }
+            if (_a != null) {
+                hash = (ODD_PRIME_NUMBER*hash) + _a.hashCode();
+            }
+            if (_i != null) {
+                hash = (ODD_PRIME_NUMBER*hash) + _i.filterHashCode();
+            }
+            if (_it != null) {
+                hash = (ODD_PRIME_NUMBER*hash) + _it.hashCode();
+            }
+            hash = (ODD_PRIME_NUMBER*hash) + _p.hashCode();
+            hash = (ODD_PRIME_NUMBER*hash) + _t;
+            hashCode = hash;
+            //Log.i(ActivityManagerService.TAG, this + " hashCode=0x"
+            //        + Integer.toHexString(hashCode));
+        }
+        
+        public boolean equals(Object otherObj) {
+            if (otherObj == null) {
+                return false;
+            }
+            try {
+                Key other = (Key)otherObj;
+                if (type != other.type) {
+                    return false;
+                }
+                if (!packageName.equals(other.packageName)) {
+                    return false;
+                }
+                if (activity != other.activity) {
+                    return false;
+                }
+                if (who != other.who) {
+                    if (who != null) {
+                        if (!who.equals(other.who)) {
+                            return false;
+                        }
+                    } else if (other.who != null) {
+                        return false;
+                    }
+                }
+                if (requestCode != other.requestCode) {
+                    return false;
+                }
+                if (requestIntent != other.requestIntent) {
+                    if (requestIntent != null) {
+                        if (!requestIntent.filterEquals(other.requestIntent)) {
+                            return false;
+                        }
+                    } else if (other.requestIntent != null) {
+                        return false;
+                    }
+                }
+                if (requestResolvedType != other.requestResolvedType) {
+                    if (requestResolvedType != null) {
+                        if (!requestResolvedType.equals(other.requestResolvedType)) {
+                            return false;
+                        }
+                    } else if (other.requestResolvedType != null) {
+                        return false;
+                    }
+                }
+                if (flags != other.flags) {
+                    return false;
+                }
+                return true;
+            } catch (ClassCastException e) {
+            }
+            return false;
+        }
+
+        public int hashCode() {
+            return hashCode;
+        }
+        
+        public String toString() {
+            return "Key{" + typeName() + " pkg=" + packageName
+                + " intent=" + requestIntent + " flags=0x"
+                + Integer.toHexString(flags) + "}";
+        }
+        
+        String typeName() {
+            switch (type) {
+                case IActivityManager.INTENT_SENDER_ACTIVITY:
+                    return "startActivity";
+                case IActivityManager.INTENT_SENDER_BROADCAST:
+                    return "broadcastIntent";
+                case IActivityManager.INTENT_SENDER_SERVICE:
+                    return "startService";
+                case IActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
+                    return "activityResult";
+            }
+            return Integer.toString(type);
+        }
+    }
+    
+    PendingIntentRecord(ActivityManagerService _owner, Key _k, int _u) {
+        owner = _owner;
+        key = _k;
+        uid = _u;
+        ref = new WeakReference<PendingIntentRecord>(this);
+    }
+
+    public int send(int code, Intent intent, String resolvedType,
+            IIntentReceiver finishedReceiver) {
+        synchronized(owner) {
+            if (!canceled) {
+                sent = true;
+                if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
+                    owner.cancelIntentSenderLocked(this, true);
+                    canceled = true;
+                }
+                Intent finalIntent = key.requestIntent != null
+                        ? new Intent(key.requestIntent) : new Intent();
+                if (intent != null) {
+                    int changes = finalIntent.fillIn(intent, key.flags);
+                    if ((changes&Intent.FILL_IN_DATA) == 0) {
+                        resolvedType = key.requestResolvedType;
+                    }
+                } else {
+                    resolvedType = key.requestResolvedType;
+                }
+                
+                final long origId = Binder.clearCallingIdentity();
+                
+                boolean sendFinish = finishedReceiver != null;
+                switch (key.type) {
+                    case IActivityManager.INTENT_SENDER_ACTIVITY:
+                        try {
+                            owner.startActivityInPackage(uid,
+                                    finalIntent, resolvedType,
+                                    null, null, 0, false);
+                        } catch (RuntimeException e) {
+                            Log.w(ActivityManagerService.TAG,
+                                    "Unable to send startActivity intent", e);
+                        }
+                        break;
+                    case IActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
+                        owner.sendActivityResultLocked(-1, key.activity,
+                                key.who, key.requestCode, code, finalIntent);
+                        break;
+                    case IActivityManager.INTENT_SENDER_BROADCAST:
+                        try {
+                            // If a completion callback has been requested, require
+                            // that the broadcast be delivered synchronously
+                            owner.broadcastIntentInPackage(key.packageName, uid,
+                                    finalIntent, resolvedType,
+                                    finishedReceiver, code, null, null, null,
+                                    (finishedReceiver != null), false);
+                            sendFinish = false;
+                        } catch (RuntimeException e) {
+                            Log.w(ActivityManagerService.TAG,
+                                    "Unable to send startActivity intent", e);
+                        }
+                        break;
+                    case IActivityManager.INTENT_SENDER_SERVICE:
+                        try {
+                            owner.startServiceInPackage(uid,
+                                    finalIntent, resolvedType);
+                        } catch (RuntimeException e) {
+                            Log.w(ActivityManagerService.TAG,
+                                    "Unable to send startService intent", e);
+                        }
+                        break;
+                }
+                
+                if (sendFinish) {
+                    try {
+                        finishedReceiver.performReceive(new Intent(finalIntent), 0,
+                                null, null, false);
+                    } catch (RemoteException e) {
+                    }
+                }
+                
+                Binder.restoreCallingIdentity(origId);
+                
+                return 0;
+            }
+        }
+        return -1;
+    }
+    
+    protected void finalize() throws Throwable {
+        if (!canceled) {
+            synchronized(owner) {
+                WeakReference<PendingIntentRecord> current =
+                        owner.mIntentSenderRecords.get(key);
+                if (current == ref) {
+                    owner.mIntentSenderRecords.remove(key);
+                }
+            }
+        }
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + "packageName=" + key.packageName
+                + " type=" + key.typeName()
+                + " flags=0x" + Integer.toHexString(key.flags));
+        pw.println(prefix + "activity=" + key.activity + " who=" + key.who);
+        pw.println(prefix + "requestCode=" + key.requestCode
+                + " requestResolvedType=" + key.requestResolvedType);
+        pw.println(prefix + "requestIntent=" + key.requestIntent);
+        pw.println(prefix + "sent=" + sent + " canceled=" + canceled);
+    }
+
+    public String toString() {
+        return "IntentSenderRecord{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + key.packageName + " " + key.typeName() + "}";
+    }
+}
diff --git a/services/java/com/android/server/am/PendingThumbnailsRecord.java b/services/java/com/android/server/am/PendingThumbnailsRecord.java
new file mode 100644
index 0000000..ed478c9
--- /dev/null
+++ b/services/java/com/android/server/am/PendingThumbnailsRecord.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.IThumbnailReceiver;
+
+import java.util.HashSet;
+
+/**
+ * This class keeps track of calls to getTasks() that are still
+ * waiting for thumbnail images.
+ */
+class PendingThumbnailsRecord
+{
+    final IThumbnailReceiver receiver;   // who is waiting.
+    HashSet pendingRecords; // HistoryRecord objects we still wait for.
+    boolean finished;       // Is pendingRecords empty?
+
+    PendingThumbnailsRecord(IThumbnailReceiver _receiver)
+    {
+        receiver = _receiver;
+        pendingRecords = new HashSet();
+        finished = false;
+    }
+}
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
new file mode 100644
index 0000000..a1320df
--- /dev/null
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import com.android.internal.os.BatteryStatsImpl;
+import com.android.server.Watchdog;
+
+import android.app.ActivityManager;
+import android.app.Dialog;
+import android.app.IApplicationThread;
+import android.app.IInstrumentationWatcher;
+import android.content.ComponentName;
+import android.content.pm.ApplicationInfo;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+
+/**
+ * Full information about a particular process that
+ * is currently running.
+ */
+class ProcessRecord implements Watchdog.PssRequestor {
+    final BatteryStatsImpl.Uid.Proc batteryStats; // where to collect runtime statistics
+    final ApplicationInfo info; // all about the first app in the process
+    final String processName;   // name of the process
+    // List of packages running in the process
+    final HashSet<String> pkgList = new HashSet();
+    IApplicationThread thread;  // the actual proc...  may be null only if
+                                // 'persistent' is true (in which case we
+                                // are in the process of launching the app)
+    int pid;                    // The process of this application; 0 if none
+    boolean starting;           // True if the process is being started
+    int maxAdj;                 // Maximum OOM adjustment for this process
+    int hiddenAdj;              // If hidden, this is the adjustment to use
+    int curRawAdj;              // Current OOM unlimited adjustment for this process
+    int setRawAdj;              // Last set OOM unlimited adjustment for this process
+    int curAdj;                 // Current OOM adjustment for this process
+    int setAdj;                 // Last set OOM adjustment for this process
+    boolean isForeground;       // Is this app running the foreground UI?
+    boolean setIsForeground;    // Running foreground UI when last set?
+    boolean foregroundServices; // Running any services that are foreground?
+    boolean bad;                // True if disabled in the bad process list
+    IBinder forcingToForeground;// Token that is forcing this process to be foreground
+    int adjSeq;                 // Sequence id for identifying repeated trav
+    ComponentName instrumentationClass;// class installed to instrument app
+    String instrumentationProfileFile; // where to save profiling
+    IInstrumentationWatcher instrumentationWatcher; // who is waiting
+    Bundle instrumentationArguments;// as given to us
+    ComponentName instrumentationResultClass;// copy of instrumentationClass
+    BroadcastRecord curReceiver;// receiver currently running in the app
+    long lastRequestedGc;       // When we last asked the app to do a gc
+    int lastPss;                // Last pss size reported by app.
+    
+    // contains HistoryRecord objects
+    final ArrayList activities = new ArrayList();
+    // all ServiceRecord running in this process
+    final HashSet services = new HashSet();
+    // services that are currently executing code (need to remain foreground).
+    final HashSet<ServiceRecord> executingServices
+             = new HashSet<ServiceRecord>();
+    // All ConnectionRecord this process holds
+    final HashSet<ConnectionRecord> connections
+            = new HashSet<ConnectionRecord>();  
+    // all IIntentReceivers that are registered from this process.
+    final HashSet<ReceiverList> receivers = new HashSet<ReceiverList>();
+    // class (String) -> ContentProviderRecord
+    final HashMap pubProviders = new HashMap(); 
+    // All ContentProviderRecord process is using
+    final HashSet conProviders = new HashSet(); 
+    
+    boolean persistent;         // always keep this application running?
+    boolean crashing;           // are we in the process of crashing?
+    Dialog crashDialog;         // dialog being displayed due to crash.
+    boolean notResponding;      // does the app have a not responding dialog?
+    Dialog anrDialog;           // dialog being displayed due to app not resp.
+    boolean removed;            // has app package been removed from device?
+    boolean debugging;          // was app launched for debugging?
+    int persistentActivities;   // number of activities that are persistent
+    boolean waitedForDebugger;  // has process show wait for debugger dialog?
+    Dialog waitDialog;          // current wait for debugger dialog
+    
+    // These reports are generated & stored when an app gets into an error condition.
+    // They will be "null" when all is OK.
+    ActivityManager.ProcessErrorStateInfo crashingReport;
+    ActivityManager.ProcessErrorStateInfo notRespondingReport;
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + this);
+        pw.println(prefix + "class=" + info.className);
+        pw.println(prefix+"manageSpaceActivityName="+info.manageSpaceActivityName);
+        pw.println(prefix + "dir=" + info.sourceDir + " publicDir=" + info.publicSourceDir 
+              + " data=" + info.dataDir);
+        pw.println(prefix + "packageList=" + pkgList);
+        pw.println(prefix + "instrumentationClass=" + instrumentationClass
+              + " instrumentationProfileFile=" + instrumentationProfileFile);
+        pw.println(prefix + "instrumentationArguments=" + instrumentationArguments);
+        pw.println(prefix + "thread=" + thread + " curReceiver=" + curReceiver);
+        pw.println(prefix + "pid=" + pid + " starting=" + starting
+                + " lastPss=" + lastPss);
+        pw.println(prefix + "maxAdj=" + maxAdj + " hiddenAdj=" + hiddenAdj
+                + " curRawAdj=" + curRawAdj + " setRawAdj=" + setRawAdj
+                + " curAdj=" + curAdj + " setAdj=" + setAdj);
+        pw.println(prefix + "isForeground=" + isForeground
+                + " setIsForeground=" + setIsForeground
+                + " foregroundServices=" + foregroundServices
+                + " forcingToForeground=" + forcingToForeground);
+        pw.println(prefix + "persistent=" + persistent + " removed=" + removed
+                + " persistentActivities=" + persistentActivities);
+        pw.println(prefix + "debugging=" + debugging
+                + " crashing=" + crashing + " " + crashDialog
+                + " notResponding=" + notResponding + " " + anrDialog
+                + " bad=" + bad);
+        pw.println(prefix + "activities=" + activities);
+        pw.println(prefix + "services=" + services);
+        pw.println(prefix + "executingServices=" + executingServices);
+        pw.println(prefix + "connections=" + connections);
+        pw.println(prefix + "pubProviders=" + pubProviders);
+        pw.println(prefix + "conProviders=" + conProviders);
+        pw.println(prefix + "receivers=" + receivers);
+    }
+    
+    ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
+            ApplicationInfo _info, String _processName) {
+        batteryStats = _batteryStats;
+        info = _info;
+        processName = _processName;
+        pkgList.add(_info.packageName);
+        thread = _thread;
+        maxAdj = ActivityManagerService.EMPTY_APP_ADJ;
+        hiddenAdj = ActivityManagerService.HIDDEN_APP_MIN_ADJ;
+        curRawAdj = setRawAdj = -100;
+        curAdj = setAdj = -100;
+        persistent = false;
+        removed = false;
+        persistentActivities = 0;
+    }
+
+    /**
+     * This method returns true if any of the activities within the process record are interesting
+     * to the user. See HistoryRecord.isInterestingToUserLocked()
+     */
+    public boolean isInterestingToUserLocked() {
+        final int size = activities.size();
+        for (int i = 0 ; i < size ; i++) {
+            HistoryRecord r = (HistoryRecord) activities.get(i);
+            if (r.isInterestingToUserLocked()) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    public void stopFreezingAllLocked() {
+        int i = activities.size();
+        while (i > 0) {
+            i--;
+            ((HistoryRecord)activities.get(i)).stopFreezingScreenLocked(true);
+        }
+    }
+    
+    public void requestPss() {
+        IApplicationThread localThread = thread;
+        if (localThread != null) {
+            try {
+                localThread.requestPss();
+            } catch (RemoteException e) {
+            }
+        }
+    }
+    
+    public String toString() {
+        return "ProcessRecord{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + pid + ":" + processName + "/" + info.uid + "}";
+    }
+    
+    /*
+     *  Return true if package has been added false if not
+     */
+    public boolean addPackage(String pkg) {
+        if (!pkgList.contains(pkg)) {
+            pkgList.add(pkg);
+            return true;
+        }
+        return false;
+    }
+    
+    /*
+     *  Delete all packages from list except the package indicated in info
+     */
+    public void resetPackageList() {
+        pkgList.clear();
+        pkgList.add(info.packageName);
+    }
+    
+    public String[] getPackageList() {
+        int size = pkgList.size();
+        if (size == 0) {
+            return null;
+        }
+        String list[] = new String[size];
+        pkgList.toArray(list);
+        return list;
+    }
+}
diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/java/com/android/server/am/ReceiverList.java
new file mode 100644
index 0000000..6ac527b
--- /dev/null
+++ b/services/java/com/android/server/am/ReceiverList.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.IIntentReceiver;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * A receiver object that has registered for one or more broadcasts.
+ * The ArrayList holds BroadcastFilter objects.
+ */
+class ReceiverList extends ArrayList<BroadcastFilter>
+        implements IBinder.DeathRecipient {
+    final ActivityManagerService owner;
+    public final IIntentReceiver receiver;
+    public final ProcessRecord app;
+    public final int pid;
+    public final int uid;
+    BroadcastRecord curBroadcast = null;
+    boolean linkedToDeath = false;
+
+    ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
+            int _pid, int _uid, IIntentReceiver _receiver) {
+        owner = _owner;
+        receiver = _receiver;
+        app = _app;
+        pid = _pid;
+        uid = _uid;
+    }
+
+    // Want object identity, not the array identity we are inheriting.
+    public boolean equals(Object o) {
+        return this == o;
+    }
+    public int hashCode() {
+        return System.identityHashCode(this);
+    }
+    
+    public void binderDied() {
+        linkedToDeath = false;
+        owner.unregisterReceiver(receiver);
+    }
+    
+    void dumpLocal(PrintWriter pw, String prefix) {
+        pw.println(prefix + "receiver=IBinder "
+                + Integer.toHexString(System.identityHashCode(receiver.asBinder())));
+        pw.println(prefix + "app=" + app + " pid=" + pid + " uid=" + uid);
+        pw.println(prefix + "curBroadcast=" + curBroadcast
+                + " linkedToDeath=" + linkedToDeath);
+    }
+    
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + this);
+        dumpLocal(pw, prefix);
+        String p2 = prefix + "  ";
+        final int N = size();
+        for (int i=0; i<N; i++) {
+            BroadcastFilter bf = get(i);
+            pw.println(prefix + "Filter #" + i + ": " + bf);
+            bf.dump(pw, p2);
+        }
+    }
+    
+    public String toString() {
+        return "ReceiverList{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + pid + " " + (app != null ? app.processName : "(unknown name)")
+            + "/" + uid + " client "
+            + Integer.toHexString(System.identityHashCode(receiver.asBinder()))
+            + "}";
+    }
+}
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
new file mode 100644
index 0000000..4b90600
--- /dev/null
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import com.android.internal.os.BatteryStatsImpl;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.SystemClock;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A running application service.
+ */
+class ServiceRecord extends Binder {
+    final BatteryStatsImpl.Uid.Pkg.Serv stats;
+    final ComponentName name; // service component.
+    final String shortName; // name.flattenToShortString().
+    final Intent.FilterComparison intent;
+                            // original intent used to find service.
+    final ServiceInfo serviceInfo;
+                            // all information about the service.
+    final ApplicationInfo appInfo;
+                            // information about service's app.
+    final String packageName; // the package implementing intent's component
+    final String processName; // process where this component wants to run
+    final String permission;// permission needed to access service
+    final String baseDir;   // where activity source (resources etc) located
+    final String resDir;   // where public activity source (public resources etc) located
+    final String dataDir;   // where activity data should go
+    final boolean exported; // from ServiceInfo.exported
+    final Runnable restarter; // used to schedule retries of starting the service
+    final long createTime;  // when this service was created
+    final HashMap<Intent.FilterComparison, IntentBindRecord> bindings
+            = new HashMap<Intent.FilterComparison, IntentBindRecord>();
+                            // All active bindings to the service.
+    final HashMap<IBinder, ConnectionRecord> connections
+            = new HashMap<IBinder, ConnectionRecord>();
+                            // IBinder -> ConnectionRecord of all bound clients
+    final List<Intent> startArgs = new ArrayList<Intent>();
+                            // start() arguments that haven't yet been delivered.
+
+    ProcessRecord app;  // where this service is running or null.
+    boolean isForeground;   // asked to run as a foreground service?
+    long lastActivity;      // last time there was some activity on the service.
+    boolean startRequested; // someone explicitly called start?
+    int lastStartId;        // identifier of most recent start request.
+    int executeNesting;     // number of outstanding operations keeping foreground.
+    long executingStart;    // start time of last execute request.
+    int crashCount;         // number of times proc has crashed with service running
+    int totalRestartCount;  // number of times we have had to restart.
+    int restartCount;       // number of restarts performed in a row.
+    long restartDelay;      // delay until next restart attempt.
+    long restartTime;       // time of last restart.
+    long nextRestartTime;   // time when restartDelay will expire.
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + this);
+        pw.println(prefix + "intent=" + intent.getIntent());
+        pw.println(prefix + "packageName=" + packageName);
+        pw.println(prefix + "processName=" + processName);
+        pw.println(prefix + "permission=" + permission);
+        pw.println(prefix + "baseDir=" + baseDir+ " resDir=" + resDir + " dataDir=" + dataDir);
+        pw.println(prefix + "app=" + app);
+        pw.println(prefix + "isForeground=" + isForeground
+                + " lastActivity=" + lastActivity);
+        pw.println(prefix + "startRequested=" + startRequested
+              + " startId=" + lastStartId
+              + " executeNesting=" + executeNesting
+              + " executingStart=" + executingStart
+              + " crashCount=" + crashCount);
+        pw.println(prefix + "totalRestartCount=" + totalRestartCount
+                + " restartCount=" + restartCount
+                + " restartDelay=" + restartDelay
+                + " restartTime=" + restartTime
+                + " nextRestartTime=" + nextRestartTime);
+        if (bindings.size() > 0) {
+            pw.println(prefix + "Bindings:");
+            Iterator<IntentBindRecord> it = bindings.values().iterator();
+            while (it.hasNext()) {
+                IntentBindRecord b = it.next();
+                pw.println(prefix + "Binding " + b);
+                b.dump(pw, prefix + "  ");
+            }
+        }
+        if (connections.size() > 0) {
+            pw.println(prefix + "All Connections:");
+            Iterator<ConnectionRecord> it = connections.values().iterator();
+            while (it.hasNext()) {
+                ConnectionRecord c = it.next();
+                pw.println(prefix + "  " + c);
+            }
+        }
+    }
+
+    ServiceRecord(BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name,
+            Intent.FilterComparison intent, ServiceInfo sInfo, Runnable restarter) {
+        this.stats = servStats;
+        this.name = name;
+        shortName = name.flattenToShortString();
+        this.intent = intent;
+        serviceInfo = sInfo;
+        appInfo = sInfo.applicationInfo;
+        packageName = sInfo.applicationInfo.packageName;
+        processName = sInfo.processName;
+        permission = sInfo.permission;
+        baseDir = sInfo.applicationInfo.sourceDir;
+        resDir = sInfo.applicationInfo.publicSourceDir;
+        dataDir = sInfo.applicationInfo.dataDir;
+        exported = sInfo.exported;
+        this.restarter = restarter;
+        createTime = lastActivity = SystemClock.uptimeMillis();
+    }
+
+    public AppBindRecord retrieveAppBindingLocked(Intent intent,
+            ProcessRecord app) {
+        Intent.FilterComparison filter = new Intent.FilterComparison(intent);
+        IntentBindRecord i = bindings.get(filter);
+        if (i == null) {
+            i = new IntentBindRecord(this, filter);
+            bindings.put(filter, i);
+        }
+        AppBindRecord a = i.apps.get(app);
+        if (a != null) {
+            return a;
+        }
+        a = new AppBindRecord(this, i, app);
+        i.apps.put(app, a);
+        return a;
+    }
+
+    public void resetRestartCounter() {
+        restartCount = 0;
+        restartDelay = 0;
+        restartTime = 0;
+    }
+    
+    public String toString() {
+        return "ServiceRecord{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + shortName + "}";
+    }
+}
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
new file mode 100644
index 0000000..aab3736
--- /dev/null
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.os.SystemClock;
+
+import java.io.PrintWriter;
+
+class TaskRecord {
+    final int taskId;       // Unique identifier for this task.
+    final String affinity;  // The affinity name for this task, or null.
+    final boolean clearOnBackground; // As per the original activity.
+    Intent intent;          // The original intent that started the task.
+    Intent affinityIntent;  // Intent of affinity-moved activity that started this task.
+    ComponentName origActivity; // The non-alias activity component of the intent.
+    ComponentName realActivity; // The actual activity component that started the task.
+    int numActivities;      // Current number of activities in this task.
+    long lastActiveTime;    // Last time this task was active, including sleep.
+    boolean rootWasReset;   // True if the intent at the root of the task had
+                            // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
+
+    TaskRecord(int _taskId, ActivityInfo info, Intent _intent,
+            boolean _clearOnBackground) {
+        taskId = _taskId;
+        affinity = info.taskAffinity;
+        clearOnBackground = _clearOnBackground;
+        setIntent(_intent, info);
+    }
+
+    void touchActiveTime() {
+        lastActiveTime = android.os.SystemClock.elapsedRealtime();
+    }
+    
+    long getInactiveDuration() {
+        return android.os.SystemClock.elapsedRealtime() - lastActiveTime;
+    }
+    
+    void setIntent(Intent _intent, ActivityInfo info) {
+        if (info.targetActivity == null) {
+            intent = _intent;
+            realActivity = _intent != null ? _intent.getComponent() : null;
+            origActivity = null;
+        } else {
+            ComponentName targetComponent = new ComponentName(
+                    info.packageName, info.targetActivity);
+            if (_intent != null) {
+                Intent targetIntent = new Intent(_intent);
+                targetIntent.setComponent(targetComponent);
+                intent = targetIntent;
+                realActivity = targetComponent;
+                origActivity = _intent.getComponent();
+            } else {
+                intent = null;
+                realActivity = targetComponent;
+                origActivity = new ComponentName(info.packageName, info.name);
+            }
+        }
+        
+        if (intent != null &&
+                (intent.getFlags()&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
+            // Once we are set to an Intent with this flag, we count this
+            // task as having a true root activity.
+            rootWasReset = true;
+        }
+    }
+    
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + this);
+        pw.println(prefix + "clearOnBackground=" + clearOnBackground
+              + " numActivities=" + numActivities
+              + " rootWasReset=" + rootWasReset);
+        pw.println(prefix + "affinity=" + affinity);
+        pw.println(prefix + "intent=" + intent);
+        pw.println(prefix + "affinityIntent=" + affinityIntent);
+        pw.println(prefix + "origActivity=" + origActivity);
+        pw.println(prefix + "lastActiveTime=" + lastActiveTime
+                +" (inactive for " + (getInactiveDuration()/1000) + "s)");
+    }
+
+    public String toString() {
+        return "Task{" + taskId + " "
+                + (affinity != null ? affinity
+                        : (intent != null ? intent.getComponent().flattenToShortString()
+                                : affinityIntent != null ? affinityIntent.getComponent().flattenToShortString() : "??"))
+                + "}";
+    }
+}
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
new file mode 100644
index 0000000..fb7a745
--- /dev/null
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.content.Intent;
+import android.net.Uri;
+
+import java.io.PrintWriter;
+import java.util.HashSet;
+
+class UriPermission {
+    final int uid;
+    final Uri uri;
+    int modeFlags = 0;
+    int globalModeFlags = 0;
+    final HashSet<HistoryRecord> readActivities = new HashSet<HistoryRecord>();
+    final HashSet<HistoryRecord> writeActivities = new HashSet<HistoryRecord>();
+    
+    UriPermission(int _uid, Uri _uri) {
+        uid = _uid;
+        uri = _uri;
+    }
+    
+    void clearModes(int modeFlags) {
+        if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+            globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+            modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
+            if (readActivities.size() > 0) {
+                for (HistoryRecord r : readActivities) {
+                    r.readUriPermissions.remove(this);
+                    if (r.readUriPermissions.size() == 0) {
+                        r.readUriPermissions = null;
+                    }
+                }
+                readActivities.clear();
+            }
+        }
+        if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+            globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+            modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+            if (readActivities.size() > 0) {
+                for (HistoryRecord r : readActivities) {
+                    r.writeUriPermissions.remove(this);
+                    if (r.writeUriPermissions.size() == 0) {
+                        r.writeUriPermissions = null;
+                    }
+                }
+                readActivities.clear();
+            }
+        }
+    }
+    
+    public String toString() {
+        return "UriPermission{"
+                + Integer.toHexString(System.identityHashCode(this))
+                + " " + uri + "}";
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + this);
+        pw.println(prefix + "  modeFlags=0x" + Integer.toHexString(modeFlags)
+                + " uid=" + uid 
+                + " globalModeFlags=0x"
+                + Integer.toHexString(globalModeFlags));
+        pw.println(prefix + "  readActivities=" + readActivities);
+        pw.println(prefix + "  writeActivities=" + writeActivities);
+    }
+}
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
new file mode 100755
index 0000000..3922f39
--- /dev/null
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2006-2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import com.android.internal.app.IUsageStats;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import com.android.internal.os.PkgUsageStats;
+import android.os.Parcel;
+import android.os.Process;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.util.Log;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This service collects the statistics associated with usage
+ * of various components, like when a particular package is launched or
+ * paused and aggregates events like number of time a component is launched
+ * total duration of a component launch.
+ */
+public final class UsageStatsService extends IUsageStats.Stub {
+    public static final String SERVICE_NAME = "usagestats";
+    private static final boolean localLOGV = false;
+    private static final String TAG = "UsageStats";
+    static IUsageStats sService;
+    private Context mContext;
+    // structure used to maintain statistics since the last checkin.
+    final private Map<String, PkgUsageStatsExtended> mStats;
+    // Lock to update package stats. Methods suffixed by SLOCK should invoked with
+    // this lock held
+    final Object mStatsLock;
+    // Lock to write to file. Methods suffixed by FLOCK should invoked with
+    // this lock held.
+    final Object mFileLock;
+    // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks
+    private String mResumedPkg;
+    private File mFile;
+    //private File mBackupFile;
+    private long mLastWriteRealTime;
+    private int _FILE_WRITE_INTERVAL = 30*60*1000; //ms
+    private static final String _PREFIX_DELIMIT=".";
+    private String mFilePrefix;
+    private Calendar mCal;
+    private static final int  _MAX_NUM_FILES = 10;
+    private long mLastTime;
+    
+    private class PkgUsageStatsExtended {
+        int mLaunchCount;
+        long mUsageTime;
+        long mPausedTime;
+        long mResumedTime;
+        
+        PkgUsageStatsExtended() {
+            mLaunchCount = 0;
+            mUsageTime = 0;
+        }
+        void updateResume() {
+            mLaunchCount ++;
+            mResumedTime = SystemClock.elapsedRealtime();
+        }
+        void updatePause() {
+            mPausedTime =  SystemClock.elapsedRealtime();
+            mUsageTime += (mPausedTime - mResumedTime);
+        }
+        void clear() {
+            mLaunchCount = 0;
+            mUsageTime = 0;
+        }
+    }
+    
+    UsageStatsService(String fileName) {
+        mStats = new HashMap<String, PkgUsageStatsExtended>();
+        mStatsLock = new Object();
+        mFileLock = new Object();
+        mFilePrefix = fileName;
+        mCal = Calendar.getInstance();
+        // Update current stats which are binned by date
+        String uFileName = getCurrentDateStr(mFilePrefix);
+        mFile = new File(uFileName);
+        readStatsFromFile();
+        mLastWriteRealTime = SystemClock.elapsedRealtime();
+        mLastTime = new Date().getTime();
+    }
+
+    /*
+     * Utility method to convert date into string.
+     */
+    private String getCurrentDateStr(String prefix) {
+        mCal.setTime(new Date());
+        StringBuilder sb = new StringBuilder();
+        if (prefix != null) {
+            sb.append(prefix);
+            sb.append(".");
+        }
+        int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1;
+        if (mm < 10) {
+            sb.append("0");
+        }
+        sb.append(mm);
+        int dd = mCal.get(Calendar.DAY_OF_MONTH);
+        if (dd < 10) {
+            sb.append("0");
+        }
+        sb.append(dd);
+        sb.append(mCal.get(Calendar.YEAR));
+        return sb.toString();
+    }
+    
+    private Parcel getParcelForFile(File file) throws IOException {
+        FileInputStream stream = new FileInputStream(file);
+        byte[] raw = readFully(stream);
+        Parcel in = Parcel.obtain();
+        in.unmarshall(raw, 0, raw.length);
+        in.setDataPosition(0);
+        stream.close();
+        return in;
+    }
+    
+    private void readStatsFromFile() {
+        File newFile = mFile;
+        synchronized (mFileLock) {
+            try {
+                if (newFile.exists()) {
+                    readStatsFLOCK(newFile);
+                } else {
+                    // Check for file limit before creating a new file
+                    checkFileLimitFLOCK();
+                    newFile.createNewFile();
+                }
+            } catch (IOException e) {
+                Log.w(TAG,"Error : " + e + " reading data from file:" + newFile);
+            }
+        }
+    }
+    
+    private void readStatsFLOCK(File file) throws IOException {
+        Parcel in = getParcelForFile(file);
+        while (in.dataAvail() > 0) {
+            String pkgName = in.readString();
+            PkgUsageStatsExtended pus = new PkgUsageStatsExtended();
+            pus.mLaunchCount = in.readInt();
+            pus.mUsageTime = in.readLong();
+            synchronized (mStatsLock) {
+                mStats.put(pkgName, pus);
+            }
+        }
+    }
+
+    private ArrayList<String> getUsageStatsFileListFLOCK() {
+        File dir = getUsageFilesDir();
+        if (dir == null) {
+            Log.w(TAG, "Couldnt find writable directory for usage stats file");
+            return null;
+        }
+        // Check if there are too many files in the system and delete older files
+        String fList[] = dir.list();
+        if (fList == null) {
+            return null;
+        }
+        File pre = new File(mFilePrefix);
+        String filePrefix = pre.getName();
+        // file name followed by dot
+        int prefixLen = filePrefix.length()+1;
+        ArrayList<String> fileList = new ArrayList<String>();
+        for (String file : fList) {
+            int index = file.indexOf(filePrefix);
+            if (index == -1) {
+                continue;
+            }
+            if (file.endsWith(".bak")) {
+                continue;
+            }
+            fileList.add(file);
+        }
+        return fileList;
+    }
+    
+    private File getUsageFilesDir() {
+        if (mFilePrefix == null) {
+            return null;
+        }
+        File pre = new File(mFilePrefix);
+        return new File(pre.getParent());
+    }
+    
+    private void checkFileLimitFLOCK() {
+        File dir = getUsageFilesDir();
+        if (dir == null) {
+            Log.w(TAG, "Couldnt find writable directory for usage stats file");
+            return;
+        }
+        // Get all usage stats output files
+        ArrayList<String> fileList = getUsageStatsFileListFLOCK();
+        if (fileList == null) {
+            // Strange but we dont have to delete any thing
+            return;
+        }
+        int count = fileList.size();
+        if (count <= _MAX_NUM_FILES) {
+            return;
+        }
+        // Sort files
+        Collections.sort(fileList);
+        count -= _MAX_NUM_FILES;
+        // Delete older files
+        for (int i = 0; i < count; i++) {
+            String fileName = fileList.get(i);
+            File file = new File(dir, fileName);
+            Log.i(TAG, "Deleting file : "+fileName);
+            file.delete();
+        }
+    }
+    
+    private void writeStatsToFile() {
+        synchronized (mFileLock) {
+            long currTime = new Date().getTime();
+            boolean dayChanged =  ((currTime - mLastTime) >= (24*60*60*1000));
+            long currRealTime = SystemClock.elapsedRealtime();
+            if (((currRealTime-mLastWriteRealTime) < _FILE_WRITE_INTERVAL) &&
+                    (!dayChanged)) {
+                // wait till the next update
+                return;
+            }
+            // Get the most recent file
+            String todayStr = getCurrentDateStr(mFilePrefix);
+            // Copy current file to back up
+            File backupFile =  new File(mFile.getPath() + ".bak");
+            mFile.renameTo(backupFile);
+            try {
+                checkFileLimitFLOCK();
+                mFile.createNewFile();
+                // Write mStats to file
+                writeStatsFLOCK();
+                mLastWriteRealTime = currRealTime;
+                mLastTime = currTime;
+                if (dayChanged) {
+                    // clear stats
+                    synchronized (mStats) {
+                        mStats.clear();
+                    }
+                    mFile = new File(todayStr);
+                }
+                // Delete the backup file
+                if (backupFile != null) {
+                    backupFile.delete();
+                }
+            } catch (IOException e) {
+                Log.w(TAG, "Failed writing stats to file:" + mFile);
+                if (backupFile != null) {
+                    backupFile.renameTo(mFile);
+                }
+            }
+        }
+    }
+
+    private void writeStatsFLOCK() throws IOException {
+        FileOutputStream stream = new FileOutputStream(mFile);
+        Parcel out = Parcel.obtain();
+        writeStatsToParcelFLOCK(out);
+        stream.write(out.marshall());
+        out.recycle();
+        stream.flush();
+        stream.close();
+    }
+
+    private void writeStatsToParcelFLOCK(Parcel out) {
+        synchronized (mStatsLock) {
+            Set<String> keys = mStats.keySet();
+            for (String key : keys) {
+                PkgUsageStatsExtended pus = mStats.get(key);
+                out.writeString(key);
+                out.writeInt(pus.mLaunchCount);
+                out.writeLong(pus.mUsageTime);
+            }
+        }
+    }
+
+    public void publish(Context context) {
+        mContext = context;
+        ServiceManager.addService(SERVICE_NAME, asBinder());
+    }
+    
+    public static IUsageStats getService() {
+        if (sService != null) {
+            return sService;
+        }
+        IBinder b = ServiceManager.getService(SERVICE_NAME);
+        sService = asInterface(b);
+        return sService;
+    }
+    
+    public void noteResumeComponent(ComponentName componentName) {
+        enforceCallingPermission();
+        String pkgName;
+        if ((componentName == null) ||
+                ((pkgName = componentName.getPackageName()) == null)) {
+            return;
+        }
+        if ((mResumedPkg != null) && (mResumedPkg.equalsIgnoreCase(pkgName))) {
+            // Moving across activities in same package. just return
+            return;
+        } 
+        if (localLOGV) Log.i(TAG, "started component:"+pkgName);
+        synchronized (mStatsLock) {
+            PkgUsageStatsExtended pus = mStats.get(pkgName);
+            if (pus == null) {
+                pus = new PkgUsageStatsExtended();
+                mStats.put(pkgName, pus);
+            }
+            pus.updateResume();
+        }
+        mResumedPkg = pkgName;
+    }
+
+    public void notePauseComponent(ComponentName componentName) {
+        enforceCallingPermission();
+        String pkgName;
+        if ((componentName == null) ||
+                ((pkgName = componentName.getPackageName()) == null)) {
+            return;
+        }
+        if ((mResumedPkg == null) || (!pkgName.equalsIgnoreCase(mResumedPkg))) {
+            Log.w(TAG, "Something wrong here, Didn't expect "+pkgName+" to be paused");
+            return;
+        }
+        if (localLOGV) Log.i(TAG, "paused component:"+pkgName);
+        synchronized (mStatsLock) {
+            PkgUsageStatsExtended pus = mStats.get(pkgName);
+            if (pus == null) {
+                // Weird some error here
+                Log.w(TAG, "No package stats for pkg:"+pkgName);
+                return;
+            }
+            pus.updatePause();
+        }
+        // Persist data to file
+        writeStatsToFile();
+    }
+    
+    public void enforceCallingPermission() {
+        if (Binder.getCallingPid() == Process.myPid()) {
+            return;
+        }
+        mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
+                Binder.getCallingPid(), Binder.getCallingUid(), null);
+    }
+    
+    public PkgUsageStats getPkgUsageStats(ComponentName componentName) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.PACKAGE_USAGE_STATS, null);
+        String pkgName;
+        if ((componentName == null) ||
+                ((pkgName = componentName.getPackageName()) == null)) {
+            return null;
+        }
+        synchronized (mStatsLock) {
+            PkgUsageStatsExtended pus = mStats.get(pkgName);
+            if (pus == null) {
+               return null;
+            }
+            return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime);
+        }
+    }
+    
+    public PkgUsageStats[] getAllPkgUsageStats() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.PACKAGE_USAGE_STATS, null);
+        synchronized (mStatsLock) {
+            Set<String> keys = mStats.keySet();
+            int size = keys.size();
+            if (size <= 0) {
+                return null;
+            }
+            PkgUsageStats retArr[] = new PkgUsageStats[size];
+            int i = 0;
+            for (String key: keys) {
+                PkgUsageStatsExtended pus = mStats.get(key);
+                retArr[i] = new PkgUsageStats(key, pus.mLaunchCount, pus.mUsageTime);
+                i++;
+            }
+            return retArr;
+        }
+    }
+    
+    static byte[] readFully(FileInputStream stream) throws java.io.IOException {
+        int pos = 0;
+        int avail = stream.available();
+        byte[] data = new byte[avail];
+        while (true) {
+            int amt = stream.read(data, pos, data.length-pos);
+            if (amt <= 0) {
+                return data;
+            }
+            pos += amt;
+            avail = stream.available();
+            if (avail > data.length-pos) {
+                byte[] newData = new byte[pos+avail];
+                System.arraycopy(data, 0, newData, 0, pos);
+                data = newData;
+            }
+        }
+    }
+    
+    private void collectDumpInfoFLOCK(PrintWriter pw, String[] args) {
+        List<String> fileList = getUsageStatsFileListFLOCK();
+        if (fileList == null) {
+            return;
+        }
+        final boolean isCheckinRequest = scanArgs(args, "-c");
+        Collections.sort(fileList);
+        File usageFile = new File(mFilePrefix);
+        String dirName = usageFile.getParent();
+        File dir = new File(dirName);
+        String filePrefix = usageFile.getName();
+        // file name followed by dot
+        int prefixLen = filePrefix.length()+1;
+        String todayStr = getCurrentDateStr(null);
+        for (String file : fileList) {
+            File dFile = new File(dir, file);
+            String dateStr = file.substring(prefixLen);
+            try {
+                Parcel in = getParcelForFile(dFile);
+                collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCheckinRequest);
+                if (isCheckinRequest && !todayStr.equalsIgnoreCase(dateStr)) {
+                    // Delete old file after collecting info only for checkin requests
+                    dFile.delete();
+                }
+            } catch (FileNotFoundException e) {
+                Log.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file);
+                return;
+            } catch (IOException e) {
+                Log.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file);
+            }      
+        }
+    }
+    
+    private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw,
+            String date, boolean isCheckinRequest) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Date:");
+        sb.append(date);
+        boolean first = true;
+        while (in.dataAvail() > 0) {
+            String pkgName = in.readString();
+            int launchCount = in.readInt();
+            long usageTime = in.readLong();
+            if (isCheckinRequest) {
+                if (!first) {
+                    sb.append(",");
+                }
+                sb.append(pkgName);
+                sb.append(",");
+                sb.append(launchCount);
+                sb.append(",");
+                sb.append(usageTime);
+                sb.append("ms");
+            } else {
+                if (first) {
+                    sb.append("\n");
+                }
+                sb.append("pkg=");
+                sb.append(pkgName);
+                sb.append(", launchCount=");
+                sb.append(launchCount);
+                sb.append(", usageTime=");
+                sb.append(usageTime);
+                sb.append(" ms\n");
+            }
+            first = false;
+        }
+        pw.write(sb.toString());
+    }
+    
+    /**
+     * Searches array of arguments for the specified string
+     * @param args array of argument strings
+     * @param value value to search for
+     * @return true if the value is contained in the array
+     */
+    private static boolean scanArgs(String[] args, String value) {
+        if (args != null) {
+            for (String arg : args) {
+                if (value.equals(arg)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    
+    @Override
+    /*
+     * The data persisted to file is parsed and the stats are computed. 
+     */
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        synchronized (mFileLock) {
+            collectDumpInfoFLOCK(pw, args);
+        }
+    }
+
+}
diff --git a/services/java/com/android/server/am/package.html b/services/java/com/android/server/am/package.html
new file mode 100755
index 0000000..c9f96a6
--- /dev/null
+++ b/services/java/com/android/server/am/package.html
@@ -0,0 +1,5 @@
+<body>
+
+{@hide}
+
+</body>
