FileDocCategorySizeDatePackage
ActivityManagerService.javaAPI DocAndroid 1.5 API487203Wed May 06 22:42:00 BST 2009com.android.server.am

ActivityManagerService

public final class ActivityManagerService extends android.app.ActivityManagerNative implements Watchdog.Monitor

Fields Summary
static final String
TAG
static final boolean
DEBUG
static final boolean
localLOGV
static final boolean
DEBUG_SWITCH
static final boolean
DEBUG_TASKS
static final boolean
DEBUG_PAUSE
static final boolean
DEBUG_OOM_ADJ
static final boolean
DEBUG_TRANSITION
static final boolean
DEBUG_BROADCAST
static final boolean
DEBUG_SERVICE
static final boolean
DEBUG_VISBILITY
static final boolean
DEBUG_PROCESSES
static final boolean
DEBUG_USER_LEAVING
static final boolean
DEBUG_RESULTS
static final boolean
VALIDATE_TOKENS
static final boolean
SHOW_ACTIVITY_START_TIME
static final long
BATTERY_STATS_TIME
static final boolean
MONITOR_CPU_USAGE
static final long
MONITOR_CPU_MIN_TIME
static final long
MONITOR_CPU_MAX_TIME
static final boolean
MONITOR_THREAD_CPU_USAGE
static final int
LOG_CONFIGURATION_CHANGED
static final int
LOG_CPU
static final int
LOG_AM_FINISH_ACTIVITY
static final int
LOG_TASK_TO_FRONT
static final int
LOG_AM_NEW_INTENT
static final int
LOG_AM_CREATE_TASK
static final int
LOG_AM_CREATE_ACTIVITY
static final int
LOG_AM_RESTART_ACTIVITY
static final int
LOG_AM_RESUME_ACTIVITY
static final int
LOG_ANR
static final int
LOG_ACTIVITY_LAUNCH_TIME
static final int
LOG_AM_PROCESS_BOUND
static final int
LOG_AM_PROCESS_DIED
static final int
LOG_AM_FAILED_TO_PAUSE_ACTIVITY
static final int
LOG_AM_PAUSE_ACTIVITY
static final int
LOG_AM_PROCESS_START
static final int
LOG_AM_PROCESS_BAD
static final int
LOG_AM_PROCESS_GOOD
static final int
LOG_AM_LOW_MEMORY
static final int
LOG_AM_DESTROY_ACTIVITY
static final int
LOG_AM_RELAUNCH_RESUME_ACTIVITY
static final int
LOG_AM_RELAUNCH_ACTIVITY
static final int
LOG_AM_KILL_FOR_MEMORY
static final int
LOG_AM_BROADCAST_DISCARD_FILTER
static final int
LOG_AM_BROADCAST_DISCARD_APP
static final int
LOG_AM_CREATE_SERVICE
static final int
LOG_AM_DESTROY_SERVICE
static final int
LOG_AM_PROCESS_CRASHED_TOO_MUCH
static final int
LOG_AM_DROP_PROCESS
static final int
LOG_AM_SERVICE_CRASHED_TOO_MUCH
static final int
LOG_AM_SCHEDULE_SERVICE_RESTART
static final int
LOG_AM_PROVIDER_LOST_PROCESS
static final int
LOG_BOOT_PROGRESS_AMS_READY
static final int
LOG_BOOT_PROGRESS_ENABLE_SCREEN
private static final String
SYSTEM_SECURE
static final int
MAX_PROCESSES
static final boolean
ENFORCE_PROCESS_LIMIT
static final int
MAX_ACTIVITIES
static final int
MAX_RECENT_TASKS
static final long
ACTIVITY_INACTIVE_RESET_TIME
static final boolean
SHOW_APP_STARTING_ICON
static final int
PAUSE_TIMEOUT
static final int
LAUNCH_TIMEOUT
How long we can hold the launch wake lock before giving up.
static final int
PROC_START_TIMEOUT
static final int
IDLE_TIMEOUT
static final int
GC_TIMEOUT
static final int
DESTROY_TIMEOUT
static final int
BROADCAST_TIMEOUT
static final int
SERVICE_TIMEOUT
static final int
SERVICE_RESTART_DURATION
static final int
MAX_SERVICE_INACTIVITY
static final int
KEY_DISPATCHING_TIMEOUT
static final int
MIN_CRASH_INTERVAL
static final int
INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT
static int
EMPTY_APP_ADJ
static int
CONTENT_PROVIDER_ADJ
final int
HIDDEN_APP_MAX_ADJ
static int
HIDDEN_APP_MIN_ADJ
final int
HOME_APP_ADJ
final int
SECONDARY_SERVER_ADJ
final int
VISIBLE_APP_ADJ
final int
FOREGROUND_APP_ADJ
static final int
CORE_SERVER_ADJ
static final int
SYSTEM_ADJ
static final int
PAGE_SIZE
final int
EMPTY_APP_MEM
final int
HIDDEN_APP_MEM
final int
HOME_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
final ArrayList
mHistory
The back history of all previous (and possibly still running) activities. It contains HistoryRecord objects.
final ArrayList
mParallelBroadcasts
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
mOrderedBroadcasts
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..
boolean
mBroadcastsScheduled
Set when we current have a BROADCAST_INTENT_MSG in flight.
boolean
mUserLeaving
Set to indicate whether to issue an onUserLeaving callback when a newly launched activity is being brought in front of us.
HistoryRecord
mPausingActivity
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
mResumedActivity
Current activity that is resumed, or null if there is none.
HistoryRecord
mFocusedActivity
Activity we have told the window manager to have key focus.
HistoryRecord
mLastPausedActivity
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.
final ArrayList
mWaitingVisibleActivities
List of activities that are waiting for a new activity to become visible before completing whatever operation they are supposed to do.
final ArrayList
mStoppingActivities
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
mRecentTasks
List of intents that were used to start the most recent tasks.
final ArrayList
mFinishingActivities
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 com.android.server.ProcessMap
mProcessNames
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 com.android.server.ProcessMap
mProcessCrashTimes
The last time that various processes have crashed.
final com.android.server.ProcessMap
mBadProcesses
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 android.util.SparseArray
mPidsSelfLocked
All of the processes we currently have running organized by pid. The keys are the pid running the application.

NOTE: This object is protected by its own lock, NOT the global activity manager lock!

final android.util.SparseArray
mForegroundProcesses
final ArrayList
mProcessesOnHold
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
mStartingProcesses
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
mPersistentStartingProcesses
List of persistent applications that are in the process of being started.
final ArrayList
mRemovedProcesses
Processes that are being forcibly torn down.
final ArrayList
mLRUProcesses
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
mProcessesToGc
List of processes that should gc as soon as things are idle.
private ProcessRecord
mHomeProcess
This is the process holding what we currently consider to be the "home" activity.
private final ArrayList
mLRUActivities
List of running activities, sorted by recent usage. The first entry in the list is the least recently used. It contains HistoryRecord objects.
final HashSet
mPendingResultRecords
Set of PendingResultRecord objects that are currently active.
final HashMap
mIntentSenderRecords
Set of IntentSenderRecord objects that are currently active.
BroadcastRecord
mPendingBroadcast
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.
final HashMap
mRegisteredReceivers
Keeps track of all IIntentReceivers that have been registered for broadcasts. Hash keys are the receiver IBinder, hash value is a ReceiverList.
final com.android.server.IntentResolver
mReceiverResolver
Resolver for broadcast intents to registered receivers. Holds BroadcastFilter (subclass of IntentFilter).
final HashMap
mStickyBroadcasts
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
mServices
All currently running services.
final HashMap
mServicesByIntent
All currently running services indexed by the Intent used to start them.
final HashMap
mServiceConnections
All currently bound service connections. Keys are the IBinder of the client's IServiceConnection.
final ArrayList
mPendingServices
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
mRestartingServices
List of services that are scheduled to restart following a crash.
final ArrayList
mStoppingServices
List of services that are in the process of being stopped.
final ArrayList
mPendingThumbnails
List of PendingThumbnailsRecord objects of clients who are still waiting to receive all of the thumbnails for a task.
final ArrayList
mCancelledThumbnails
List of HistoryRecord objects that have been finished and must still report back to a pending thumbnail receiver.
final HashMap
mProvidersByName
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
mProvidersByClass
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 ArrayList
mLaunchingProviders
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.
private final android.util.SparseArray
mGrantedUriPermissions
Global set of specific Uri permissions that have been granted.
private static ThreadLocal
sCallerIdentity
final BatteryStatsService
mBatteryStatsService
All information we have collected about the runtime performance of any user id that can impact battery performance.
final UsageStatsService
mUsageStatsService
information about component usage
android.content.res.Configuration
mConfiguration
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.
HashMap
mAppBindArgs
List of initialization arguments to pass to all processes when binding applications to them. For example, references to the commonly used services.
boolean
mStartRunning
Used to control how we initialize the service.
android.content.ComponentName
mTopComponent
String
mTopAction
String
mTopData
boolean
mSystemReady
boolean
mBooting
android.content.Context
mContext
int
mFactoryTest
boolean
mSleeping
Set while we are wanting to sleep, to prevent any activities from being started/resumed.
PowerManager.WakeLock
mGoingToSleep
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
mLaunchingActivity
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.
int
mCurTask
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
mAdjSeq
Current sequence id for oom_adj computation traversal.
boolean
mSimpleProcessManagement
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).
int[]
mProcDeaths
System monitoring: number of processes that died since the last N procs were started.
String
mDebugApp
boolean
mWaitForDebugger
boolean
mDebugTransient
String
mOrigDebugApp
boolean
mOrigWaitForDebugger
boolean
mAlwaysFinishActivities
android.app.IActivityWatcher
mWatcher
Runnable
mRequestPssCallback
Callback of last caller to {@link #requestPss}.
final ArrayList
mRequestPssList
Remaining processes for which we are waiting results from the last call to {@link #requestPss}.
final Thread
mProcessStatsThread
Runtime statistics collection thread. This object's lock is used to protect all related state.
final com.android.server.ProcessStats
mProcessStats
Used to collect process stats when showing not responding dialog. Protected by mProcessStatsThread.
long
mLastCpuTime
long
mLastWriteTime
boolean
mBooted
Set to true after the system has finished booting.
int
mProcessLimit
com.android.server.WindowManagerService
mWindowManager
static ActivityManagerService
mSelf
static android.app.ActivityThread
mSystemThread
static final int
SHOW_ERROR_MSG
static final int
SHOW_NOT_RESPONDING_MSG
static final int
SHOW_FACTORY_ERROR_MSG
static final int
UPDATE_CONFIGURATION_MSG
static final int
GC_BACKGROUND_PROCESSES_MSG
static final int
WAIT_FOR_DEBUGGER_MSG
static final int
BROADCAST_INTENT_MSG
static final int
BROADCAST_TIMEOUT_MSG
static final int
PAUSE_TIMEOUT_MSG
static final int
IDLE_TIMEOUT_MSG
static final int
IDLE_NOW_MSG
static final int
SERVICE_TIMEOUT_MSG
static final int
UPDATE_TIME_ZONE
static final int
SHOW_UID_ERROR_MSG
static final int
IM_FEELING_LUCKY_MSG
static final int
LAUNCH_TIMEOUT_MSG
static final int
DESTROY_TIMEOUT_MSG
static final int
SERVICE_ERROR_MSG
static final int
RESUME_TOP_ACTIVITY_MSG
static final int
PROC_START_TIMEOUT_MSG
android.app.AlertDialog
mUidAlert
final android.os.Handler
mHandler
private static final int
FINISH_IMMEDIATELY
private static final int
FINISH_AFTER_PAUSE
private static final int
FINISH_AFTER_VISIBLE
Constructors Summary
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"));
        HOME_APP_ADJ =
            Integer.valueOf(SystemProperties.get("ro.HOME_APP_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;
        HOME_APP_MEM =
            Integer.valueOf(SystemProperties.get("ro.HOME_APP_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();
    
Methods Summary
public final voidactivityDestroyed(android.os.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 final voidactivityIdle(android.os.IBinder token)

        final long origId = Binder.clearCallingIdentity();
        activityIdleInternal(token, false);
        Binder.restoreCallingIdentity(origId);
    
final voidactivityIdleInternal(android.os.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 voidactivityPaused(android.os.IBinder token, android.os.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 voidactivityPaused(android.os.IBinder token, android.os.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 voidactivityStopped(android.os.IBinder token, android.graphics.Bitmap thumbnail, java.lang.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);
    
final ProcessRecordaddAppLocked(android.content.pm.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;
    
private final voidaddRecentTask(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);
    
private final voidappDiedLocked(ProcessRecord app, int pid, android.app.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 voidappNotRespondingLocked(ProcessRecord app, HistoryRecord activity, java.lang.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;
    
public final voidattachApplication(android.app.IApplicationThread thread)

        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    
private final booleanattachApplicationLocked(android.app.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 intbindService(android.app.IApplicationThread caller, android.os.IBinder token, android.content.Intent service, java.lang.String resolvedType, android.app.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 final voidbringDownServiceLocked(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);
        }
    
private final booleanbringUpServiceLocked(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;
    
public final intbroadcastIntent(android.app.IApplicationThread caller, android.content.Intent intent, java.lang.String resolvedType, android.app.IIntentReceiver resultTo, int resultCode, java.lang.String resultData, android.os.Bundle map, java.lang.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;
        }
    
intbroadcastIntentInPackage(java.lang.String packageName, int uid, android.content.Intent intent, java.lang.String resolvedType, android.app.IIntentReceiver resultTo, int resultCode, java.lang.String resultData, android.os.Bundle map, java.lang.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;
        }
    
private final intbroadcastIntentLocked(ProcessRecord callerApp, java.lang.String callerPackage, android.content.Intent intent, java.lang.String resolvedType, android.app.IIntentReceiver resultTo, int resultCode, java.lang.String resultData, android.os.Bundle map, java.lang.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.
            boolean skip = false;
            if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
                skip = true;
            } else if (intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())) {
                skip = true;
            } else if (intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
                skip = true;
            }
            String skipPackage = (skip && 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;
    
private final voidbroadcastTimeout()

        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 voidbumpServiceExecutingLocked(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 booleancanGcNow()
Returns true if things are idle enough to perform GCs.

        return mParallelBroadcasts.size() == 0
                && mOrderedBroadcasts.size() == 0
                && (mSleeping || (mResumedActivity != null &&
                        mResumedActivity.idle));
    
public voidcancelIntentSender(android.app.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);
        }
    
voidcancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity)

        rec.canceled = true;
        mIntentSenderRecords.remove(rec.key);
        if (cleanActivity && rec.key.activity != null) {
            rec.key.activity.pendingResults.remove(rec.ref);
        }
    
intcheckCallingPermission(java.lang.String permission)
Binder IPC calls go through the public entry point. This can be called with or without the global lock held.

        return checkPermission(permission,
                Binder.getCallingPid(),
                Binder.getCallingUid());
    
intcheckComponentPermission(java.lang.String permission, int pid, int uid, int reqUid)
This can be called with or without the global lock held.

        // 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;
    
private final java.lang.StringcheckContentProviderPermissionLocked(android.content.pm.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 booleancheckHoldingPermissionsLocked(android.content.pm.IPackageManager pm, android.content.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;
        }
    
public intcheckPermission(java.lang.String permission, int pid, int uid)
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.

        if (permission == null) {
            return PackageManager.PERMISSION_DENIED;
        }
        return checkComponentPermission(permission, pid, uid, -1);
    
public intcheckUriPermission(android.net.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 final booleancheckUriPermissionLocked(android.net.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;
    
private final voidcleanUpActivityLocked(HistoryRecord r, boolean cleanServices)
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.

        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 voidcleanUpActivityServicesLocked(HistoryRecord r)
Perform clean-up of service connections in an activity record.

        // 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;
        }
    
private final voidcleanUpApplicationRecordLocked(ProcessRecord app, boolean restarting, int index)
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.

        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 (app == mHomeProcess) {
            mHomeProcess = null;
        }
        
        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;
        }
    
public booleanclearApplicationUserData(java.lang.String packageName, android.content.pm.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 voidcollectPss(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++;
                }
            }
        }
    
private final voidcompletePauseLocked()

        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();
        }
    
private final voidcompleteResumeLocked(HistoryRecord next)
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.

        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();
    
private final intcomputeOomAdjLocked(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;

        // Determine the importance of the process, starting with most
        // important to least, and assign an appropriate OOM adjustment.
        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 (app == mHomeProcess) {
            // This process is hosting what we currently consider to be the
            // home app, so we don't want to let it go into the background.
            adj = HOME_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 adjustment.  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.binding.client == app) {
                            // Binding to ourself is not interesting.
                            continue;
                        }
                        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();
                        if (client == app) {
                            // Being our own client is not interesting.
                            continue;
                        }
                        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;
    
private final voiddecPersistentCountLocked(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();
    
private final voiddeliverNewIntentLocked(HistoryRecord r, android.content.Intent intent)
Deliver a new Intent to an existing activity, so that its onNewIntent() method will be called at the proper time.

        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 voiddeliverToRegisteredReceiver(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 booleandestroyActivityLocked(HistoryRecord r, boolean removeFromApp)
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.

        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;
    
protected voiddump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.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("  mHomeProcess: " + mHomeProcess);
            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);
        }
    
private static final voiddumpApplicationMemoryUsage(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.util.List list, java.lang.String prefix, java.lang.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();
                    }
                }
            }
        }
    
voiddumpBroadcasts(java.io.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), "    ");
        }
    
private static final voiddumpHistoryList(java.io.PrintWriter pw, java.util.List list, java.lang.String prefix, java.lang.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 intdumpProcessList(java.io.PrintWriter pw, java.util.List list, java.lang.String prefix, java.lang.String normalLabel, java.lang.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;
    
voiddumpProviders(java.io.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, "    ");
                }
            }
        }
    
voiddumpSenders(java.io.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);
                    }
                }
            }
        }
    
protected voiddumpService(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)
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

        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);
                }
            }
        }
    
private voiddumpService(java.io.FileDescriptor fd, java.io.PrintWriter pw, ServiceRecord r, java.lang.String[] args)
Invokes IApplicationThread.dumpService() on the thread of the specified service if there is a thread associated with the service.

        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");
            }
        }
    
voiddumpServices(java.io.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, "    ");
                }
            }
        }
    
voidenableScreenAfterBoot()

        mWindowManager.enableScreenAfterBoot();
    
voidenforceCallingPermission(java.lang.String permission, java.lang.String func)
This can be called with or without the global lock held.

        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 voidensureActivitiesVisibleLocked(HistoryRecord top, HistoryRecord starting, java.lang.String onlyThisProcess, int configChanges)
Make sure that all activities that need to be visible (that is, they currently can be seen by the user) actually are.

        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--;
        }
    
private final voidensureActivitiesVisibleLocked(HistoryRecord starting, int configChanges)
Version of ensureActivitiesVisible that can easily be called anywhere.

        HistoryRecord r = topRunningActivityLocked(null);
        if (r != null) {
            ensureActivitiesVisibleLocked(r, starting, null, configChanges);
        }
    
private final booleanensureActivityConfigurationLocked(HistoryRecord r, int globalChanges)
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.

        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;
    
public final voidenterSafeMode()

        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);
            }
        }
    
private final intfindActivityInHistoryLocked(HistoryRecord r, int task)
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.

        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;
    
private HistoryRecordfindActivityLocked(android.content.Intent intent, android.content.pm.ActivityInfo info)
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.

        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;
    
private final intfindAffinityTaskTopLocked(int startIndex, java.lang.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;
    
private final ServiceRecordfindServiceLocked(android.content.ComponentName name, android.os.IBinder token)

        ServiceRecord r = mServices.get(name);
        return r == token ? r : null;
    
private com.android.server.am.ActivityManagerService$ServiceLookupResultfindServiceLocked(android.content.Intent service, java.lang.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 HistoryRecordfindTaskLocked(android.content.Intent intent, android.content.pm.ActivityInfo info)
Returns the top activity in any existing task matching the given Intent. Returns null if no such task is found.

        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;
    
public final booleanfinishActivity(android.os.IBinder token, int resultCode, android.content.Intent resultData)
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.

        // 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;
        }
    
private final booleanfinishActivityLocked(HistoryRecord r, int index, int resultCode, android.content.Intent resultData, java.lang.String reason)

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.

        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 (DEBUG_RESULTS) Log.v(TAG, "Adding result to " + resultTo
                    + " who=" + r.resultWho + " req=" + r.requestCode
                    + " res=" + resultCode + " data=" + resultData);
            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;
        }
        else if (DEBUG_RESULTS) Log.v(TAG, "No result destination from " + r);

        // 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 final HistoryRecordfinishCurrentActivityLocked(HistoryRecord r, int mode)


        
              
        final int index = indexOfTokenLocked(r, false);
        if (index < 0) {
            return null;
        }

        return finishCurrentActivityLocked(r, index, mode);
    
private final HistoryRecordfinishCurrentActivityLocked(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;
    
public voidfinishInstrumentation(android.app.IApplicationThread target, int resultCode, android.os.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);
        }
    
voidfinishInstrumentationLocked(ProcessRecord app, int resultCode, android.os.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 voidfinishOtherInstances(android.os.IBinder token, android.content.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);
        }
    
public voidfinishReceiver(android.os.IBinder who, int resultCode, java.lang.String resultData, android.os.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 booleanfinishReceiverLocked(android.os.IBinder receiver, int resultCode, java.lang.String resultData, android.os.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 final voidfinishSubActivity(android.os.IBinder token, java.lang.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);
        }
    
private final voidfinishTaskMove(int task)

        resumeTopActivityLocked(null);
    
voidforegroundTokenDied(com.android.server.am.ActivityManagerService$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();
        }
    
private final java.util.ListgenerateApplicationProvidersLocked(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 ActivityManager.ProcessErrorStateInfogenerateProcessError(ProcessRecord app, int condition, java.lang.String tag, java.lang.String shortMsg, java.lang.String longMsg, byte[] crashData)
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.

        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;
    
public android.content.ComponentNamegetActivityClassForToken(android.os.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 android.content.ComponentNamegetCallingActivity(android.os.IBinder token)

        synchronized (this) {
            HistoryRecord r = getCallingRecordLocked(token);
            return r != null ? r.intent.getComponent() : null;
        }
    
public java.lang.StringgetCallingPackage(android.os.IBinder token)

        synchronized (this) {
            HistoryRecord r = getCallingRecordLocked(token);
            return r != null && r.app != null ? r.app.processName : null;
        }
    
private HistoryRecordgetCallingRecordLocked(android.os.IBinder token)

        int index = indexOfTokenLocked(token, true);
        if (index >= 0) {
            HistoryRecord r = (HistoryRecord)mHistory.get(index);
            if (r != null) {
                return r.resultTo;
            }
        }
        return null;
    
private java.util.HashMapgetCommonServicesLocked()
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.

        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;
    
public android.content.res.ConfigurationgetConfiguration()

        Configuration ci;
        synchronized(this) {
            ci = new Configuration(mConfiguration);
        }
        return ci;
    
public final ContentProviderHoldergetContentProvider(android.app.IApplicationThread caller, java.lang.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 ContentProviderHoldergetContentProviderExternal(java.lang.String name)

        return getContentProviderImpl(null, name);
    
private final ContentProviderHoldergetContentProviderImpl(android.app.IApplicationThread caller, java.lang.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 android.content.pm.ConfigurationInfogetDeviceConfigurationInfo()

        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 android.app.IIntentSendergetIntentSender(int type, java.lang.String packageName, android.os.IBinder token, java.lang.String resultWho, int requestCode, android.content.Intent intent, java.lang.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;
        }
    
private final intgetLRURecordIndexForAppLocked(android.app.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;
    
public voidgetMemoryInfo(ActivityManager.MemoryInfo outInfo)

        outInfo.availMem = Process.getFreeMemory();
        outInfo.threshold = HOME_APP_MEM;
        outInfo.lowMemory = outInfo.availMem <
                (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
    
public java.lang.StringgetPackageForIntentSender(android.app.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 java.lang.StringgetPackageForToken(android.os.IBinder token)

        synchronized(this) {
            int index = indexOfTokenLocked(token, false);
            if (index >= 0) {
                HistoryRecord r = (HistoryRecord)mHistory.get(index);
                return r.packageName;
            }
            return null;
        }
    
public intgetProcessLimit()

        return mProcessLimit;
    
private final ProcessRecordgetProcessRecordLocked(java.lang.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;
    
public java.util.ListgetProcessesInErrorState()

        // 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 java.util.ListgetRecentTasks(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 ProcessRecordgetRecordForAppLocked(android.app.IApplicationThread thread)

        if (thread == null) {
            return null;
        }

        int appIndex = getLRURecordIndexForAppLocked(thread);
        return appIndex >= 0 ? mLRUProcesses.get(appIndex) : null;
    
public intgetRequestedOrientation(android.os.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);
        }
    
public java.util.ListgetRunningAppProcesses()

        // 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 + 1;
                    } else if (adj >= HOME_APP_ADJ) {
                        currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
                        currApp.lru = 0;
                    } 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;
    
public java.util.ListgetServices(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 java.util.ListgetStickies(java.lang.String action, android.content.IntentFilter filter, java.util.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;
    
public intgetTaskForActivity(android.os.IBinder token, boolean onlyRoot)

        synchronized(this) {
            return getTaskForActivityLocked(token, onlyRoot);
        }
    
intgetTaskForActivityLocked(android.os.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;
    
public java.util.ListgetTasks(int maxNum, int flags, android.app.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 voidgoingToSleep()

        synchronized(this) {
            mSleeping = true;
            mWindowManager.setEventDispatching(false);

            if (mResumedActivity != null) {
                pauseIfSleepingLocked();
            } else {
                Log.w(TAG, "goingToSleep with no resumed activity!");
            }
        }
    
public voidgrantUriPermission(android.app.IApplicationThread caller, java.lang.String targetPkg, android.net.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 voidgrantUriPermissionFromIntentLocked(int callingUid, java.lang.String targetPkg, android.content.Intent intent, HistoryRecord activity)

        if (intent == null) {
            return;
        }
        Uri data = intent.getData();
        if (data == null) {
            return;
        }
        grantUriPermissionLocked(callingUid, targetPkg, data,
                intent.getFlags(), activity);
    
private voidgrantUriPermissionLocked(int callingUid, java.lang.String targetPkg, android.net.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);
        }
    
booleanhandleAppCrashLocked(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;
    
private final voidhandleAppDiedLocked(ProcessRecord app, boolean restarting)
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.

        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);
                }
            }
        }
    
public inthandleApplicationError(android.os.IBinder app, int flags, java.lang.String tag, java.lang.String shortMsg, java.lang.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;
    
private final intindexOfTokenLocked(android.os.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;
    
public static final voidinstallSystemProviders()

        ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
        List providers = mSelf.generateApplicationProvidersLocked(app);
        mSystemThread.installSystemProviders(providers);
    
private booleanisNextTransitionForward()

        int transit = mWindowManager.getPendingAppTransition();
        return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
                || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
                || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
    
voidkillAppAtUsersRequest(ProcessRecord app, android.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);
            }
            
        }
    
public booleankillPidsForMemory(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;
    
private final voidkillServicesLocked(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 voidlogBroadcastReceiverDiscard(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 voidlogStartActivity(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());
    
public static final android.content.Contextmain(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;
    
booleanmakeAppCrashingLocked(ProcessRecord app, java.lang.String tag, java.lang.String shortMsg, java.lang.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);
    
voidmakeAppNotRespondingLocked(ProcessRecord app, java.lang.String tag, java.lang.String shortMsg, java.lang.String longMsg, byte[] crashData)

        app.notResponding = true;
        app.notRespondingReport = generateProcessError(app, 
                ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING, tag, shortMsg, longMsg, 
                crashData);
        startAppProblemLocked(app);
        app.stopFreezingAllLocked();
    
ActivityManager.RunningServiceInfomakeRunningServiceInfoLocked(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 voidmonitor()
In this method we try to acquire our lock to make sure that we have not deadlocked

        synchronized (this) { }
    
public booleanmoveActivityTaskToBack(android.os.IBinder token, boolean nonRoot)
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.

        synchronized(this) {
            final long origId = Binder.clearCallingIdentity();
            int taskId = getTaskForActivityLocked(token, !nonRoot);
            if (taskId >= 0) {
                return moveTaskToBackLocked(taskId);
            }
            Binder.restoreCallingIdentity(origId);
        }
        return false;
    
private final HistoryRecordmoveActivityToFrontLocked(int where)
Reorder the history stack so that the activity at the given index is brought to the front.

        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;
    
public voidmoveTaskBackwards(int task)

        enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
                "moveTaskBackwards()");

        synchronized(this) {
            final long origId = Binder.clearCallingIdentity();
            moveTaskBackwardsLocked(task);
            Binder.restoreCallingIdentity(origId);
        }
    
private final voidmoveTaskBackwardsLocked(int task)

        Log.e(TAG, "moveTaskBackwards not yet implemented!");
    
public voidmoveTaskToBack(int task)

        enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
                "moveTaskToBack()");

        synchronized(this) {
            final long origId = Binder.clearCallingIdentity();
            moveTaskToBackLocked(task);
            Binder.restoreCallingIdentity(origId);
        }
    
private final booleanmoveTaskToBackLocked(int task)
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.

        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 voidmoveTaskToFront(int task)
TODO: Add mWatcher hook

        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 voidmoveTaskToFrontLocked(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);
    
final ProcessRecordnewProcessRecordLocked(android.app.IApplicationThread thread, android.content.pm.ApplicationInfo info, java.lang.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);
    
public voidnoteWakeupAlarm(android.app.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 booleanonTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)

        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;
        }
    
public android.os.ParcelFileDescriptoropenContentUri(android.net.Uri uri)

        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;
    
voidpauseIfSleepingLocked()

        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 android.os.IBinderpeekService(android.content.Intent service, java.lang.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;
    
final voidperformAppGcLocked(ProcessRecord app)
Ask a given process to GC right now.

        try {
            app.lastRequestedGc = SystemClock.uptimeMillis();
            if (app.thread != null) {
                app.thread.processInBackground();
            }
        } catch (Exception e) {
            // whatever.
        }
    
final voidperformAppGcsIfAppropriateLocked()
If all looks good, perform GCs on all processes waiting for them.

        if (canGcNow()) {
            performAppGcsLocked();
            return;
        }
        // Still not idle, wait some more.
        scheduleAppGcsLocked();
    
final voidperformAppGcsLocked()
Perform GCs on all processes that are waiting for it, but only if things are idle.

        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;
                }
            }
        }
    
private final HistoryRecordperformClearTopTaskLocked(int taskId, HistoryRecord newR, boolean doClear)
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.

        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;
    
static voidperformReceive(ProcessRecord app, android.app.IIntentReceiver receiver, android.content.Intent intent, int resultCode, java.lang.String data, android.os.Bundle extras, boolean ordered)

        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);
        }
    
final voidperformServiceRestartLocked(ServiceRecord r)

        if (!mRestartingServices.contains(r)) {
            return;
        }
        bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
    
public static booleanprepareTraceFile(boolean removeExisting)
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

        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 voidprocessCurBroadcastLocked(BroadcastRecord r, ProcessRecord app)

        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;
            }
        }

    
private final voidprocessNextBroadcast(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;
        }
    
private final voidprocessStartTimedOutLocked(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);
        }
    
final java.util.ArrayListprocessStoppingActivitiesLocked(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;
    
public booleanprofileControl(java.lang.String process, boolean start, java.lang.String path)


        synchronized (this) {
            // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
            // its own permission.
            if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
                    != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException("Requires permission "
                        + android.Manifest.permission.SET_ACTIVITY_WATCHER);
            }
            
            ProcessRecord proc = null;
            try {
                int pid = Integer.parseInt(process);
                synchronized (mPidsSelfLocked) {
                    proc = mPidsSelfLocked.get(pid);
                }
            } catch (NumberFormatException e) {
            }
            
            if (proc == null) {
                HashMap<String, SparseArray<ProcessRecord>> all
                        = mProcessNames.getMap();
                SparseArray<ProcessRecord> procs = all.get(process);
                if (procs != null && procs.size() > 0) {
                    proc = procs.valueAt(0);
                }
            }
            
            if (proc == null || proc.thread == null) {
                throw new IllegalArgumentException("Unknown process: " + process);
            }
            
            boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
            if (isSecure) {
                if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
                    throw new SecurityException("Process not debuggable: " + proc);
                }
            }
            
            try {
                proc.thread.profilerControl(start, path);
                return true;
            } catch (RemoteException e) {
                throw new IllegalStateException("Process disappeared");
            }
        }
    
public final voidpublishContentProviders(android.app.IApplicationThread caller, java.util.List 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 voidpublishService(android.os.IBinder token, android.content.Intent intent, android.os.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);
            }
        }
    
final java.lang.StringreadFile(java.lang.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 "";
    
private final booleanrealStartActivityLocked(HistoryRecord r, ProcessRecord app, boolean andResume, boolean checkConfig)


        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(
                    mConfiguration,
                    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);
            }
            if (r.isHomeActivity) {
                mHomeProcess = app;
            }
            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 voidrealStartServiceLocked(ServiceRecord r, ProcessRecord app)

        if (app.thread == null) {
            throw new RemoteException();
        }

        r.app = app;
        r.restartTime = r.lastActivity = 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);
    
public android.content.IntentregisterReceiver(android.app.IApplicationThread caller, android.app.IIntentReceiver receiver, android.content.IntentFilter filter, java.lang.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;
        }
    
private final booleanrelaunchActivityLocked(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;
    
private final voidremoveActivityFromHistoryLocked(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);
        }
    
private voidremoveActivityUriPermissionsLocked(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 voidremoveConnectionLocked(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 voidremoveContentProvider(android.app.IApplicationThread caller, java.lang.String name)
Drop a content provider from a ProcessRecord's bookkeeping

param
cpr

        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 voidremoveContentProviderExternal(java.lang.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();
        }
    
private final voidremoveDyingProviderLocked(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);
    
private static voidremoveHistoryRecordsForAppLocked(java.util.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);
            }
        }
    
private final booleanremoveProcessLocked(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;
    
voidremoveReceiverLocked(ReceiverList rl)

        mRegisteredReceivers.remove(rl.receiver.asBinder());
        int N = rl.size();
        for (int i=0; i<N; i++) {
            mReceiverResolver.removeFilter(rl.get(i));
        }
    
voidremoveRequestedPss(ProcessRecord proc)

        Runnable callback = null;
        synchronized (this) {
            if (mRequestPssList.remove(proc)) {
                if (mRequestPssList.size() == 0) {
                    callback = mRequestPssCallback;
                    mRequestPssCallback = null;
                }
            }
        }
        
        if (callback != null) {
            callback.run();
        }
    
private voidremoveUriPermissionIfNeededLocked(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);
                }
            }
        }
    
public voidreportPss(android.app.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);
        }
    
private voidreportStartInstrumentationFailure(android.app.IInstrumentationWatcher watcher, android.content.ComponentName cn, java.lang.String report)
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.

        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);
        }
    
public voidreportThumbnail(android.os.IBinder token, android.graphics.Bitmap thumbnail, java.lang.CharSequence description)

        //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
        final long origId = Binder.clearCallingIdentity();
        sendPendingThumbnail(null, token, thumbnail, description, true);
        Binder.restoreCallingIdentity(origId);
    
private final booleanrequestFinishActivityLocked(android.os.IBinder token, int resultCode, android.content.Intent resultData, java.lang.String reason)

return
Returns true if the activity is being finished, false if for some reason it is being left as-is.

        if (DEBUG_RESULTS) 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;
    
public voidrequestPss(java.lang.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);
    
private final booleanrequestServiceBindingLocked(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 voidrequestServiceBindingsLocked(ServiceRecord r)

        Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
        while (bindings.hasNext()) {
            IntentBindRecord i = bindings.next();
            if (!requestServiceBindingLocked(r, i, false)) {
                break;
            }
        }
    
private final HistoryRecordresetTaskIfNeededLocked(HistoryRecord taskTop, HistoryRecord newActivity)
Perform a reset of the given task, if needed as part of launching it. Returns the new HistoryRecord at the top of the task.

        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 && !clearWhenTaskReset && 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 && !clearWhenTaskReset && 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;
    
public voidrestartPackage(java.lang.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 voidrestartPackageLocked(java.lang.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 booleanresumeTopActivityLocked(HistoryRecord prev)
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.

        // 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, 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(
                    mConfiguration,
                    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 (DEBUG_RESULTS) 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 HistoryRecordresumedAppLocked()

        HistoryRecord resumedActivity = mResumedActivity;
        if (resumedActivity == null || resumedActivity.app == null) {
            resumedActivity = mPausingActivity;
            if (resumedActivity == null || resumedActivity.app == null) {
                resumedActivity = topRunningActivityLocked(null);
            }
        }
        return resumedActivity;
    
private com.android.server.am.ActivityManagerService$ServiceLookupResultretrieveServiceLocked(android.content.Intent service, java.lang.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 voidretrieveSettings()

        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 voidrevokeUriPermission(android.app.IApplicationThread caller, android.net.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);
        }
    
private voidrevokeUriPermissionLocked(int callingUid, android.net.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--;
                }
            }
        }
    
private voidsaveLocaleLocked(java.util.Locale l, boolean isDiff, boolean isPersist)
Save the locale. You must be inside a synchronized (this) block.

        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());
        }
    
private static booleanscanArgs(java.lang.String[] args, java.lang.String value)
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

        if (args != null) {
            for (String arg : args) {
                if (value.equals(arg)) {
                    return true;
                }
            }
        }
        return false;
    
final voidscheduleAppGcLocked(ProcessRecord app)
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.

        long now = SystemClock.uptimeMillis();
        if ((app.lastRequestedGc+5000) > now) {
            return;
        }
        if (!mProcessesToGc.contains(app)) {
            mProcessesToGc.add(app);
            scheduleAppGcsLocked();
        }
    
final voidscheduleAppGcsLocked()
Schedule the execution of all pending app GCs.

        mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
        Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
        mHandler.sendMessageDelayed(msg, GC_TIMEOUT);
    
private final voidscheduleBroadcastsLocked()

        if (DEBUG_BROADCAST) Log.v(TAG, "Schedule broadcasts: current="
                + mBroadcastsScheduled);

        if (mBroadcastsScheduled) {
            return;
        }
        mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
        mBroadcastsScheduled = true;
    
private final voidscheduleServiceRestartLocked(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);
    
public static com.android.server.am.ActivityManagerServiceself()

        return mSelf;
    
voidsendActivityResultLocked(int callingUid, HistoryRecord r, java.lang.String resultWho, int requestCode, int resultCode, android.content.Intent data)


        if (callingUid > 0) {
            grantUriPermissionFromIntentLocked(callingUid, r.packageName,
                    data, r);
        }

        if (DEBUG_RESULTS) Log.v(TAG, "Send activity result to " + r
                + " : who=" + resultWho + " req=" + requestCode
                + " res=" + resultCode + " data=" + data);
        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);
    
final voidsendPendingThumbnail(HistoryRecord r, android.os.IBinder token, android.graphics.Bitmap thumbnail, java.lang.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);
                }
            }
        }
    
private final voidsendServiceArgsLocked(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--;
            }
        }
    
public voidserviceDoneExecuting(android.os.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 voidserviceDoneExecutingLocked(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);
        }
    
voidserviceTimeout(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);
            }
        }
    
public voidsetActivityWatcher(android.app.IActivityWatcher watcher)

        enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                "setActivityWatcher()");
        synchronized (this) {
            mWatcher = watcher;
        }
    
public voidsetAlwaysFinish(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 voidsetDebugApp(java.lang.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);
            }
        }
    
private final voidsetFocusedActivityLocked(HistoryRecord r)

        if (mFocusedActivity != r) {
            mFocusedActivity = r;
            mWindowManager.setFocusedApp(r, true);
        }
    
public voidsetPersistent(android.os.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 voidsetProcessForeground(android.os.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();
            }
        }
    
public voidsetProcessLimit(int max)

        enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
                "setProcessLimit()");
        mProcessLimit = max;
    
public voidsetRequestedOrientation(android.os.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(
                    mConfiguration,
                    r.mayFreezeScreenLocked(r.app) ? r : null);
            if (config != null) {
                r.frozenBeforeDestroy = true;
                if (!updateConfigurationLocked(config, r)) {
                    resumeTopActivityLocked(null);
                }
            }
            Binder.restoreCallingIdentity(origId);
        }
    
public voidsetServiceForeground(android.content.ComponentName className, android.os.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 static voidsetSystemProcess()


        
        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 voidsetWindowManager(com.android.server.WindowManagerService wm)

        mWindowManager = wm;
    
public voidshowWaitingForDebugger(android.app.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 voidsignalPersistentProcesses(int sig)
This method sends the specified signal to each of the persistent apps

        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);
                }
            }
        }
    
voidskipCurrentReceiverLocked(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 final intstartActivity(android.app.IApplicationThread caller, android.content.Intent intent, java.lang.String resolvedType, android.net.Uri[] grantedUriPermissions, int grantedMode, android.os.IBinder resultTo, java.lang.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");
        }

        final boolean componentSpecified = intent.getComponent() != null;
        
        // 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, componentSpecified);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    
final intstartActivityInPackage(int uid, android.content.Intent intent, java.lang.String resolvedType, android.os.IBinder resultTo, java.lang.String resultWho, int requestCode, boolean onlyIfNeeded)

        final boolean componentSpecified = intent.getComponent() != null;
        
        // 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, componentSpecified);
        }
    
private final voidstartActivityLocked(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);
    
private final intstartActivityLocked(android.app.IApplicationThread caller, android.content.Intent intent, java.lang.String resolvedType, android.net.Uri[] grantedUriPermissions, int grantedMode, android.content.pm.ActivityInfo aInfo, android.os.IBinder resultTo, java.lang.String resultWho, int requestCode, int callingPid, int callingUid, boolean onlyIfNeeded, boolean componentSpecified)

        Log.i(TAG, "Starting activity: " + intent);

        HistoryRecord sourceRecord = null;
        HistoryRecord resultRecord = null;
        if (resultTo != null) {
            int index = indexOfTokenLocked(resultTo, false);
            if (DEBUG_RESULTS) 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, componentSpecified);
        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;
    
voidstartAppProblemLocked(ProcessRecord app)

        skipCurrentReceiverLocked(app);
    
public booleanstartInstrumentation(android.content.ComponentName className, java.lang.String profileFile, int flags, android.os.Bundle arguments, android.app.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;
    
public booleanstartNextMatchingActivity(android.os.IBinder callingActivity, android.content.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, false);
            Binder.restoreCallingIdentity(origId);

            r.finishing = wasFinishing;
            if (res != START_SUCCESS) {
                return false;
            }
            return true;
        }
    
private final voidstartPausingLocked(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 ProcessRecordstartProcessLocked(java.lang.String processName, android.content.pm.ApplicationInfo info, boolean knownToBeDead, int intentFlags, java.lang.String hostingType, android.content.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 voidstartProcessLocked(ProcessRecord app, java.lang.String hostingType, java.lang.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);
        }
    
public final voidstartRunning(java.lang.String pkg, java.lang.String cls, java.lang.String action, java.lang.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();
    
public android.content.ComponentNamestartService(android.app.IApplicationThread caller, android.content.Intent service, java.lang.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;
        }
    
android.content.ComponentNamestartServiceInPackage(int uid, android.content.Intent service, java.lang.String resolvedType)

        synchronized(this) {
            final long origId = Binder.clearCallingIdentity();
            ComponentName res = startServiceLocked(null, service,
                    resolvedType, -1, uid);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    
android.content.ComponentNamestartServiceLocked(android.app.IApplicationThread caller, android.content.Intent service, java.lang.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;
        }
    
private final voidstartSpecificActivityLocked(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 voidstopActivityLocked(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);
                }
            }
        }
    
public intstopService(android.app.IApplicationThread caller, android.content.Intent service, java.lang.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 booleanstopServiceToken(android.content.ComponentName className, android.os.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 voidsystemReady()

        // 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);
        }
    
public booleantestIsSystemReady()

        // no need to synchronize(this) just to read & return the value
        return mSystemReady;
    
private final HistoryRecordtopRunningActivityLocked(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;
    
private final HistoryRecordtopRunningActivityLocked(android.os.IBinder token, int taskId)
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.

        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 voidtrimApplications()

        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--;
                    }
                }
            }
        }
    
public voidunbindFinished(android.os.IBinder token, android.content.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 booleanunbindService(android.app.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 final voidunbroadcastIntent(android.app.IApplicationThread caller, android.content.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;
                    }
                }
            }
        }
    
public voidunhandledBack()

        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);
            }
        }
    
private final voiduninstallPackageLocked(java.lang.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);
    
public voidunregisterReceiver(android.app.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);
    
private final booleanunscheduleServiceRestartLocked(ServiceRecord r)

        if (r.restartDelay == 0) {
            return false;
        }
        r.resetRestartCounter();
        mRestartingServices.remove(r);
        mHandler.removeCallbacks(r.restarter);
        return true;
    
public voidupdateConfiguration(android.content.res.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);
        }
    
public booleanupdateConfigurationLocked(android.content.res.Configuration values, HistoryRecord starting)
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 starting is being destroyed to match the new configuration.

        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;
    
voidupdateCpuStats()

        synchronized (mProcessStatsThread) {
            final long now = SystemClock.uptimeMillis();
            if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
                mProcessStatsThread.notify();
            }
        }
    
voidupdateCpuStatsNow()

        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();
                }
            }
        }
    
private final voidupdateLRUListLocked(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 booleanupdateLRUListLocked(HistoryRecord r)

        final boolean hadit = mLRUActivities.remove(r);
        mLRUActivities.add(r);
        return hadit;
    
private final booleanupdateOomAdjLocked(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 booleanupdateOomAdjLocked(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 booleanupdateOomAdjLocked()

        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;
    
public voidupdateServiceForegroundLocked(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();
            }
        }
    
private voidupdateUsageStats(HistoryRecord resumedComponent, boolean resumed)

        if (resumed) {
            mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
        } else {
            mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
        }
    
public voidwakingUp()

        synchronized(this) {
            if (mGoingToSleep.isHeld()) {
                mGoingToSleep.release();
            }
            mWindowManager.setEventDispatching(true);
            mSleeping = false;
            resumeTopActivityLocked(null);
        }