Project: cornerstone
/*
 * Copyright (C) 2006-2008 The Android Open Source Project 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */
 
package com.android.server.am; 
 
import com.android.internal.R; 
import com.android.internal.os.BatteryStatsImpl; 
import com.android.internal.os.ProcessStats; 
import com.android.server.AttributeCache; 
import com.android.server.IntentResolver; 
import com.android.server.ProcessMap; 
import com.android.server.SystemServer; 
import com.android.server.Watchdog; 
import com.android.server.am.ActivityStack.ActivityState; 
import com.android.server.wm.WindowManagerService; 
import com.android.server.wm.WindowManagerService.Cornerstone_State; 
 
import dalvik.system.Zygote; 
 
import android.app.Activity; 
import android.app.ActivityManager; 
import android.app.ActivityManagerNative; 
import android.app.ActivityThread; 
import android.app.AlertDialog; 
import android.app.AppGlobals; 
import android.app.ApplicationErrorReport; 
import android.app.Dialog; 
import android.app.IActivityController; 
import android.app.IActivityManager; 
import android.app.IActivityWatcher; 
import android.app.IApplicationThread; 
import android.app.IInstrumentationWatcher; 
import android.app.INotificationManager; 
import android.app.IProcessObserver; 
import android.app.IServiceConnection; 
import android.app.IThumbnailReceiver; 
import android.app.Instrumentation; 
import android.app.ICornerstoneManager; 
import android.app.Notification; 
import android.app.NotificationManager; 
import android.app.PendingIntent; 
import android.app.Service; 
import android.app.backup.IBackupManager; 
import android.content.ActivityNotFoundException; 
import android.content.BroadcastReceiver; 
import android.content.ComponentCallbacks2; 
import android.content.ComponentName; 
import android.content.ContentResolver; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.content.IIntentReceiver; 
import android.content.IIntentSender; 
import android.content.IntentSender; 
import android.content.pm.ActivityInfo; 
import android.content.pm.ApplicationInfo; 
import android.content.pm.ConfigurationInfo; 
import android.content.pm.IPackageDataObserver; 
import android.content.pm.IPackageManager; 
import android.content.pm.InstrumentationInfo; 
import android.content.pm.PackageInfo; 
import android.content.pm.PackageManager; 
import android.content.pm.PathPermission; 
import android.content.pm.ProviderInfo; 
import android.content.pm.ResolveInfo; 
import android.content.pm.ServiceInfo; 
import android.content.pm.PackageManager.NameNotFoundException; 
import android.content.res.CompatibilityInfo; 
import android.content.res.Configuration; 
import android.content.res.Resources; 
import android.content.res.XmlResourceParser; 
import android.graphics.Bitmap; 
import android.net.Proxy; 
import android.net.ProxyProperties; 
import android.net.Uri; 
import android.os.Binder; 
import android.os.Build; 
import android.os.Bundle; 
import android.os.Debug; 
import android.os.DropBoxManager; 
import android.os.Environment; 
import android.os.FileObserver; 
import android.os.FileUtils; 
import android.os.Handler; 
import android.os.IBinder; 
import android.os.IPermissionController; 
import android.os.Looper; 
import android.os.Message; 
import android.os.Parcel; 
import android.os.ParcelFileDescriptor; 
import android.os.Process; 
import android.os.RemoteCallbackList; 
import android.os.RemoteException; 
import android.os.ServiceManager; 
import android.os.StrictMode; 
import android.os.SystemClock; 
import android.os.SystemProperties; 
import android.provider.Settings; 
import android.util.EventLog; 
import android.util.Pair; 
import android.util.Slog; 
import android.util.Log; 
import android.util.PrintWriterPrinter; 
import android.util.SparseArray; 
import android.util.TimeUtils; 
import android.view.Gravity; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.WindowManager; 
import android.view.WindowManagerPolicy; 
 
import java.io.BufferedInputStream; 
import java.io.BufferedOutputStream; 
import java.io.BufferedReader; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.File; 
import java.io.FileDescriptor; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.io.StringWriter; 
import java.lang.IllegalStateException; 
import java.lang.ref.WeakReference; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.Comparator; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.Iterator; 
import java.util.List; 
import java.util.Locale; 
import java.util.Map; 
import java.util.Set; 
import java.util.concurrent.atomic.AtomicBoolean; 
import java.util.concurrent.atomic.AtomicLong; 
 
import org.xmlpull.v1.XmlPullParser; 
import org.xmlpull.v1.XmlPullParserException; 
 
public final class ActivityManagerService extends ActivityManagerNative 
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { 
    static final String TAG = "ActivityManager"
    static final boolean DEBUG = false
    static final boolean localLOGV = DEBUG; 
    static final boolean DEBUG_CORNERSTONE = localLOGV || false
    static final boolean DEBUG_SWITCH = localLOGV || false
    static final boolean DEBUG_TASKS = localLOGV || false
    static final boolean DEBUG_PAUSE = localLOGV || false
    static final boolean DEBUG_OOM_ADJ = localLOGV || false
    static final boolean DEBUG_TRANSITION = localLOGV || false
    static final boolean DEBUG_BROADCAST = localLOGV || false
    static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false
    static final boolean DEBUG_SERVICE = localLOGV || false
    static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false
    static final boolean DEBUG_VISBILITY = localLOGV || false
    static final boolean DEBUG_PROCESSES = localLOGV || true
    static final boolean DEBUG_PROVIDER = localLOGV || false
    static final boolean DEBUG_URI_PERMISSION = localLOGV || false
    static final boolean DEBUG_USER_LEAVING = localLOGV || false
    static final boolean DEBUG_RESULTS = localLOGV || false
    static final boolean DEBUG_BACKUP = localLOGV || false
    static final boolean DEBUG_CONFIGURATION = localLOGV || true
    static final boolean DEBUG_POWER = localLOGV || false
    static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false
    static final boolean VALIDATE_TOKENS = false
    static final boolean SHOW_ACTIVITY_START_TIME = true
     
    // Control over CPU and battery monitoring. 
    static final long BATTERY_STATS_TIME = 30*60*1000;      // write battery stats every 30 minutes. 
    static final boolean MONITOR_CPU_USAGE = true
    static final long MONITOR_CPU_MIN_TIME = 5*1000;        // don't sample cpu less than every 5 seconds. 
    static final long MONITOR_CPU_MAX_TIME = 0x0fffffff;    // wait possibly forever for next cpu sample. 
    static final boolean MONITOR_THREAD_CPU_USAGE = false
 
    // The flags that are set for all calls we make to the package manager. 
    static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES; 
     
    private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"
 
    // Maximum number of recent tasks that we can remember. 
    static final int MAX_RECENT_TASKS = 20
     
    // Amount of time after a call to stopAppSwitches() during which we will 
    // prevent further untrusted switches from happening. 
    static final long APP_SWITCH_DELAY_TIME = 5*1000
 
    // How long we wait for a launched process to attach to the activity manager 
    // before we decide it's never going to come up for real. 
    static final int PROC_START_TIMEOUT = 10*1000
 
    // How long we wait for a launched process to attach to the activity manager 
    // before we decide it's never going to come up for real, when the process was 
    // started with a wrapper for instrumentation (such as Valgrind) because it 
    // could take much longer than usual. 
    static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000
 
    // How long to wait after going idle before forcing apps to GC. 
    static final int GC_TIMEOUT = 5*1000
 
    // The minimum amount of time between successive GC requests for a process. 
    static final int GC_MIN_INTERVAL = 60*1000
 
    // The rate at which we check for apps using excessive power -- 15 mins. 
    static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000
 
    // The minimum sample duration we will allow before deciding we have 
    // enough data on wake locks to start killing things. 
    static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000
 
    // The minimum sample duration we will allow before deciding we have 
    // enough data on CPU usage to start killing things. 
    static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000
 
    // How long we allow a receiver to run before giving up on it. 
    static final int BROADCAST_TIMEOUT = 10*1000
 
    // How long we wait for a service to finish executing. 
    static final int SERVICE_TIMEOUT = 20*1000
 
    // How long a service needs to be running until restarting its process 
    // is no longer considered to be a relaunch of the service. 
    static final int SERVICE_RESTART_DURATION = 5*1000
 
    // How long a service needs to be running until it will start back at 
    // SERVICE_RESTART_DURATION after being killed. 
    static final int SERVICE_RESET_RUN_DURATION = 60*1000
 
    // Multiplying factor to increase restart duration time by, for each time 
    // a service is killed before it has run for SERVICE_RESET_RUN_DURATION. 
    static final int SERVICE_RESTART_DURATION_FACTOR = 4
     
    // The minimum amount of time between restarting services that we allow. 
    // That is, when multiple services are restarting, we won't allow each 
    // to restart less than this amount of time from the last one. 
    static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000
 
    // Maximum amount of time for there to be no activity on a service before 
    // we consider it non-essential and allow its process to go on the 
    // LRU background list. 
    static final int MAX_SERVICE_INACTIVITY = 30*60*1000
     
    // How long we wait until we timeout on key dispatching. 
    static final int KEY_DISPATCHING_TIMEOUT = 5*1000
 
    // How long we wait until we timeout on key dispatching during instrumentation. 
    static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000
 
    static final int MY_PID = Process.myPid(); 
     
    static final String[] EMPTY_STRING_ARRAY = new String[0]; 
 
    public ActivityStack mMainStack; 
 
    /**
     * Author: Onskreen 
     * Date: 12/01/2011 
     * 
     * Stack containing the cornerstone app itself 
     */
 
    public ActivityStack mCornerstoneStack; 
    //TODO Hardcoding package name to recognized cornerstone app. should be upgraded so can be recognized with any package. 
    String mCornerstoneAppPackageName; 
    String mCornerstoneLauncherAppPackageName; 
    String mCornerstoneLauncherClassName; 
 
    /**
     * Author: Onskreen 
     * Date: 10/02/2011 
     * 
     * Stacks containing the cornerstone panels 
     */
 
    public ArrayList<ActivityStack> mCornerstonePanelStacks = new ArrayList<ActivityStack>(); 
    /**
     * Author: Onskreen 
     * Date: 10/02/2011 
     * 
     * Maximum number of allowed panels in the cornerstone. It's not clear whether this should 
     * be hardcoded here or variable and come from the cornerstone app? 
     */
 
    int mMaxNumCornerstonePanels = 2
 
    /**
     * Author: Onskreen 
     * Date: 10/02/2011 
     * 
     * Simplistic method of knowing which cs panel stack to put new apps. Will have to be retrieved 
     * from WMS based on api. 
     */
 
    int mCornerstonePanelsCreated = 0
 
    /**
     * Author: Onskreen 
     * Date: 10/02/2011 
     * 
     * Constants used in searching for tasks in various stacks. Positive numbers 
     * will indicate the index of the panel the task resides in. 
     * 
     */
 
    static final int NO_STACK = -1
    static final int MAIN_STACK = -2
    static final int CORNERSTONE_STACK = -3
 
    public enum Cornerstone_Transitions{ 
  OPENING,    //Running and opening 
  CLOSING,    //Running and closing 
  LAUNCHING,    //Launching CS 
  TERMINATING,   //Exiting CS 
  NONE     //Nothing 
    } 
    public Cornerstone_Transitions mCornerstoneTransition = Cornerstone_Transitions.NONE; 
 
    /**
     * Description of a request to start a new activity, which has been held 
     * due to app switches being disabled. 
     */
 
    static class PendingActivityLaunch { 
        ActivityRecord r; 
        ActivityRecord sourceRecord; 
        Uri[] grantedUriPermissions; 
        int grantedMode; 
        boolean onlyIfNeeded; 
    } 
     
    final ArrayList<PendingActivityLaunch> mPendingActivityLaunches 
            = new ArrayList<PendingActivityLaunch>(); 
     
    /**
     * List of all active broadcasts that are to be executed immediately 
     * (without waiting for another broadcast to finish).  Currently this only 
     * contains broadcasts to registered receivers, to avoid spinning up 
     * a bunch of processes to execute IntentReceiver components. 
     */
 
    final ArrayList<BroadcastRecord> mParallelBroadcasts 
            = new ArrayList<BroadcastRecord>(); 
 
    /**
     * List of all active broadcasts that are to be executed one at a time. 
     * The object at the top of the list is the currently activity broadcasts; 
     * those after it are waiting for the top to finish.. 
     */
 
    final ArrayList<BroadcastRecord> mOrderedBroadcasts 
            = new ArrayList<BroadcastRecord>(); 
 
    /**
     * Historical data of past broadcasts, for debugging. 
     */
 
    static final int MAX_BROADCAST_HISTORY = 25
    final BroadcastRecord[] mBroadcastHistory 
            = new BroadcastRecord[MAX_BROADCAST_HISTORY]; 
 
    /**
     * Set when we current have a BROADCAST_INTENT_MSG in flight. 
     */
 
    boolean mBroadcastsScheduled = false
 
    /**
     * Activity we have told the window manager to have key focus. 
     */
 
    ActivityRecord mFocusedActivity = null
    /**
     * List of intents that were used to start the most recent tasks. 
     */
 
    final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>(); 
 
    /**
     * Process management. 
     */
 
    final ProcessList mProcessList = new ProcessList(); 
 
    /**
     * All of the applications we currently have running organized by name. 
     * The keys are strings of the application package name (as 
     * returned by the package manager), and the keys are ApplicationRecord 
     * objects. 
     */
 
    final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>(); 
 
    /**
     * The currently running heavy-weight process, if any. 
     */
 
    ProcessRecord mHeavyWeightProcess = null
     
    /**
     * The last time that various processes have crashed. 
     */
 
    final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>(); 
 
    /**
     * Set of applications that we consider to be bad, and will reject 
     * incoming broadcasts from (which the user has no control over). 
     * Processes are added to this set when they have crashed twice within 
     * a minimum amount of time; they are removed from it when they are 
     * later restarted (hopefully due to some user action).  The value is the 
     * time it was added to the list. 
     */
 
    final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>(); 
 
    /**
     * All of the processes we currently have running organized by pid. 
     * The keys are the pid running the application. 
     * 
     * <p>NOTE: This object is protected by its own lock, NOT the global 
     * activity manager lock! 
     */
 
    final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>(); 
 
    /**
     * All of the processes that have been forced to be foreground.  The key 
     * is the pid of the caller who requested it (we hold a death 
     * link on it). 
     */
 
    abstract class ForegroundToken implements IBinder.DeathRecipient { 
        int pid; 
        IBinder token; 
    } 
    final SparseArray<ForegroundToken> mForegroundProcesses 
            = new SparseArray<ForegroundToken>(); 
     
    /**
     * List of records for processes that someone had tried to start before the 
     * system was ready.  We don't start them at that point, but ensure they 
     * are started by the time booting is complete. 
     */
 
    final ArrayList<ProcessRecord> mProcessesOnHold 
            = new ArrayList<ProcessRecord>(); 
 
    /**
     * List of persistent applications that are in the process 
     * of being started. 
     */
 
    final ArrayList<ProcessRecord> mPersistentStartingProcesses 
            = new ArrayList<ProcessRecord>(); 
 
    /**
     * Processes that are being forcibly torn down. 
     */
 
    final ArrayList<ProcessRecord> mRemovedProcesses 
            = new ArrayList<ProcessRecord>(); 
 
    /**
     * List of running applications, sorted by recent usage. 
     * The first entry in the list is the least recently used. 
     * It contains ApplicationRecord objects.  This list does NOT include 
     * any persistent application records (since we never want to exit them). 
     */
 
    final ArrayList<ProcessRecord> mLruProcesses 
            = new ArrayList<ProcessRecord>(); 
 
    /**
     * List of processes that should gc as soon as things are idle. 
     */
 
    final ArrayList<ProcessRecord> mProcessesToGc 
            = new ArrayList<ProcessRecord>(); 
 
    /**
     * This is the process holding what we currently consider to be 
     * the "home" activity. 
     */
 
    ProcessRecord mHomeProcess; 
     
    /**
     * This is the process holding the activity the user last visited that 
     * is in a different process from the one they are currently in. 
     */
 
    ProcessRecord mPreviousProcess; 
 
    /**
     * The time at which the previous process was last visible. 
     */
 
    long mPreviousProcessVisibleTime; 
 
    /**
     * Packages that the user has asked to have run in screen size 
     * compatibility mode instead of filling the screen. 
     */
 
    final CompatModePackages mCompatModePackages; 
 
    /**
     * Set of PendingResultRecord objects that are currently active. 
     */
 
    final HashSet mPendingResultRecords = new HashSet(); 
 
    /**
     * Set of IntentSenderRecord objects that are currently active. 
     */
 
    final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords 
            = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>(); 
 
    /**
     * Fingerprints (hashCode()) of stack traces that we've 
     * already logged DropBox entries for.  Guarded by itself.  If 
     * something (rogue user app) forces this over 
     * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared. 
     */
 
    private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>(); 
    private static final int MAX_DUP_SUPPRESSED_STACKS = 5000
 
    /**
     * Strict Mode background batched logging state. 
     * 
     * The string buffer is guarded by itself, and its lock is also 
     * used to determine if another batched write is already 
     * in-flight. 
     */
 
    private final StringBuilder mStrictModeBuffer = new StringBuilder(); 
 
    /**
     * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler. 
     */
 
    private boolean mPendingBroadcastTimeoutMessage; 
 
    /**
     * Intent broadcast that we have tried to start, but are 
     * waiting for its application's process to be created.  We only 
     * need one (instead of a list) because we always process broadcasts 
     * one at a time, so no others can be started while waiting for this 
     * one. 
     */
 
    BroadcastRecord mPendingBroadcast = null
 
    /**
     * The receiver index that is pending, to restart the broadcast if needed. 
     */
 
    int mPendingBroadcastRecvIndex; 
 
    /**
     * Keeps track of all IIntentReceivers that have been registered for 
     * broadcasts.  Hash keys are the receiver IBinder, hash value is 
     * a ReceiverList. 
     */
 
    final HashMap mRegisteredReceivers = new HashMap(); 
 
    /**
     * Resolver for broadcast intents to registered receivers. 
     * Holds BroadcastFilter (subclass of IntentFilter). 
     */
 
    final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver 
            = new IntentResolver<BroadcastFilter, BroadcastFilter>() { 
        @Override 
        protected boolean allowFilterResult( 
                BroadcastFilter filter, List<BroadcastFilter> dest) { 
            IBinder target = filter.receiverList.receiver.asBinder(); 
            for (int i=dest.size()-1; i>=0; i--) { 
                if (dest.get(i).receiverList.receiver.asBinder() == target) { 
                    return false
                } 
            } 
            return true
        } 
 
        @Override 
        protected String packageForFilter(BroadcastFilter filter) { 
            return filter.packageName; 
        } 
    }; 
 
    /**
     * State of all active sticky broadcasts.  Keys are the action of the 
     * sticky Intent, values are an ArrayList of all broadcasted intents with 
     * that action (which should usually be one). 
     */
 
    final HashMap<String, ArrayList<Intent>> mStickyBroadcasts = 
            new HashMap<String, ArrayList<Intent>>(); 
 
    /**
     * All currently running services. 
     */
 
    final HashMap<ComponentName, ServiceRecord> mServices = 
        new HashMap<ComponentName, ServiceRecord>(); 
 
    /**
     * All currently running services indexed by the Intent used to start them. 
     */
 
    final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent = 
        new HashMap<Intent.FilterComparison, ServiceRecord>(); 
 
    /**
     * All currently bound service connections.  Keys are the IBinder of 
     * the client's IServiceConnection. 
     */
 
    final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections 
            = new HashMap<IBinder, ArrayList<ConnectionRecord>>(); 
 
    /**
     * List of services that we have been asked to start, 
     * but haven't yet been able to.  It is used to hold start requests 
     * while waiting for their corresponding application thread to get 
     * going. 
     */
 
    final ArrayList<ServiceRecord> mPendingServices 
            = new ArrayList<ServiceRecord>(); 
 
    /**
     * List of services that are scheduled to restart following a crash. 
     */
 
    final ArrayList<ServiceRecord> mRestartingServices 
            = new ArrayList<ServiceRecord>(); 
 
    /**
     * List of services that are in the process of being stopped. 
     */
 
    final ArrayList<ServiceRecord> mStoppingServices 
            = new ArrayList<ServiceRecord>(); 
 
    /**
     * Backup/restore process management 
     */
 
    String mBackupAppName = null
    BackupRecord mBackupTarget = null
 
    /**
     * List of PendingThumbnailsRecord objects of clients who are still 
     * waiting to receive all of the thumbnails for a task. 
     */
 
    final ArrayList mPendingThumbnails = new ArrayList(); 
 
    /**
     * List of HistoryRecord objects that have been finished and must 
     * still report back to a pending thumbnail receiver. 
     */
 
    final ArrayList mCancelledThumbnails = new ArrayList(); 
 
    /**
     * All of the currently running global content providers.  Keys are a 
     * string containing the provider name and values are a 
     * ContentProviderRecord object containing the data about it.  Note 
     * that a single provider may be published under multiple names, so 
     * there may be multiple entries here for a single one in mProvidersByClass. 
     */
 
    final HashMap<String, ContentProviderRecord> mProvidersByName 
            = new HashMap<String, ContentProviderRecord>(); 
 
    /**
     * All of the currently running global content providers.  Keys are a 
     * string containing the provider's implementation class and values are a 
     * ContentProviderRecord object containing the data about it. 
     */
 
    final HashMap<ComponentName, ContentProviderRecord> mProvidersByClass 
            = new HashMap<ComponentName, ContentProviderRecord>(); 
 
    /**
     * List of content providers who have clients waiting for them.  The 
     * application is currently being launched and the provider will be 
     * removed from this list once it is published. 
     */
 
    final ArrayList<ContentProviderRecord> mLaunchingProviders 
            = new ArrayList<ContentProviderRecord>(); 
 
    /**
     * Global set of specific Uri permissions that have been granted. 
     */
 
    final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions 
            = new SparseArray<HashMap<Uri, UriPermission>>(); 
 
    CoreSettingsObserver mCoreSettingsObserver; 
 
    /**
     * Thread-local storage used to carry caller permissions over through 
     * indirect content-provider access. 
     * @see #ActivityManagerService.openContentUri() 
     */
 
    private class Identity { 
        public int pid; 
        public int uid; 
 
        Identity(int _pid, int _uid) { 
            pid = _pid; 
            uid = _uid; 
        } 
    } 
    private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>(); 
 
    /**
     * All information we have collected about the runtime performance of 
     * any user id that can impact battery performance. 
     */
 
    final BatteryStatsService mBatteryStatsService; 
     
    /**
     * information about component usage 
     */
 
    final UsageStatsService mUsageStatsService; 
 
    /**
     * Current configuration information.  HistoryRecord objects are given 
     * a reference to this object to indicate which configuration they are 
     * currently running in, so this object must be kept immutable. 
     */
 
    Configuration mConfiguration = new Configuration(); 
 
    /**
     * Current sequencing integer of the configuration, for skipping old 
     * configurations. 
     */
 
    int mConfigurationSeq = 0
     
    /**
     * Hardware-reported OpenGLES version. 
     */
 
    final int GL_ES_VERSION; 
 
    /**
     * List of initialization arguments to pass to all processes when binding applications to them. 
     * For example, references to the commonly used services. 
     */
 
    HashMap<String, IBinder> mAppBindArgs; 
 
    /**
     * Temporary to avoid allocations.  Protected by main lock. 
     */
 
    final StringBuilder mStringBuilder = new StringBuilder(256); 
     
    /**
     * Used to control how we initialize the service. 
     */
 
    boolean mStartRunning = false
    ComponentName mTopComponent; 
    String mTopAction; 
    String mTopData; 
    boolean mProcessesReady = false
    boolean mSystemReady = false
    boolean mBooting = false
    boolean mWaitingUpdate = false
    boolean mDidUpdate = false
    boolean mOnBattery = false
    boolean mLaunchWarningShown = false
 
    Context mContext; 
 
    int mFactoryTest; 
 
    boolean mCheckedForSetup; 
     
    /**
     * The time at which we will allow normal application switches again, 
     * after a call to {@link #stopAppSwitches()}. 
     */
 
    long mAppSwitchesAllowedTime; 
 
    /**
     * This is set to true after the first switch after mAppSwitchesAllowedTime 
     * is set; any switches after that will clear the time. 
     */
 
    boolean mDidAppSwitch; 
     
    /**
     * Last time (in realtime) at which we checked for power usage. 
     */
 
    long mLastPowerCheckRealtime; 
 
    /**
     * Last time (in uptime) at which we checked for power usage. 
     */
 
    long mLastPowerCheckUptime; 
 
    /**
     * Set while we are wanting to sleep, to prevent any 
     * activities from being started/resumed. 
     */
 
    boolean mSleeping = false
 
    /**
     * Set if we are shutting down the system, similar to sleeping. 
     */
 
    boolean mShuttingDown = false
 
    /**
     * Task identifier that activities are currently being started 
     * in.  Incremented each time a new task is created. 
     * todo: Replace this with a TokenSpace class that generates non-repeating 
     * integers that won't wrap. 
     */
 
    int mCurTask = 1
 
    /**
     * Current sequence id for oom_adj computation traversal. 
     */
 
    int mAdjSeq = 0
 
    /**
     * Current sequence id for process LRU updating. 
     */
 
    int mLruSeq = 0
 
    /**
     * Keep track of the number of service processes we last found, to 
     * determine on the next iteration which should be B services. 
     */
 
    int mNumServiceProcs = 0
    int mNewNumServiceProcs = 0
 
    /**
     * System monitoring: number of processes that died since the last 
     * N procs were started. 
     */
 
    int[] mProcDeaths = new int[20]; 
     
    /**
     * This is set if we had to do a delayed dexopt of an app before launching 
     * it, to increasing the ANR timeouts in that case. 
     */
 
    boolean mDidDexOpt; 
     
    String mDebugApp = null
    boolean mWaitForDebugger = false
    boolean mDebugTransient = false
    String mOrigDebugApp = null
    boolean mOrigWaitForDebugger = false
    boolean mAlwaysFinishActivities = false
    IActivityController mController = null
    String mProfileApp = null
    ProcessRecord mProfileProc = null
    String mProfileFile; 
    ParcelFileDescriptor mProfileFd; 
    int mProfileType = 0
    boolean mAutoStopProfiler = false
 
   /**
    * Author: Onskreen 
    * Date: 28/02/2011 
    * 
    * ICornerstoneManager object 
    */
 
    ICornerstoneManager mCornerstoneManager = null
 
   /**
    * Author: Onskreen 
    * Date: 16/07/2011 
    * 
    * Activity stack kill setting Flag 
    */
 
    boolean mActivityStackExiting; 
 
    final RemoteCallbackList<IActivityWatcher> mWatchers 
            = new RemoteCallbackList<IActivityWatcher>(); 
 
    final RemoteCallbackList<IProcessObserver> mProcessObservers 
            = new RemoteCallbackList<IProcessObserver>(); 
 
    /**
     * Callback of last caller to {@link #requestPss}. 
     */
 
    Runnable mRequestPssCallback; 
 
    /**
     * Remaining processes for which we are waiting results from the last 
     * call to {@link #requestPss}. 
     */
 
    final ArrayList<ProcessRecord> mRequestPssList 
            = new ArrayList<ProcessRecord>(); 
     
    /**
     * Runtime statistics collection thread.  This object's lock is used to 
     * protect all related state. 
     */
 
    final Thread mProcessStatsThread; 
     
    /**
     * Used to collect process stats when showing not responding dialog. 
     * Protected by mProcessStatsThread. 
     */
 
    final ProcessStats mProcessStats = new ProcessStats( 
            MONITOR_THREAD_CPU_USAGE); 
    final AtomicLong mLastCpuTime = new AtomicLong(0); 
    final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true); 
 
    long mLastWriteTime = 0
 
    /**
     * Set to true after the system has finished booting. 
     */
 
    boolean mBooted = false
 
    int mProcessLimit = ProcessList.MAX_HIDDEN_APPS; 
    int mProcessLimitOverride = -1
 
    WindowManagerService mWindowManager; 
 
    static ActivityManagerService mSelf; 
    static ActivityThread mSystemThread; 
 
    private final class AppDeathRecipient implements IBinder.DeathRecipient { 
        final ProcessRecord mApp; 
        final int mPid; 
        final IApplicationThread mAppThread; 
 
        AppDeathRecipient(ProcessRecord app, int pid, 
                IApplicationThread thread) { 
            if (localLOGV) Slog.v( 
                TAG, "New death recipient " + this 
                + " for thread " + thread.asBinder()); 
            mApp = app; 
            mPid = pid; 
            mAppThread = thread; 
        } 
 
        public void binderDied() { 
            if (localLOGV) Slog.v( 
                TAG, "Death received in " + this 
                + " for thread " + mAppThread.asBinder()); 
            synchronized(ActivityManagerService.this) { 
                appDiedLocked(mApp, mPid, mAppThread); 
            } 
        } 
    } 
 
    static final int SHOW_ERROR_MSG = 1
    static final int SHOW_NOT_RESPONDING_MSG = 2
    static final int SHOW_FACTORY_ERROR_MSG = 3
    static final int UPDATE_CONFIGURATION_MSG = 4
    static final int GC_BACKGROUND_PROCESSES_MSG = 5
    static final int WAIT_FOR_DEBUGGER_MSG = 6
    static final int BROADCAST_INTENT_MSG = 7
    static final int BROADCAST_TIMEOUT_MSG = 8
    static final int SERVICE_TIMEOUT_MSG = 12
    static final int UPDATE_TIME_ZONE = 13
    static final int SHOW_UID_ERROR_MSG = 14
    static final int IM_FEELING_LUCKY_MSG = 15
    static final int PROC_START_TIMEOUT_MSG = 20
    static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21
    static final int KILL_APPLICATION_MSG = 22
    static final int FINALIZE_PENDING_INTENT_MSG = 23
    static final int POST_HEAVY_NOTIFICATION_MSG = 24
    static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25
    static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26
    static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27
    static final int CLEAR_DNS_CACHE = 28
    static final int UPDATE_HTTP_PROXY = 29
    static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30
    static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31
    static final int DISPATCH_PROCESS_DIED = 32
    static final int REPORT_MEM_USAGE = 33
    /**
     * Author: Onskreen 
     * Date: 10/06/2011 
     * 
     * Constant to show the alert dialog when user tries to launch 
     * the multiple instances of same app (for ex, Gallery) to avoid 
     * any unwanted crashes. 
     */
 
    static final int SHOW_APP_ERROR_MSG = 34
 
    AlertDialog mUidAlert; 
    CompatModeDialog mCompatModeDialog; 
    long mLastMemUsageReportTime = 0
 
    final Handler mHandler = new Handler() { 
        //public Handler() { 
        //    if (localLOGV) Slog.v(TAG, "Handler started!"); 
        //} 
 
        public void handleMessage(Message msg) { 
            switch (msg.what) { 
            case SHOW_ERROR_MSG: { 
                HashMap data = (HashMap) msg.obj; 
                synchronized (ActivityManagerService.this) { 
                    ProcessRecord proc = (ProcessRecord)data.get("app"); 
                    if (proc != null && proc.crashDialog != null) { 
                        Slog.e(TAG, "App already has crash dialog: " + proc); 
                        return
                    } 
                    AppErrorResult res = (AppErrorResult) data.get("result"); 
                    if (!mSleeping && !mShuttingDown) { 
                        Dialog d = new AppErrorDialog(mContext, res, proc); 
                        d.show(); 
                        proc.crashDialog = d; 
                    } else { 
                        // The device is asleep, so just pretend that the user 
                        // saw a crash dialog and hit "force quit". 
                        res.set(0); 
                    } 
                } 
                 
                ensureBootCompleted(); 
            } break
            case SHOW_NOT_RESPONDING_MSG: { 
                synchronized (ActivityManagerService.this) { 
                    HashMap data = (HashMap) msg.obj; 
                    ProcessRecord proc = (ProcessRecord)data.get("app"); 
                    if (proc != null && proc.anrDialog != null) { 
                        Slog.e(TAG, "App already has anr dialog: " + proc); 
                        return
                    } 
                     
                    Intent intent = new Intent("android.intent.action.ANR"); 
                    if (!mProcessesReady) { 
                        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 
                    } 
                    broadcastIntentLocked(nullnull, intent, 
                            nullnull, 0, nullnullnull
                            falsefalse, MY_PID, Process.SYSTEM_UID); 
 
                    Dialog d = new AppNotRespondingDialog(ActivityManagerService.this
                            mContext, proc, (ActivityRecord)data.get("activity")); 
                    d.show(); 
                    proc.anrDialog = d; 
                } 
                 
                ensureBootCompleted(); 
            } break
            case SHOW_STRICT_MODE_VIOLATION_MSG: { 
                HashMap<String, Object> data = (HashMap<String, Object>) msg.obj; 
                synchronized (ActivityManagerService.this) { 
                    ProcessRecord proc = (ProcessRecord) data.get("app"); 
                    if (proc == null) { 
                        Slog.e(TAG, "App not found when showing strict mode dialog."); 
                        break
                    } 
                    if (proc.crashDialog != null) { 
                        Slog.e(TAG, "App already has strict mode dialog: " + proc); 
                        return
                    } 
                    AppErrorResult res = (AppErrorResult) data.get("result"); 
                    if (!mSleeping && !mShuttingDown) { 
                        Dialog d = new StrictModeViolationDialog(mContext, res, proc); 
                        d.show(); 
                        proc.crashDialog = d; 
                    } else { 
                        // The device is asleep, so just pretend that the user 
                        // saw a crash dialog and hit "force quit". 
                        res.set(0); 
                    } 
                } 
                ensureBootCompleted(); 
            } break
            case SHOW_FACTORY_ERROR_MSG: { 
                Dialog d = new FactoryErrorDialog( 
                    mContext, msg.getData().getCharSequence("msg")); 
                d.show(); 
                ensureBootCompleted(); 
            } break
            case UPDATE_CONFIGURATION_MSG: { 
                final ContentResolver resolver = mContext.getContentResolver(); 
                Settings.System.putConfiguration(resolver, (Configuration)msg.obj); 
            } break
            case GC_BACKGROUND_PROCESSES_MSG: { 
                synchronized (ActivityManagerService.this) { 
                    performAppGcsIfAppropriateLocked(); 
                } 
            } break
            case WAIT_FOR_DEBUGGER_MSG: { 
                synchronized (ActivityManagerService.this) { 
                    ProcessRecord app = (ProcessRecord)msg.obj; 
                    if (msg.arg1 != 0) { 
                        if (!app.waitedForDebugger) { 
                            Dialog d = new AppWaitingForDebuggerDialog( 
                                    ActivityManagerService.this
                                    mContext, app); 
                            app.waitDialog = d; 
                            app.waitedForDebugger = true
                            d.show(); 
                        } 
                    } else { 
                        if (app.waitDialog != null) { 
                            app.waitDialog.dismiss(); 
                            app.waitDialog = null
                        } 
                    } 
                } 
            } break
            case BROADCAST_INTENT_MSG: { 
                if (DEBUG_BROADCAST) Slog.v( 
                        TAG, "Received BROADCAST_INTENT_MSG"); 
                processNextBroadcast(true); 
            } break
            case BROADCAST_TIMEOUT_MSG: { 
                synchronized (ActivityManagerService.this) { 
                    broadcastTimeoutLocked(true); 
                } 
            } break
            case SERVICE_TIMEOUT_MSG: { 
                if (mDidDexOpt) { 
                    mDidDexOpt = false
                    Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG); 
                    nmsg.obj = msg.obj; 
                    mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT); 
                    return
                } 
                serviceTimeout((ProcessRecord)msg.obj); 
            } break
            case UPDATE_TIME_ZONE: { 
                synchronized (ActivityManagerService.this) { 
                    for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) { 
                        ProcessRecord r = mLruProcesses.get(i); 
                        if (r.thread != null) { 
                            try { 
                                r.thread.updateTimeZone(); 
                            } catch (RemoteException ex) { 
                                Slog.w(TAG, "Failed to update time zone for: " + r.info.processName); 
                            } 
                        } 
                    } 
                } 
            } break
            case CLEAR_DNS_CACHE: { 
                synchronized (ActivityManagerService.this) { 
                    for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) { 
                        ProcessRecord r = mLruProcesses.get(i); 
                        if (r.thread != null) { 
                            try { 
                                r.thread.clearDnsCache(); 
                            } catch (RemoteException ex) { 
                                Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName); 
                            } 
                        } 
                    } 
                } 
            } break
            case UPDATE_HTTP_PROXY: { 
                ProxyProperties proxy = (ProxyProperties)msg.obj; 
                String host = ""; 
                String port = ""; 
                String exclList = ""; 
                if (proxy != null) { 
                    host = proxy.getHost(); 
                    port = Integer.toString(proxy.getPort()); 
                    exclList = proxy.getExclusionList(); 
                } 
                synchronized (ActivityManagerService.this) { 
                    for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) { 
                        ProcessRecord r = mLruProcesses.get(i); 
                        if (r.thread != null) { 
                            try { 
                                r.thread.setHttpProxy(host, port, exclList); 
                            } catch (RemoteException ex) { 
                                Slog.w(TAG, "Failed to update http proxy for: " + 
                                        r.info.processName); 
                            } 
                        } 
                    } 
                } 
            } break
            case SHOW_UID_ERROR_MSG: { 
                // XXX This is a temporary dialog, no need to localize. 
                AlertDialog d = new BaseErrorDialog(mContext); 
                d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); 
                d.setCancelable(false); 
                d.setTitle("System UIDs Inconsistent"); 
                d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable."); 
                d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky", 
                        mHandler.obtainMessage(IM_FEELING_LUCKY_MSG)); 
                mUidAlert = d; 
                d.show(); 
            } break
            case IM_FEELING_LUCKY_MSG: { 
                if (mUidAlert != null) { 
                    mUidAlert.dismiss(); 
                    mUidAlert = null
                } 
            } break
            case PROC_START_TIMEOUT_MSG: { 
                if (mDidDexOpt) { 
                    mDidDexOpt = false
                    Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); 
                    nmsg.obj = msg.obj; 
                    mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT); 
                    return
                } 
                ProcessRecord app = (ProcessRecord)msg.obj; 
                synchronized (ActivityManagerService.this) { 
                    processStartTimedOutLocked(app); 
                } 
            } break
            case DO_PENDING_ACTIVITY_LAUNCHES_MSG: { 
                synchronized (ActivityManagerService.this) { 
                    doPendingActivityLaunchesLocked(true); 
                } 
            } break
            case KILL_APPLICATION_MSG: { 
                synchronized (ActivityManagerService.this) { 
                    int uid = msg.arg1; 
                    boolean restart = (msg.arg2 == 1); 
                    String pkg = (String) msg.obj; 
                    forceStopPackageLocked(pkg, uid, restart, falsetruefalse); 
                } 
            } break
            case FINALIZE_PENDING_INTENT_MSG: { 
                ((PendingIntentRecord)msg.obj).completeFinalize(); 
            } break
            case POST_HEAVY_NOTIFICATION_MSG: { 
                INotificationManager inm = NotificationManager.getService(); 
                if (inm == null) { 
                    return
                } 
                 
                ActivityRecord root = (ActivityRecord)msg.obj; 
                ProcessRecord process = root.app; 
                if (process == null) { 
                    return
                } 
                 
                try { 
                    Context context = mContext.createPackageContext(process.info.packageName, 0); 
                    String text = mContext.getString(R.string.heavy_weight_notification, 
                            context.getApplicationInfo().loadLabel(context.getPackageManager())); 
                    Notification notification = new Notification(); 
                    notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon; 
                    notification.when = 0; 
                    notification.flags = Notification.FLAG_ONGOING_EVENT; 
                    notification.tickerText = text; 
                    notification.defaults = 0; // please be quiet 
                    notification.sound = null
                    notification.vibrate = null
                    notification.setLatestEventInfo(context, text, 
                            mContext.getText(R.string.heavy_weight_notification_detail), 
                            PendingIntent.getActivity(mContext, 0, root.intent, 
                                    PendingIntent.FLAG_CANCEL_CURRENT)); 
                     
                    try { 
                        int[] outId = new int[1]; 
                        inm.enqueueNotification("android", R.string.heavy_weight_notification, 
                                notification, outId); 
                    } catch (RuntimeException e) { 
                        Slog.w(ActivityManagerService.TAG, 
                                "Error showing notification for heavy-weight app", e); 
                    } catch (RemoteException e) { 
                    } 
                } catch (NameNotFoundException e) { 
                    Slog.w(TAG, "Unable to create context for heavy notification", e); 
                } 
            } break
            case CANCEL_HEAVY_NOTIFICATION_MSG: { 
                INotificationManager inm = NotificationManager.getService(); 
                if (inm == null) { 
                    return
                } 
                try { 
                    inm.cancelNotification("android", 
                            R.string.heavy_weight_notification); 
                } catch (RuntimeException e) { 
                    Slog.w(ActivityManagerService.TAG, 
                            "Error canceling notification for service", e); 
                } catch (RemoteException e) { 
                } 
            } break
            case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: { 
                synchronized (ActivityManagerService.this) { 
                    checkExcessivePowerUsageLocked(true); 
                    removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); 
                    Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); 
                    sendMessageDelayed(nmsg, POWER_CHECK_DELAY); 
                } 
            } break
            case SHOW_COMPAT_MODE_DIALOG_MSG: { 
                synchronized (ActivityManagerService.this) { 
                    ActivityRecord ar = (ActivityRecord)msg.obj; 
                    if (mCompatModeDialog != null) { 
                        if (mCompatModeDialog.mAppInfo.packageName.equals( 
                                ar.info.applicationInfo.packageName)) { 
                            return
                        } 
                        mCompatModeDialog.dismiss(); 
                        mCompatModeDialog = null
                    } 
                    if (ar != null && false) { 
                        if (mCompatModePackages.getPackageAskCompatModeLocked( 
                                ar.packageName)) { 
                            int mode = mCompatModePackages.computeCompatModeLocked( 
                                    ar.info.applicationInfo); 
                            if (mode == ActivityManager.COMPAT_MODE_DISABLED 
                                    || mode == ActivityManager.COMPAT_MODE_ENABLED) { 
                                mCompatModeDialog = new CompatModeDialog( 
                                        ActivityManagerService.this, mContext, 
                                        ar.info.applicationInfo); 
                                mCompatModeDialog.show(); 
                            } 
                        } 
                    } 
                } 
                break
            } 
            case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: { 
                final int pid = msg.arg1; 
                final int uid = msg.arg2; 
                final boolean foregroundActivities = (Boolean) msg.obj; 
                dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities); 
                break
            } 
            case DISPATCH_PROCESS_DIED: { 
                final int pid = msg.arg1; 
                final int uid = msg.arg2; 
                dispatchProcessDied(pid, uid); 
                break
            } 
            case REPORT_MEM_USAGE: { 
                boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); 
                if (!isDebuggable) { 
                    return
                } 
                synchronized (ActivityManagerService.this) { 
                    long now = SystemClock.uptimeMillis(); 
                    if (now < (mLastMemUsageReportTime+5*60*1000)) { 
                        // Don't report more than every 5 minutes to somewhat 
                        // avoid spamming. 
                        return
                    } 
                    mLastMemUsageReportTime = now; 
                } 
                Thread thread = new Thread() { 
                    @Override public void run() { 
                        StringBuilder dropBuilder = new StringBuilder(1024); 
                        StringBuilder logBuilder = new StringBuilder(1024); 
                        StringWriter oomSw = new StringWriter(); 
                        PrintWriter oomPw = new PrintWriter(oomSw); 
                        StringWriter catSw = new StringWriter(); 
                        PrintWriter catPw = new PrintWriter(catSw); 
                        String[] emptyArgs = new String[] { }; 
                        StringBuilder tag = new StringBuilder(128); 
                        StringBuilder stack = new StringBuilder(128); 
                        tag.append("Low on memory -- "); 
                        dumpApplicationMemoryUsage(null, oomPw, "  ", emptyArgs, true, catPw, 
                                tag, stack); 
                        dropBuilder.append(stack); 
                        dropBuilder.append('\n'); 
                        dropBuilder.append('\n'); 
                        String oomString = oomSw.toString(); 
                        dropBuilder.append(oomString); 
                        dropBuilder.append('\n'); 
                        logBuilder.append(oomString); 
                        try { 
                            java.lang.Process proc = Runtime.getRuntime().exec(new String[] { 
                                    "procrank", }); 
                            final InputStreamReader converter = new InputStreamReader( 
                                    proc.getInputStream()); 
                            BufferedReader in = new BufferedReader(converter); 
                            String line; 
                            while (true) { 
                                line = in.readLine(); 
                                if (line == null) { 
                                    break
                                } 
                                if (line.length() > 0) { 
                                    logBuilder.append(line); 
                                    logBuilder.append('\n'); 
                                } 
                                dropBuilder.append(line); 
                                dropBuilder.append('\n'); 
                            } 
                            converter.close(); 
                        } catch (IOException e) { 
                        } 
                        synchronized (ActivityManagerService.this) { 
                            catPw.println(); 
                            dumpProcessesLocked(null, catPw, emptyArgs, 0, falsenull); 
                            catPw.println(); 
                            dumpServicesLocked(null, catPw, emptyArgs, 0, falsefalsenull); 
                            catPw.println(); 
                            dumpActivitiesLocked(null, catPw, emptyArgs, 0, falsefalsenull); 
                        } 
                        dropBuilder.append(catSw.toString()); 
                        addErrorToDropBox("lowmem", null, "system_server", null
                                null, tag.toString(), dropBuilder.toString(), nullnull); 
                        Slog.i(TAG, logBuilder.toString()); 
                        synchronized (ActivityManagerService.this) { 
                            long now = SystemClock.uptimeMillis(); 
                            if (mLastMemUsageReportTime < now) { 
                                mLastMemUsageReportTime = now; 
                            } 
                        } 
                    } 
                }; 
                thread.start(); 
                break
            } 
            /**
             * Author: Onskreen 
             * Date: 10/06/2011 
             * 
             * Show the alert dialog when user tries to launch the multiple 
             * instances of similar app. 
             */
 
            case SHOW_APP_ERROR_MSG: { 
                AlertDialog d = new BaseErrorDialog(mContext); 
                d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); 
                d.setCancelable(false); 
                d.setTitle(msg.getData().getCharSequence("title")); 
                d.setMessage(msg.getData().getCharSequence("body")); 
                d.setButton(DialogInterface.BUTTON_POSITIVE, "OK", 
                    mHandler.obtainMessage(IM_FEELING_LUCKY_MSG)); 
                mUidAlert = d; 
                d.show(); 
    break
            } 
            } 
        } 
    }; 
 
    public static void setSystemProcess() { 
        try { 
            ActivityManagerService m = mSelf; 
             
            ServiceManager.addService("activity", m); 
            ServiceManager.addService("meminfo"new MemBinder(m)); 
            ServiceManager.addService("gfxinfo"new GraphicsBinder(m)); 
            if (MONITOR_CPU_USAGE) { 
                ServiceManager.addService("cpuinfo"new CpuBinder(m)); 
            } 
            ServiceManager.addService("permission"new PermissionController(m)); 
 
            ApplicationInfo info = 
                mSelf.mContext.getPackageManager().getApplicationInfo( 
                        "android", STOCK_PM_FLAGS); 
            mSystemThread.installSystemApplicationInfo(info); 
        
            synchronized (mSelf) { 
                ProcessRecord app = mSelf.newProcessRecordLocked( 
                        mSystemThread.getApplicationThread(), info, 
                        info.processName); 
                app.persistent = true
                app.pid = MY_PID; 
                app.maxAdj = ProcessList.SYSTEM_ADJ; 
                mSelf.mProcessNames.put(app.processName, app.info.uid, app); 
                synchronized (mSelf.mPidsSelfLocked) { 
                    mSelf.mPidsSelfLocked.put(app.pid, app); 
                } 
                mSelf.updateLruProcessLocked(app, truetrue); 
            } 
        } catch (PackageManager.NameNotFoundException e) { 
            throw new RuntimeException( 
                    "Unable to find android system package", e); 
        } 
    } 
 
    public void setWindowManager(WindowManagerService wm) { 
        mWindowManager = wm; 
    } 
 
    public static final Context main(int factoryTest) { 
        AThread thr = new AThread(); 
        thr.start(); 
 
        synchronized (thr) { 
            while (thr.mService == null) { 
                try { 
                    thr.wait(); 
                } catch (InterruptedException e) { 
                } 
            } 
        } 
 
        ActivityManagerService m = thr.mService; 
        mSelf = m; 
        ActivityThread at = ActivityThread.systemMain(); 
        mSystemThread = at; 
        Context context = at.getSystemContext(); 
        context.setTheme(android.R.style.Theme_Holo); 
        m.mContext = context; 
        m.mFactoryTest = factoryTest; 
  /**
   * Author: Onskreen 
   * Date: 19/02/2011 
   * 
   * Instantiate the stacks with cornerstone flags 
   */
 
        //m.mMainStack = new ActivityStack(m, context, true); 
        m.mMainStack = new ActivityStack(m, context, truefalse, -1); 
 
  /**
   * Author: Onskreen 
   * Date: 12/01/2011 
   * 
   * Instantiate the stacks for cornerstone 
   */
 
        m.mCornerstoneStack = new ActivityStack(m, context, falsefalse, -1); 
        for(int i=0; i<m.mMaxNumCornerstonePanels; i++) { 
   ActivityStack panelStack = new ActivityStack(m, context, falsetrue, i); 
   m.mCornerstonePanelStacks.add(panelStack); 
        } 
 
  /**
   * Author: Onskreen 
   * Date: 20/07/2011 
   * 
   * populate the mCornerstoneAppPackageName, mCornerstoneLauncherAppPackageName and 
   * mCornerstoneLauncherClassName from the cornerstone.xml 
   */
 
        XmlResourceParser xpp = null
        try { 
            Resources res = context.getResources(); 
            xpp = res.getXml(com.android.internal.R.xml.cornerstone); 
            xpp.next(); 
            int eventType = xpp.getEventType(); 
            String tag; 
            while (eventType != XmlPullParser.END_DOCUMENT) { 
                if(eventType == XmlPullParser.START_DOCUMENT) { 
 
                } else if(eventType == XmlPullParser.START_TAG) { 
                     tag = xpp.getName(); 
                     if(tag.equals("pkg")){ 
                          xpp.next(); 
                          m.mCornerstoneAppPackageName = xpp.getText(); 
                     } else if(tag.equals("launcher")) { 
                         xpp.next(); 
                         tag = xpp.getName(); 
                         if(tag.equals("pkg")){ 
                            xpp.next(); 
                            m.mCornerstoneLauncherAppPackageName = xpp.getText(); 
                            xpp.next(); 
                         } 
                         xpp.next(); 
                         tag = xpp.getName(); 
                         if(tag.equals("class")){ 
                            xpp.next(); 
                            m.mCornerstoneLauncherClassName = xpp.getText(); 
                            xpp.next(); 
                         } 
                         break
                     } 
                } 
                eventType = xpp.next(); 
            } 
            xpp.close(); 
         } catch (XmlPullParserException e) { 
              // TODO Auto-generated catch block 
              e.printStackTrace(); 
              xpp.close(); 
         } catch (IOException e) { 
             // TODO Auto-generated catch block 
             e.printStackTrace(); 
             xpp.close(); 
         } 
 
  m.mBatteryStatsService.publish(context); 
        m.mUsageStatsService.publish(context); 
         
        synchronized (thr) { 
            thr.mReady = true
            thr.notifyAll(); 
        } 
 
        m.startRunning(nullnullnullnull); 
         
        return context; 
    } 
 
    public static ActivityManagerService self() { 
        return mSelf; 
    } 
     
    static class AThread extends Thread { 
        ActivityManagerService mService; 
        boolean mReady = false
 
        public AThread() { 
            super("ActivityManager"); 
        } 
 
        public void run() { 
            Looper.prepare(); 
 
            android.os.Process.setThreadPriority( 
                    android.os.Process.THREAD_PRIORITY_FOREGROUND); 
            android.os.Process.setCanSelfBackground(false); 
 
            ActivityManagerService m = new ActivityManagerService(); 
 
            synchronized (this) { 
                mService = m; 
                notifyAll(); 
            } 
 
            synchronized (this) { 
                while (!mReady) { 
                    try { 
                        wait(); 
                    } catch (InterruptedException e) { 
                    } 
                } 
            } 
 
            // For debug builds, log event loop stalls to dropbox for analysis. 
            if (StrictMode.conditionallyEnableDebugLogging()) { 
                Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper"); 
            } 
 
            Looper.loop(); 
        } 
    } 
 
    static class MemBinder extends Binder { 
        ActivityManagerService mActivityManagerService; 
        MemBinder(ActivityManagerService activityManagerService) { 
            mActivityManagerService = activityManagerService; 
        } 
 
        @Override 
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 
            if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP) 
                    != PackageManager.PERMISSION_GRANTED) { 
                pw.println("Permission Denial: can't dump meminfo from from pid=" 
                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 
                        + " without permission " + android.Manifest.permission.DUMP); 
                return
            } 
 
            mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, "  ", args, 
                    falsenullnullnull); 
        } 
    } 
 
    static class GraphicsBinder extends Binder { 
        ActivityManagerService mActivityManagerService; 
        GraphicsBinder(ActivityManagerService activityManagerService) { 
            mActivityManagerService = activityManagerService; 
        } 
 
        @Override 
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 
            if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP) 
                    != PackageManager.PERMISSION_GRANTED) { 
                pw.println("Permission Denial: can't dump gfxinfo from from pid=" 
                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 
                        + " without permission " + android.Manifest.permission.DUMP); 
                return
            } 
 
            mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args); 
        } 
    } 
 
    static class CpuBinder extends Binder { 
        ActivityManagerService mActivityManagerService; 
        CpuBinder(ActivityManagerService activityManagerService) { 
            mActivityManagerService = activityManagerService; 
        } 
 
        @Override 
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 
            if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP) 
                    != PackageManager.PERMISSION_GRANTED) { 
                pw.println("Permission Denial: can't dump cpuinfo from from pid=" 
                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 
                        + " without permission " + android.Manifest.permission.DUMP); 
                return
            } 
 
            synchronized (mActivityManagerService.mProcessStatsThread) { 
                pw.print(mActivityManagerService.mProcessStats.printCurrentLoad()); 
                pw.print(mActivityManagerService.mProcessStats.printCurrentState( 
                        SystemClock.uptimeMillis())); 
            } 
        } 
    } 
 
    private ActivityManagerService() { 
        Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass()); 
         
        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().writeAsyncLocked(); 
        mOnBattery = DEBUG_POWER ? true 
                : mBatteryStatsService.getActiveStatistics().getIsOnBattery(); 
        mBatteryStatsService.getActiveStatistics().setCallback(this); 
         
        mUsageStatsService = new UsageStatsService(new File( 
                systemDir, "usagestats").toString()); 
 
        GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version"
            ConfigurationInfo.GL_ES_VERSION_UNDEFINED); 
 
        mConfiguration.setToDefaults(); 
        mConfiguration.locale = Locale.getDefault(); 
        mConfigurationSeq = mConfiguration.seq = 1
        mProcessStats.init(); 
         
        mCompatModePackages = new CompatModePackages(this, systemDir); 
 
        // Add ourself to the Watchdog monitors. 
        Watchdog.getInstance().addMonitor(this); 
 
        mProcessStatsThread = new Thread("ProcessStats") { 
            public void run() { 
                while (true) { 
                    try { 
                        try { 
                            synchronized(this) { 
                                final long now = SystemClock.uptimeMillis(); 
                                long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now; 
                                long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now; 
                                //Slog.i(TAG, "Cpu delay=" + nextCpuDelay 
                                //        + ", write delay=" + nextWriteDelay); 
                                if (nextWriteDelay < nextCpuDelay) { 
                                    nextCpuDelay = nextWriteDelay; 
                                } 
                                if (nextCpuDelay > 0) { 
                                    mProcessStatsMutexFree.set(true); 
                                    this.wait(nextCpuDelay); 
                                } 
                            } 
                        } catch (InterruptedException e) { 
                        } 
                        updateCpuStatsNow(); 
                    } catch (Exception e) { 
                        Slog.e(TAG, "Unexpected exception collecting process stats", e); 
                    } 
                } 
            } 
        }; 
        mProcessStatsThread.start(); 
    } 
 
    @Override 
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 
            throws RemoteException { 
        try { 
            return super.onTransact(code, data, reply, flags); 
        } catch (RuntimeException e) { 
            // The activity manager only throws security exceptions, so let's 
            // log all others. 
            if (!(e instanceof SecurityException)) { 
                Slog.e(TAG, "Activity Manager Crash", e); 
            } 
            throw e; 
        } 
    } 
 
    void updateCpuStats() { 
        final long now = SystemClock.uptimeMillis(); 
        if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) { 
            return
        } 
        if (mProcessStatsMutexFree.compareAndSet(truefalse)) { 
            synchronized (mProcessStatsThread) { 
                mProcessStatsThread.notify(); 
            } 
        } 
    } 
 
    void updateCpuStatsNow() { 
        synchronized (mProcessStatsThread) { 
            mProcessStatsMutexFree.set(false); 
            final long now = SystemClock.uptimeMillis(); 
            boolean haveNewCpuStats = false
 
            if (MONITOR_CPU_USAGE && 
                    mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) { 
                mLastCpuTime.set(now); 
                haveNewCpuStats = true
                mProcessStats.update(); 
                //Slog.i(TAG, mProcessStats.printCurrentState()); 
                //Slog.i(TAG, "Total CPU usage: " 
                //        + mProcessStats.getTotalCpuPercent() + "%"); 
 
                // Slog 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(EventLogTags.CPU, 
                            ((user+system+iowait+irq+softIrq) * 100) / total, 
                            (user * 100) / total, 
                            (system * 100) / total, 
                            (iowait * 100) / total, 
                            (irq * 100) / total, 
                            (softIrq * 100) / total); 
                } 
            } 
             
            long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes(); 
            final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics(); 
            synchronized(bstats) { 
                synchronized(mPidsSelfLocked) { 
                    if (haveNewCpuStats) { 
                        if (mOnBattery) { 
                            int perc = bstats.startAddingCpuLocked(); 
                            int totalUTime = 0
                            int totalSTime = 0
                            final int N = mProcessStats.countStats(); 
                            for (int i=0; i<N; i++) { 
                                ProcessStats.Stats st = mProcessStats.getStats(i); 
                                if (!st.working) { 
                                    continue
                                } 
                                ProcessRecord pr = mPidsSelfLocked.get(st.pid); 
                                int otherUTime = (st.rel_utime*perc)/100
                                int otherSTime = (st.rel_stime*perc)/100
                                totalUTime += otherUTime; 
                                totalSTime += otherSTime; 
                                if (pr != null) { 
                                    BatteryStatsImpl.Uid.Proc ps = pr.batteryStats; 
                                    ps.addCpuTimeLocked(st.rel_utime-otherUTime, 
                                            st.rel_stime-otherSTime); 
                                    ps.addSpeedStepTimes(cpuSpeedTimes); 
                                    pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10
                                } else { 
                                    BatteryStatsImpl.Uid.Proc ps = 
                                            bstats.getProcessStatsLocked(st.name, st.pid); 
                                    if (ps != null) { 
                                        ps.addCpuTimeLocked(st.rel_utime-otherUTime, 
                                                st.rel_stime-otherSTime); 
                                        ps.addSpeedStepTimes(cpuSpeedTimes); 
                                    } 
                                } 
                            } 
                            bstats.finishAddingCpuLocked(perc, totalUTime, 
                                    totalSTime, cpuSpeedTimes); 
                        } 
                    } 
                } 
 
                if (mLastWriteTime < (now-BATTERY_STATS_TIME)) { 
                    mLastWriteTime = now; 
                    mBatteryStatsService.getActiveStatistics().writeAsyncLocked(); 
                } 
            } 
        } 
    } 
     
    @Override 
    public void batteryNeedsCpuUpdate() { 
        updateCpuStatsNow(); 
    } 
 
    @Override 
    public void batteryPowerChanged(boolean onBattery) { 
        // When plugging in, update the CPU stats first before changing 
        // the plug state. 
        updateCpuStatsNow(); 
        synchronized (this) { 
            synchronized(mPidsSelfLocked) { 
                mOnBattery = DEBUG_POWER ? true : onBattery; 
            } 
        } 
    } 
 
    /**
     * Initialize the application bind args. These are passed to each 
     * process when the bindApplication() IPC is sent to the process. They're 
     * lazily setup to make sure the services are running when they're asked for. 
     */
 
    private HashMap<String, IBinder> getCommonServicesLocked() { 
        if (mAppBindArgs == null) { 
            mAppBindArgs = new HashMap<String, IBinder>(); 
 
            // Setup the application init args 
            mAppBindArgs.put("package", ServiceManager.getService("package")); 
            mAppBindArgs.put("window", ServiceManager.getService("window")); 
            mAppBindArgs.put(Context.ALARM_SERVICE, 
                    ServiceManager.getService(Context.ALARM_SERVICE)); 
        } 
        return mAppBindArgs; 
    } 
 
    final void setFocusedActivityLocked(ActivityRecord r) { 
        if (mFocusedActivity != r) { 
            mFocusedActivity = r; 
            if (r != null) { 
                mWindowManager.setFocusedApp(r.appToken, true); 
            } 
            /**
             * Author: Onskreen 
             * Date: 11/10/2011 
             * 
             * Sets the appropriate focused app and changes 
             * the z-order of focused window. 
             */
 
            //mWindowManager.handleFocusChange(r); 
        } 
    } 
 
    private final void updateLruProcessInternalLocked(ProcessRecord app, 
            boolean oomAdj, boolean updateActivityTime, int bestPos) { 
        // 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); 
         
        int i = mLruProcesses.size()-1
        int skipTop = 0
         
        app.lruSeq = mLruSeq; 
         
        // compute the new weight for this process. 
        if (updateActivityTime) { 
            app.lastActivityTime = SystemClock.uptimeMillis(); 
        } 
        if (app.activities.size() > 0) { 
            // If this process has activities, we more strongly want to keep 
            // it around. 
            app.lruWeight = app.lastActivityTime; 
        } else if (app.pubProviders.size() > 0) { 
            // If this process contains content providers, we want to keep 
            // it a little more strongly. 
            app.lruWeight = app.lastActivityTime - ProcessList.CONTENT_APP_IDLE_OFFSET; 
            // Also don't let it kick out the first few "real" hidden processes. 
            skipTop = ProcessList.MIN_HIDDEN_APPS; 
        } else { 
            // If this process doesn't have activities, we less strongly 
            // want to keep it around, and generally want to avoid getting 
            // in front of any very recently used activities. 
            app.lruWeight = app.lastActivityTime - ProcessList.EMPTY_APP_IDLE_OFFSET; 
            // Also don't let it kick out the first few "real" hidden processes. 
            skipTop = ProcessList.MIN_HIDDEN_APPS; 
        } 
         
        while (i >= 0) { 
            ProcessRecord p = mLruProcesses.get(i); 
            // If this app shouldn't be in front of the first N background 
            // apps, then skip over that many that are currently hidden. 
            if (skipTop > 0 && p.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) { 
                skipTop--; 
            } 
            if (p.lruWeight <= app.lruWeight || i < bestPos) { 
                mLruProcesses.add(i+1, app); 
                break
            } 
            i--; 
        } 
        if (i < 0) { 
            mLruProcesses.add(0, app); 
        } 
         
        // If the app is currently using a content provider or service, 
        // bump those processes as well. 
        if (app.connections.size() > 0) { 
            for (ConnectionRecord cr : app.connections) { 
                if (cr.binding != null && cr.binding.service != null 
                        && cr.binding.service.app != null 
                        && cr.binding.service.app.lruSeq != mLruSeq) { 
                    updateLruProcessInternalLocked(cr.binding.service.app, oomAdj, 
                            updateActivityTime, i+1); 
                } 
            } 
        } 
        if (app.conProviders.size() > 0) { 
            for (ContentProviderRecord cpr : app.conProviders.keySet()) { 
                if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) { 
                    updateLruProcessInternalLocked(cpr.proc, oomAdj, 
                            updateActivityTime, i+1); 
                } 
            } 
        } 
         
        //Slog.i(TAG, "Putting proc to front: " + app.processName); 
        if (oomAdj) { 
            updateOomAdjLocked(); 
        } 
    } 
 
    final void updateLruProcessLocked(ProcessRecord app, 
            boolean oomAdj, boolean updateActivityTime) { 
        mLruSeq++; 
        updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0); 
    } 
 
    final ProcessRecord getProcessRecordLocked
            String processName, int uid) { 
        if (uid == Process.SYSTEM_UID) { 
            // The system gets to run in any process.  If there are multiple 
            // processes with the same uid, just pick the first (this 
            // should never happen). 
            SparseArray<ProcessRecord> procs = mProcessNames.getMap().get( 
                    processName); 
            return procs != null ? procs.valueAt(0) : null
        } 
        ProcessRecord proc = mProcessNames.get(processName, uid); 
        return proc; 
    } 
 
    void ensurePackageDexOpt(String packageName) { 
        IPackageManager pm = AppGlobals.getPackageManager(); 
        try { 
            if (pm.performDexOpt(packageName)) { 
                mDidDexOpt = true
            } 
        } catch (RemoteException e) { 
        } 
    } 
     
    boolean isNextTransitionForward() { 
        int transit = mWindowManager.getPendingAppTransition(); 
        return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN 
                || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN 
                || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT; 
    } 
     
    final ProcessRecord startProcessLocked(String processName, 
            ApplicationInfo info, boolean knownToBeDead, int intentFlags, 
            String hostingType, ComponentName hostingName, boolean allowWhileBooting) { 
        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) Slog.v(TAG, "startProcess: name=" + processName 
                + " app=" + app + " knownToBeDead=" + knownToBeDead 
                + " thread=" + (app != null ? app.thread : null
                + " pid=" + (app != null ? app.pid : -1)); 
        if (app != null && app.pid > 0) { 
            if (!knownToBeDead || app.thread == null) { 
                // We already have the app running, or are waiting for it to 
                // come up (we have a pid but not yet its thread), so keep it. 
                if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app); 
                // If this is a new package in the process, add the package to the list 
                app.addPackage(info.packageName); 
                return app; 
            } else { 
                // An application record is attached to a previous process, 
                // clean it up now. 
                if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app); 
                handleAppDiedLocked(app, truetrue); 
            } 
        } 
 
        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) { 
                if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid 
                        + "/" + info.processName); 
                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. 
            if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid 
                    + "/" + info.processName); 
            mProcessCrashTimes.remove(info.processName, info.uid); 
            if (mBadProcesses.get(info.processName, info.uid) != null) { 
                EventLog.writeEvent(EventLogTags.AM_PROC_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 (!mProcessesReady 
                && !isAllowedWhileBooting(info) 
                && !allowWhileBooting) { 
            if (!mProcessesOnHold.contains(app)) { 
                mProcessesOnHold.add(app); 
            } 
            if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app); 
            return app; 
        } 
 
        startProcessLocked(app, hostingType, hostingNameStr); 
        return (app.pid != 0) ? app : null
    } 
 
    boolean isAllowedWhileBooting(ApplicationInfo ai) { 
        return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
    } 
     
    private final void startProcessLocked(ProcessRecord app, 
            String hostingType, String hostingNameStr) { 
        if (app.pid > 0 && app.pid != MY_PID) { 
            synchronized (mPidsSelfLocked) { 
                mPidsSelfLocked.remove(app.pid); 
                mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); 
            } 
            app.pid = 0
        } 
 
        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG, 
                "startProcessLocked removing on hold: " + app); 
        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) { 
                Slog.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; 
                // Also turn on CheckJNI for debuggable apps. It's quite 
                // awkward to turn on otherwise. 
                debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; 
            } 
            // Run the app in safe mode if its manifest requests so or the 
            // system is booted in safe mode. 
            if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 || 
                Zygote.systemInSafeMode == true) { 
                debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE; 
            } 
            if ("1".equals(SystemProperties.get("debug.checkjni"))) { 
                debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; 
            } 
            if ("1".equals(SystemProperties.get("debug.jni.logging"))) { 
                debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; 
            } 
            if ("1".equals(SystemProperties.get("debug.assert"))) { 
                debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; 
            } 
 
            // Start the process.  It will either succeed and return a result containing 
            // the PID of the new process, or else throw a RuntimeException. 
            Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread"
                    app.processName, uid, uid, gids, debugFlags, 
                    app.info.targetSdkVersion, null); 
 
            BatteryStatsImpl bs = app.batteryStats.getBatteryStats(); 
            synchronized (bs) { 
                if (bs.isOnBattery()) { 
                    app.batteryStats.incStartsLocked(); 
                } 
            } 
             
            EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid, 
                    app.processName, hostingType, 
                    hostingNameStr != null ? hostingNameStr : ""); 
             
            if (app.persistent) { 
                Watchdog.getInstance().processStarted(app.processName, startResult.pid); 
            } 
             
            StringBuilder buf = mStringBuilder; 
            buf.setLength(0); 
            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(startResult.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("}"); 
            Slog.i(TAG, buf.toString()); 
            app.pid = startResult.pid; 
            app.usingWrapper = startResult.usingWrapper; 
            app.removed = false
            synchronized (mPidsSelfLocked) { 
                this.mPidsSelfLocked.put(startResult.pid, app); 
                Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); 
                msg.obj = app; 
                mHandler.sendMessageDelayed(msg, startResult.usingWrapper 
                        ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT); 
            } 
        } catch (RuntimeException e) { 
            // XXX do better error recovery. 
            app.pid = 0
            Slog.e(TAG, "Failure starting process " + app.processName, e); 
        } 
    } 
 
    void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) { 
        if (resumed) { 
            mUsageStatsService.noteResumeComponent(resumedComponent.realActivity); 
        } else { 
            mUsageStatsService.notePauseComponent(resumedComponent.realActivity); 
        } 
    } 
 
    boolean startHomeActivityLocked() { 
        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(), 
                    STOCK_PM_FLAGS); 
        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); 
                mMainStack.startActivityLocked(null, intent, nullnull0, aInfo, 
                        nullnull000falsefalsenull); 
            } 
        } 
         
         
        return true
    } 
 
 
    /**
     * Author: Onskreen 
     * Date: 11/03/2011 
     * 
     * Start the Cornerstone Launcher in the specified CS Panel 
     */
 
    boolean startCornerstoneLauncherLocked(int panelIndex) { 
  Intent intent = new Intent(); 
  ComponentName cp = new ComponentName(mCornerstoneLauncherAppPackageName, mCornerstoneLauncherClassName); 
  intent.setComponent(cp); 
  startCornerstoneApp(intent, panelIndex); 
  return true
    } 
 
    /**
     * Starts the "new version setup screen" if appropriate. 
     */
 
    void startSetupActivityLocked() { 
        // Only do this once per boot. 
        if (mCheckedForSetup) { 
            return
        } 
         
        // We will show this screen if the current one is a different 
        // version than the last one shown, and we are not running in 
        // low-level factory test mode. 
        final ContentResolver resolver = mContext.getContentResolver(); 
        if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL && 
                Settings.Secure.getInt(resolver, 
                        Settings.Secure.DEVICE_PROVISIONED, 0) != 0) { 
            mCheckedForSetup = true
             
            // See if we should be showing the platform update setup UI. 
            Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP); 
            List<ResolveInfo> ris = mSelf.mContext.getPackageManager() 
                    .queryIntentActivities(intent, PackageManager.GET_META_DATA); 
             
            // We don't allow third party apps to replace this. 
            ResolveInfo ri = null
            for (int i=0; ris != null && i<ris.size(); i++) { 
                if ((ris.get(i).activityInfo.applicationInfo.flags 
                        & ApplicationInfo.FLAG_SYSTEM) != 0) { 
                    ri = ris.get(i); 
                    break
                } 
            } 
             
            if (ri != null) { 
                String vers = ri.activityInfo.metaData != null 
                        ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION) 
                        : null
                if (vers == null && ri.activityInfo.applicationInfo.metaData != null) { 
                    vers = ri.activityInfo.applicationInfo.metaData.getString( 
                            Intent.METADATA_SETUP_VERSION); 
                } 
                String lastVers = Settings.Secure.getString( 
                        resolver, Settings.Secure.LAST_SETUP_SHOWN); 
                if (vers != null && !vers.equals(lastVers)) { 
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
                    intent.setComponent(new ComponentName( 
                            ri.activityInfo.packageName, ri.activityInfo.name)); 
                    mMainStack.startActivityLocked(null, intent, nullnull0, ri.activityInfo, 
                            nullnull000falsefalsenull); 
                } 
            } 
        } 
    } 
     
    CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) { 
        return mCompatModePackages.compatibilityInfoForPackageLocked(ai); 
    } 
 
    public int getFrontActivityScreenCompatMode() { 
        synchronized (this) { 
            return mCompatModePackages.getFrontActivityScreenCompatModeLocked(); 
        } 
    } 
 
    public void setFrontActivityScreenCompatMode(int mode) { 
        synchronized (this) { 
            mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode); 
        } 
    } 
 
    public int getPackageScreenCompatMode(String packageName) { 
        synchronized (this) { 
            return mCompatModePackages.getPackageScreenCompatModeLocked(packageName); 
        } 
    } 
 
    public void setPackageScreenCompatMode(String packageName, int mode) { 
        synchronized (this) { 
            mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode); 
        } 
    } 
 
    public boolean getPackageAskScreenCompat(String packageName) { 
        synchronized (this) { 
            return mCompatModePackages.getPackageAskCompatModeLocked(packageName); 
        } 
    } 
 
    public void setPackageAskScreenCompat(String packageName, boolean ask) { 
        synchronized (this) { 
            mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask); 
        } 
    } 
 
    void reportResumedActivityLocked(ActivityRecord r) { 
        //Slog.i(TAG, "**** REPORT RESUME: " + r); 
         
        final int identHash = System.identityHashCode(r); 
        updateUsageStats(r, true); 
         
        int i = mWatchers.beginBroadcast(); 
        while (i > 0) { 
            i--; 
            IActivityWatcher w = mWatchers.getBroadcastItem(i); 
            if (w != null) { 
                try { 
                    w.activityResuming(identHash); 
                } catch (RemoteException e) { 
                } 
            } 
        } 
        mWatchers.finishBroadcast(); 
    } 
 
    private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) { 
        int i = mProcessObservers.beginBroadcast(); 
        while (i > 0) { 
            i--; 
            final IProcessObserver observer = mProcessObservers.getBroadcastItem(i); 
            if (observer != null) { 
                try { 
                    observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities); 
                } catch (RemoteException e) { 
                } 
            } 
        } 
        mProcessObservers.finishBroadcast(); 
    } 
 
    private void dispatchProcessDied(int pid, int uid) { 
        int i = mProcessObservers.beginBroadcast(); 
        while (i > 0) { 
            i--; 
            final IProcessObserver observer = mProcessObservers.getBroadcastItem(i); 
            if (observer != null) { 
                try { 
                    observer.onProcessDied(pid, uid); 
                } catch (RemoteException e) { 
                } 
            } 
        } 
        mProcessObservers.finishBroadcast(); 
    } 
 
    final void doPendingActivityLaunchesLocked(boolean doResume) { 
        final int N = mPendingActivityLaunches.size(); 
        if (N <= 0) { 
            return
        } 
        for (int i=0; i<N; i++) { 
            PendingActivityLaunch pal = mPendingActivityLaunches.get(i); 
            /**
             * Author: Onskreen 
             * Date: 27/01/2011 
             * 
             * Push message to appropriate stack. 
             */
 
            int stack = getActivityStack(pal.r); 
            ActivityStack targetStack = null
            //Cornerstone Panel 
            if(stack >= 0) { 
    if(stack < mCornerstonePanelStacks.size()) { 
     targetStack = mCornerstonePanelStacks.get(stack); 
    else { 
     Log.e(TAG, "Found in Non-Existent Stack"); 
     return
    
   else if(stack == CORNERSTONE_STACK) { 
    //Cornerstone 
    targetStack = mCornerstoneStack; 
   else if(stack == MAIN_STACK || stack == NO_STACK) { 
    //Main stack or Unknown 
    targetStack = mMainStack; 
   
   targetStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord, 
           pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded, 
           doResume && i == (N-1)); 
        } 
  mPendingActivityLaunches.clear(); 
    } 
 
    /**
     * Author: Onskreen 
     * Date: 23/02/2012 
     * 
     * Determines if the requested Activity is HOME app and returns 
     * boolean value. HOME app shouldn't be allowed to run in 
     * Cornerstone Panels. They are allowed only in main panel. 
     */
 
    private boolean checkActivityIsHomeApp(ActivityInfo appInfo) { 
  boolean isHomeActivity = false
  PackageManager pm = mContext.getPackageManager(); 
  if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "appInfo.packageName: " + appInfo.packageName); 
 
  final Intent intent = new Intent(Intent.ACTION_MAIN); 
  intent.addCategory(Intent.CATEGORY_HOME); 
  List<ResolveInfo> list = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); 
  for(int i = 0; i < list.size(); i++) { 
   ResolveInfo info = (ResolveInfo)list.get(i); 
   String pkg = info.activityInfo.packageName; 
   if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "i: " + i + " Home App->" + pkg); 
   if(appInfo.packageName.equals(pkg)) { 
    isHomeActivity = true
    return isHomeActivity; 
   
  
  return isHomeActivity; 
    } 
 
    /**
     * Author: Onskreen 
     * Date: 07/01/2012 
     * 
     * Determine if the activity is permitted to start. An activity is permitted to launch if: 
     * - No other instance of it is currently in the resumed state in a different panel 
     * other than the one it wants to launch in 
     * - No instance of it will be active causing a conflict - If opening in the Main Panel, another instance cannot 
     * be in the closed Cornerstone about to become Resumed once the user opens it 
     * - If opening in the Cornerstone, the app must declare that it supports any orientation 
     * 
     * 
     */
 
    public boolean isActivityPermittedToStart(ActivityInfo appInfo, ActivityStack stack) { 
  //TODO These strings do not belong hardcoded here 
  String titleMsg = "Sorry!"
  String activityConflictMsg = "In this version of Cornerstone, only one instance of this application can be active at any time. This capability will be refined to allow multiple instances of Applications that don't share resources, and launch those that do into separate processes."
  String orientationsNotSupportedMsg = "This application does not support all the possible configurations, so cannot be opened in the Cornerstone"
  String homeActivityMsg = "This application is a Launcher application, so cannot be opened in the Cornerstone"
 
  if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "Cornerstone permitting to start: " + appInfo + " in: " + stack.mStackName); 
  //No check for Cornerstone Stack 
  if(stack == mCornerstoneStack) { 
   if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "\tResult: Permitted\tReason: No check for cornerstone."); 
   return true
  
 
  //Apps launched in Cornerstone Panels must support portrait or landscape 
  // orientations since the device may be rotated due to the user or main 
  // main panel app. 
  if(mCornerstonePanelStacks.contains(stack)) { 
   if(!checkActivitySupportsRequiredOrientations(appInfo)) { 
    if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "\tResult: Banned\tReason: In Cornerstone and doesn't support all orientations"); 
    Message msg = Message.obtain(); 
    msg.what = SHOW_APP_ERROR_MSG; 
    msg.getData().putCharSequence("title", titleMsg); 
    msg.getData().putCharSequence("body", orientationsNotSupportedMsg); 
    mHandler.sendMessage(msg); 
    return false
   else if(checkActivityIsHomeApp(appInfo)) { 
    if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "\tResult: Banned\tReason: Launcher app can't be opened in Cornerstone"); 
    Message msg = Message.obtain(); 
    msg.what = SHOW_APP_ERROR_MSG; 
    msg.getData().putCharSequence("title", titleMsg); 
    msg.getData().putCharSequence("body", homeActivityMsg); 
    mHandler.sendMessage(msg); 
    return false
   
  
 
  /**
   * Is the package running in a process anywhere. If not, safe to start. 
   */
 
  ProcessRecord proc = getProcessRecordLocked(appInfo.processName, appInfo.applicationInfo.uid); 
  if(proc == null) { 
   if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "\tResult: Permitted\tReason: Not found elsewhere"); 
   return true
  
 
  List<ActivityRecord> records = new ArrayList<ActivityRecord>(); 
 
  /**
   * Find Activities of the same process in stacks other than the one we are trying to launch in. If found, do a 
   * check on them to see if they will cause a conflict. 
   * 
   * records - the list of Activities that we found that do cause a conflict. If we want to act upon them all 
   * in the future (move them, reconfig them, kill them, etc...) we can do it with this list. 
   */
 
  boolean retValue = true
  //Main Stack 
  // Don't search in the stack we are currently in to avoid cases where the Activity is in our stack somewhere, but also 
  // on top of another stack. 
  if(stack != mMainStack) { 
   for(ActivityRecord ar: mMainStack.mHistory) { 
    if(ar.app == proc) { 
     if(!checkActivityCausesConflict(ar, mMainStack)) { 
      retValue = false
      break
     else { 
      records.add(ar); 
     
    
   
  
  //CornerstonePanelStacks 
  if(retValue) { 
   for(ActivityStack as: mCornerstonePanelStacks) { 
    if(stack != as && retValue) { 
     for(ActivityRecord ar: as.mHistory) { 
      if(ar.app == proc) { 
       if(!checkActivityCausesConflict(ar, as)) { 
        retValue = false
        break
       else { 
        records.add(ar); 
       
      
     
    
   
  
 
  //Display error if not permitted to proceed 
  if(!retValue) { 
   Message msg = Message.obtain(); 
   msg.what = SHOW_APP_ERROR_MSG; 
   msg.getData().putCharSequence("title", titleMsg); 
   msg.getData().putCharSequence("body", activityConflictMsg); 
   mHandler.sendMessage(msg); 
  else { 
   for(ActivityRecord r: records) { 
    //TODO Ideally we would remove the activity that is in the other stack but not resumed so that the user 
    // can't navigate back to it. As is, the user can and that can create a conflict where the same 
    // process has actvities in multiple panels concurrently. This happens when an activity starts an activity 
    // from a different process, then opens an activity of the original process in another panel. Then in the 
    // original panel presses back. 
    //mMainStack.destroyActivityLocked(r, true, false, "Cornerstone-Open Different Panel"); 
    //this.killApplicationProcess(r.app.processName, proc.info.uid); 
   
  
 
  return retValue; 
 
 
    /**
     * Author: Onskreen 
     * Date: 07/01/2012 
     * 
     * Test if the specified Activity (ar) in the specified stack (as) will cause a launch conflict. 
     * true - Ok to launch Activity 
     * false - This Activity should restrict another of the same package from being opened 
     * 
     */
 
    private boolean checkActivityCausesConflict(ActivityRecord ar, ActivityStack as) { 
  if(ar.state != ActivityState.RESUMED) {  //Not running 
   if(as == mMainStack) {   //Main Stack 
    if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "\tResult: Permitted\tReason: In main stack, but not running"); 
    return true
   else if(mCornerstonePanelStacks.contains(as)) {  //CS Panel Stack 
    //If the CS Panel is minimized, the Activity can be in the paused state but 
    // will immediately be resumed when the user opens the CS. So don't allow the 
    // user to open this app. 
    if(mWindowManager.mCornerstoneState == WindowManagerService.Cornerstone_State.RUNNING_CLOSED) {    //RUNNING_CLOSED 
     ActivityRecord arTop = as.topRunningActivityLocked(null); 
     if(arTop !=  ar) { 
      if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "\tResult: Permitted\tReason: CS Closed, In cs panel stack, but not at top"); 
      return true
     else { 
      if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "\tResult: Banned\tReason: CS Closed, In cs panel stack, at top"); 
      return false
     
    else {                         //Any Other CS State 
     if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "\tResult: Permitted\tReason: In cs panel stack, but not running"); 
     return true
    
   else { 
    if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "\tResult: Permitted\tReason: Should never get here, didn't find the stack to evaluate"); 
    return true
   
  else {          //Running. Fail 
   if(DEBUG_CORNERSTONE||DEBUG_PROCESSES) Slog.v(TAG, "\tResult: Banned\tReason: Running elsewhere and in RESUMED state"); 
   return false
  
    } 
 
    /**
     * Author: Onskreen 
     * Date: 07/01/2012 
     * 
     * Determines if an Activity will support both landscape and portrait 
     * 
     * true - Activity does not specifiy only portrait or landscape orientations 
     * false - Activity specifies runs in either landscape or portrait only. 
     * 
     */
 
    private boolean checkActivitySupportsRequiredOrientations(ActivityInfo appInfo) { 
  int screenOrientation = appInfo.screenOrientation; 
  if(screenOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || 
   screenOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || 
   screenOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE || 
   screenOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT || 
   screenOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE || 
   screenOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT){ 
   return false
  else { 
   return true
  
    } 
 
    public final int startActivity(IApplicationThread caller, 
            Intent intent, String resolvedType, Uri[] grantedUriPermissions, 
            int grantedMode, IBinder resultTo, 
            String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug, 
            String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { 
 
  /**
   * Author: Onskreen 
   * Date: 12/01/2011 
   * 
   * Send to appropriate stack 
   */
 
  int stack = getActivityStack(intent, resultTo); 
  ActivityStack targetStack = null
  //Cornerstone Panel 
  if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    //System.out.println("Found in Cornerstone Panel Stack"); 
    targetStack = mCornerstonePanelStacks.get(stack); 
 
                /**
                 * Author: Onskreen 
                 * Date: 08/03/2011 
                 * 
                 * Notifies CSPanel app to change the cs app header controls appropriately 
                 */
 
    ComponentName cp = intent.getComponent(); 
    if(cp != null){ 
     String pkg = cp.getPackageName(); 
     if(pkg != null){ 
      broadcastCornerstonePanelFocusChanged(pkg, true, stack); 
     
    
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return -1
   
  else if(stack == CORNERSTONE_STACK) { 
   //System.out.println("Found in Cornerstone Stack"); 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
   mActivityStackExiting = false
   mWindowManager.setCornerstoneState(WindowManagerService.Cornerstone_State.RUNNING_OPEN); 
 
   /**
    * Author: Onskreen 
    * Date: 07/01/2012 
    * 
    * Cornerstone running will require a config change of Main Panel 
    */
 
   final long origId = Binder.clearCallingIdentity(); 
   if(DEBUG_CONFIGURATION) { 
    Slog.i(TAG, "State: Cornerstone Launched\tAction: Config Main Panel"); 
   
   /**
    * Author: Onskreen 
    * Date: 07/01/2012 
    * 
    * we might not want to call for a reconfig until after the activity is started? 
    */
 
   forceConfigurationLocked(mMainStack, WindowManagerService.Cornerstone_State.RUNNING_OPEN); 
   Binder.restoreCallingIdentity(origId); 
  else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //System.out.println("Found in Main Stack"); 
   //Main stack or Unknown 
   targetStack = mMainStack; 
  
 
  /**
   * Author: Onskreen 
   * Date: 16/03/2011 
   * 
   * Bring the top most main panel activity to front on long press HOME key 
   */
 
  if(targetStack == mMainStack && resultTo == null){ 
   ActivityRecord r = mMainStack.topRunningActivityLocked(null); 
   if(r !=null) { 
    ComponentName cp = intent.getComponent(); 
    if(cp != null){ 
     String pkg = cp.getPackageName(); 
     if(pkg != null){ 
      if(pkg.equals(r.packageName)){ 
       mWindowManager.handleFocusChange(r.appToken.asBinder()); 
       return IActivityManager.START_TASK_TO_FRONT; 
      else { 
       mWindowManager.handleFocusChange(r.appToken.asBinder()); 
      
     
    
   
  
 
  /**
   * Author: Onskreen 
   * Date: 09/08/2011 
   * 
   * Check for the multiple instances of CSPanel app in cornerstone stack. 
   * If found the second instance, then don't start the new instance just 
   * return it. 
   */
 
  if(targetStack == mCornerstoneStack && resultTo != null){ 
   ActivityRecord r = mCornerstoneStack.topRunningActivityLocked(null); 
   if(r !=null) { 
    ComponentName cp = intent.getComponent(); 
    if(cp != null){ 
     String pkg = cp.getPackageName(); 
     if(pkg != null){ 
      if(pkg.equals(r.packageName)){ 
       return IActivityManager.START_TASK_TO_FRONT; 
      
     
    
   
  
 
  return targetStack.startActivityMayWait(caller, -1, intent, resolvedType, 
                grantedUriPermissions, grantedMode, resultTo, resultWho, 
                requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler, 
                nullnull); 
 
 
    public final WaitResult startActivityAndWait(IApplicationThread caller, 
            Intent intent, String resolvedType, Uri[] grantedUriPermissions, 
            int grantedMode, IBinder resultTo, 
            String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug, 
            String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { 
  WaitResult res = new WaitResult(); 
  int stack = getActivityStack(intent, resultTo); 
  ActivityStack targetStack = null
  //Cornerstone Panel 
  if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return res; 
   
  else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
  else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
   targetStack = mMainStack; 
  
  targetStack.startActivityMayWait(caller, -1, intent, resolvedType, 
                grantedUriPermissions, grantedMode, resultTo, resultWho, 
                requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler, 
                res, null); 
  return res; 
 
 
    public final int startActivityWithConfig(IApplicationThread caller, 
            Intent intent, String resolvedType, Uri[] grantedUriPermissions, 
            int grantedMode, IBinder resultTo, 
            String resultWho, int requestCode, boolean onlyIfNeeded, 
            boolean debug, Configuration config) { 
  int stack = getActivityStack(intent, resultTo); 
  ActivityStack targetStack = null
  //Cornerstone Panel 
  if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return -1
   
  else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
  else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
   targetStack = mMainStack; 
  
 
  return targetStack.startActivityMayWait(caller,-1, intent, resolvedType, 
                grantedUriPermissions, grantedMode, resultTo, resultWho, 
                requestCode, onlyIfNeeded, debug, nullnullfalsenull, config); 
 
 
    public int startActivityIntentSender(IApplicationThread caller, 
            IntentSender intent, Intent fillInIntent, String resolvedType, 
            IBinder resultTo, String resultWho, int requestCode, 
            int flagsMask, int flagsValues) { 
        // Refuse possible leaked file descriptors 
        if (fillInIntent != null && fillInIntent.hasFileDescriptors()) { 
            throw new IllegalArgumentException("File descriptors passed in Intent"); 
        } 
 
        IIntentSender sender = intent.getTarget(); 
        if (!(sender instanceof PendingIntentRecord)) { 
            throw new IllegalArgumentException("Bad PendingIntent object"); 
        } 
 
        PendingIntentRecord pir = (PendingIntentRecord)sender; 
 
        synchronized (this) { 
            // If this is coming from the currently resumed activity, it is 
            // effectively saying that app switches are allowed at this point. 
            if (mMainStack.mResumedActivity != null 
                    && mMainStack.mResumedActivity.info.applicationInfo.uid == 
                            Binder.getCallingUid()) { 
                mAppSwitchesAllowedTime = 0
            } 
            /**
             * Author: Onskreen 
             * Date: 27/01/2011 
             * 
             * Mirroring the app switching logic in cornerstone. Not clear if this should 
             * be mirrored or applied to only the appropriate stack? 
             */
 
            if (mCornerstoneStack.mResumedActivity != null 
                    && mCornerstoneStack.mResumedActivity.info.applicationInfo.uid == 
                            Binder.getCallingUid()) { 
                mAppSwitchesAllowedTime = 0
            } 
        } 
 
        return pir.sendInner(0, fillInIntent, resolvedType, null
                null, resultTo, resultWho, requestCode, flagsMask, flagsValues); 
    } 
 
    public boolean startNextMatchingActivity(IBinder callingActivity, 
            Intent intent) { 
        // Refuse possible leaked file descriptors 
        if (intent != null && intent.hasFileDescriptors() == true) { 
            throw new IllegalArgumentException("File descriptors passed in Intent"); 
        } 
 
        synchronized (this) { 
   /**
    * Author: Onskreen 
    * Date: 27/01/2011 
    * 
    * Choosing between stacks for all following logic. Has to be 
    * ensured that callingActivity can indicate this. 
    */
 
   int stack = getActivityStack(callingActivity); 
   ActivityStack targetStack = null
   //Cornerstone Panel 
   if(stack >= 0) { 
    if(stack < mCornerstonePanelStacks.size()) { 
     targetStack = mCornerstonePanelStacks.get(stack); 
    else { 
     Log.e(TAG, "Found in Non-Existent Stack"); 
     return false
    
   else if(stack == CORNERSTONE_STACK) { 
    //Cornerstone 
    targetStack = mCornerstoneStack; 
   else if(stack == MAIN_STACK || stack == NO_STACK) { 
    //Main stack or Unknown 
    targetStack = mMainStack; 
   
 
            int index = targetStack.indexOfTokenLocked(callingActivity); 
            if (index < 0) { 
                return false
            } 
            ActivityRecord r = (ActivityRecord)targetStack.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 = 
                    AppGlobals.getPackageManager().queryIntentActivities( 
                            intent, r.resolvedType, 
                            PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS); 
 
                // 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 ActivityRecord 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 = targetStack.startActivityLocked(r.app.thread, intent, 
                    r.resolvedType, null0, aInfo, 
                    resultTo != null ? resultTo.appToken : null, resultWho, 
                    requestCode, -1, r.launchedFromUid, falsefalsenull); 
            Binder.restoreCallingIdentity(origId); 
 
            r.finishing = wasFinishing; 
            if (res != START_SUCCESS) { 
                return false
            } 
            return true
        } 
    } 
 
    public final int startActivityInPackage(int uid, 
            Intent intent, String resolvedType, IBinder resultTo, 
            String resultWho, int requestCode, boolean onlyIfNeeded) { 
 
        // This is so super not safe, that only the system (or okay root) 
        // can do it. 
        final int callingUid = Binder.getCallingUid(); 
        if (callingUid != 0 && callingUid != Process.myUid()) { 
            throw new SecurityException( 
                    "startActivityInPackage only available to the system"); 
        } 
 
        synchronized(this) { 
   /**
    * Author: Onskreen 
    * Date: 12/01/2011 
    * 
    * TODO - All of this in a synchronized block is a horrible idea. Must clean. 
    */
 
            int stack = getActivityStack(intent, resultTo); 
            ActivityStack targetStack = null
            //Cornerstone Panel 
            if(stack >= 0) { 
    if(stack < mCornerstonePanelStacks.size()) { 
     targetStack = mCornerstonePanelStacks.get(stack); 
    else { 
     Log.e(TAG, "Found in Non-Existent Stack"); 
     return -1
    
            } else if(stack == CORNERSTONE_STACK) { 
    //Cornerstone 
    targetStack = mCornerstoneStack; 
   else if(stack == MAIN_STACK || stack == NO_STACK) { 
    //Main stack or Unknown 
                targetStack = mMainStack; 
            } 
 
            return targetStack.startActivityMayWait(null, uid, intent, resolvedType, 
                null0, resultTo, resultWho, requestCode, onlyIfNeeded, false
                nullnullfalsenullnull); 
        } 
    } 
 
    public final int startActivities(IApplicationThread caller, 
            Intent[] intents, String[] resolvedTypes, IBinder resultTo) { 
  synchronized(this) { 
   /**
    * Author: Onskreen 
    * Date: 12/01/2011 
    * 
    */
 
            int stack = getActivityStack(intents[0], resultTo); 
            ActivityStack targetStack = null
            //Cornerstone Panel 
            if(stack >= 0) { 
    if(stack < mCornerstonePanelStacks.size()) { 
     targetStack = mCornerstonePanelStacks.get(stack); 
    else { 
     Log.e(TAG, "Found in Non-Existent Stack"); 
     return -1
    
            } else if(stack == CORNERSTONE_STACK) { 
    //Cornerstone 
    targetStack = mCornerstoneStack; 
            } else if(stack == MAIN_STACK || stack == NO_STACK) { 
    //Main stack or Unknown 
                targetStack = mMainStack; 
            } 
            return targetStack.startActivities(caller, -1, intents, resolvedTypes, resultTo); 
  
    } 
 
    public final int startActivitiesInPackage(int uid, 
            Intent[] intents, String[] resolvedTypes, IBinder resultTo) { 
 
        // This is so super not safe, that only the system (or okay root) 
        // can do it. 
        final int callingUid = Binder.getCallingUid(); 
        if (callingUid != 0 && callingUid != Process.myUid()) { 
            throw new SecurityException( 
                    "startActivityInPackage only available to the system"); 
        } 
 
        synchronized(this) { 
   /**
    * Author: Onskreen 
    * Date: 12/01/2011 
    * 
    */
 
            int stack = getActivityStack(intents[0], resultTo); 
            ActivityStack targetStack = null
            //Cornerstone Panel 
            if(stack >= 0) { 
    if(stack < mCornerstonePanelStacks.size()) { 
     targetStack = mCornerstonePanelStacks.get(stack); 
    else { 
     Log.e(TAG, "Found in Non-Existent Stack"); 
     return -1
    
            } else if(stack == CORNERSTONE_STACK) { 
    //Cornerstone 
    targetStack = mCornerstoneStack; 
            } else if(stack == MAIN_STACK || stack == NO_STACK) { 
    //Main stack or Unknown 
                targetStack = mMainStack; 
            } 
   return targetStack.startActivities(null, uid, intents, resolvedTypes, resultTo); 
  
 
 
    final void addRecentTaskLocked(TaskRecord task) { 
        int N = mRecentTasks.size(); 
        // Quick case: check if the top-most recent task is the same. 
        if (N > 0 && mRecentTasks.get(0) == task) { 
            return
        } 
        // Remove any existing entries that are the same kind of task. 
        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); 
    } 
 
    /**
     * Author: Onskreen 
     * Date: 24/12/2011 
     * 
     * Utility method to specifically remove a task from the list of recent apps 
     * @param task 
     */
 
    final void removeRecentTaskLocked(TaskRecord task) { 
        int N = mRecentTasks.size(); 
        // Remove any existing entries that are the same kind of task. 
        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--; 
            } 
        } 
    } 
 
    public void setRequestedOrientation(IBinder token, 
            int requestedOrientation) { 
        synchronized (this) { 
   /**
    * Author: Onskreen 
    * Date: 12/01/2011 
    * 
    */
 
            int stack = getActivityStack(token); 
            ActivityStack targetStack = null
            //Cornerstone Panel 
            if(stack >= 0) { 
    if(stack < mCornerstonePanelStacks.size()) { 
     targetStack = mCornerstonePanelStacks.get(stack); 
    else { 
     Log.e(TAG, "Found in Non-Existent Stack"); 
     return
    
            } else if(stack == CORNERSTONE_STACK) { 
    //Cornerstone 
    targetStack = mCornerstoneStack; 
            } else if(stack == MAIN_STACK || stack == NO_STACK) { 
    //Main stack or Unknown 
                targetStack = mMainStack; 
            } 
            ActivityRecord r = targetStack.isInStackLocked(token); 
            if (r == null) { 
                return
            } 
            final long origId = Binder.clearCallingIdentity(); 
            mWindowManager.setAppOrientation(r.appToken, requestedOrientation); 
   /**
    * Author: Onskreen 
    * Date: 26/12/2011 
    * 
    * Using standard config logic 
    */
 
            Configuration config = mWindowManager.updateOrientationFromAppTokens( 
                    mConfiguration, 
                    r.mayFreezeScreenLocked(r.app) ? r.appToken : null); 
            if (config != null) { 
                r.frozenBeforeDestroy = true
                if (!updateConfigurationLocked(config, r, falsefalse)) { 
                    targetStack.resumeTopActivityLocked(null); 
                } 
            } 
            Binder.restoreCallingIdentity(origId); 
        } 
 
        /**ORIGINAL IMPLEMENTATION**/ 
        /**public void setRequestedOrientation(IBinder token,
                int requestedOrientation) { 
            synchronized (this) { 
                ActivityRecord r = mMainStack.isInStackLocked(token); 
                if (r == null) { 
                    return; 
                } 
                final long origId = Binder.clearCallingIdentity(); 
                mWindowManager.setAppOrientation(r.appToken, requestedOrientation); 
                Configuration config = mWindowManager.updateOrientationFromAppTokens( 
                        mConfiguration, 
                        r.mayFreezeScreenLocked(r.app) ? r.appToken : null); 
                if (config != null) { 
                    r.frozenBeforeDestroy = true; 
                    if (!updateConfigurationLocked(config, r, false, false)) { 
                        mMainStack.resumeTopActivityLocked(null); 
                    } 
                } 
                Binder.restoreCallingIdentity(origId); 
            } 
        }**/
 
    } 
 
    public int getRequestedOrientation(IBinder token) { 
        synchronized (this) { 
   /**
    * Author: Onskreen 
    * Date: 12/01/2011 
    * 
    */
 
            int stack = getActivityStack(token); 
            ActivityStack targetStack = null
            //Cornerstone Panel 
            if(stack >= 0) { 
    if(stack < mCornerstonePanelStacks.size()) { 
     targetStack = mCornerstonePanelStacks.get(stack); 
    else { 
     Log.e(TAG, "Found in Non-Existent Stack"); 
     return -1
    
   else if(stack == CORNERSTONE_STACK) { 
    //Cornerstone 
    targetStack = mCornerstoneStack; 
   else if(stack == MAIN_STACK || stack == NO_STACK) { 
    //Main stack or Unknown 
    targetStack = mMainStack; 
            } 
            ActivityRecord r = targetStack.isInStackLocked(token); 
            if (r == null) { 
                return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 
            } 
            return mWindowManager.getAppOrientation(r.appToken); 
        } 
    } 
 
    /**
     * 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. 
     *  
     * @return Returns true if the activity successfully finished, or false if it is still running. 
     */
 
    public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) { 
        // Refuse possible leaked file descriptors 
        if (resultData != null && resultData.hasFileDescriptors() == true) { 
            throw new IllegalArgumentException("File descriptors passed in Intent"); 
        } 
 
        synchronized(this) { 
   /**
    * Author: Onskreen 
    * Date: 12/01/2011 
    * 
    */
 
            int stack = getActivityStack(token); 
            ActivityStack targetStack = null
            //Cornerstone Panel 
            if(stack >= 0) { 
    if(stack < mCornerstonePanelStacks.size()) { 
     targetStack = mCornerstonePanelStacks.get(stack); 
    else { 
     Log.e(TAG, "Found in Non-Existent Stack"); 
     return false
    
            } else if(stack == CORNERSTONE_STACK) { 
    //Cornerstone 
    targetStack = mCornerstoneStack; 
            } else if(stack == MAIN_STACK || stack == NO_STACK) { 
    //Main stack or Unknown 
    targetStack = mMainStack; 
            } 
            if (mController != null) { 
                // Find the first activity that is not finishing. 
                ActivityRecord next = targetStack.topRunningActivityLocked(token, 0); 
                if (next != null) { 
                    // ask watcher if this is allowed 
                    boolean resumeOK = true
                    try { 
                        resumeOK = mController.activityResuming(next.packageName); 
                    } catch (RemoteException e) { 
                        mController = null
                    } 
 
                    if (!resumeOK) { 
                        return false
                    } 
                } 
            } 
            final long origId = Binder.clearCallingIdentity(); 
 
   /**
    * Author: Onskreen 
    * Date: 16/07/2011 
    * 
    * If cornerstone stack found, then kill the CSPanel and cornerstone panel 
    * activities and inform the WindowManagerService to set the layout as per 
    * layout config. 
    */
 
            boolean res; 
            if(targetStack == mCornerstoneStack) { 
                mActivityStackExiting = true
                for(int i = 0; i < mCornerstonePanelStacks.size(); i++){ 
                    targetStack = mCornerstonePanelStacks.get(i); 
                    for (int j = targetStack.mHistory.size()-1; j >= 0; j--) { 
                        ActivityRecord r = (ActivityRecord)targetStack.mHistory.get(j); 
                        targetStack.requestFinishActivityLocked(r.appToken.asBinder(), 0null"app-request"); 
                    } 
                } 
                res = mCornerstoneStack.requestFinishActivityLocked(token, resultCode, 
                            resultData, "app-request"); 
                mWindowManager.setCornerstoneState(WindowManagerService.Cornerstone_State.TERMINATED); 
 
    /**
     * Author: Onskreen 
     * Date: 26/12/2011 
     * 
     * Trigger the Main Stack to config itself. 
     */
 
                if(DEBUG_CONFIGURATION) { 
     Slog.i(TAG, "State: Cornerstone Exit\tAction: Config Main Panel"); 
                } 
                forceConfigurationLocked(mMainStack, WindowManagerService.Cornerstone_State.TERMINATED); 
            } else { 
                res = targetStack.requestFinishActivityLocked(token, resultCode, 
                            resultData, "app-request"); 
            } 
 
            Binder.restoreCallingIdentity(origId); 
            return res; 
        } 
    } 
 
    public final void finishHeavyWeightApp() { 
        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) 
                != PackageManager.PERMISSION_GRANTED) { 
            String msg = "Permission Denial: finishHeavyWeightApp() from pid=" 
                    + Binder.getCallingPid() 
                    + ", uid=" + Binder.getCallingUid() 
                    + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES; 
            Slog.w(TAG, msg); 
            throw new SecurityException(msg); 
        } 
 
        synchronized(this) { 
            if (mHeavyWeightProcess == null) { 
                return
            } 
 
            ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>( 
                    mHeavyWeightProcess.activities); 
            for (int i=0; i<activities.size(); i++) { 
                ActivityRecord r = activities.get(i); 
                if (!r.finishing) { 
     /**
      * Author: Onskreen 
      * Date: 27/01/2011 
      * 
      */
 
                    int stack = getActivityStack(r); 
                    ActivityStack targetStack = null
                    //Cornerstone Panel 
                    if(stack >= 0) { 
      if(stack < mCornerstonePanelStacks.size()) { 
       targetStack = mCornerstonePanelStacks.get(stack); 
      else { 
       Log.e(TAG, "Found in Non-Existent Stack"); 
       return
      
                    } else if(stack == CORNERSTONE_STACK) { 
      //Cornerstone 
      targetStack = mCornerstoneStack; 
                    } else if(stack == MAIN_STACK || stack == NO_STACK) { 
      //Main stack or Unknown 
                        targetStack = mMainStack; 
                    } 
 
                    int index = targetStack.indexOfTokenLocked(r.appToken); 
                    if (index >= 0) { 
                        targetStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED, 
                                null"finish-heavy"); 
                    } 
                } 
            } 
 
            mHeavyWeightProcess = null
            mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG); 
        } 
    } 
 
    public void crashApplication(int uid, int initialPid, String packageName, 
            String message) { 
        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) 
                != PackageManager.PERMISSION_GRANTED) { 
            String msg = "Permission Denial: crashApplication() from pid=" 
                    + Binder.getCallingPid() 
                    + ", uid=" + Binder.getCallingUid() 
                    + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES; 
            Slog.w(TAG, msg); 
            throw new SecurityException(msg); 
        } 
 
        synchronized(this) { 
            ProcessRecord proc = null
 
            // Figure out which process to kill.  We don't trust that initialPid 
            // still has any relation to current pids, so must scan through the 
            // list. 
            synchronized (mPidsSelfLocked) { 
                for (int i=0; i<mPidsSelfLocked.size(); i++) { 
                    ProcessRecord p = mPidsSelfLocked.valueAt(i); 
                    if (p.info.uid != uid) { 
                        continue
                    } 
                    if (p.pid == initialPid) { 
                        proc = p; 
                        break
                    } 
                    for (String str : p.pkgList) { 
                        if (str.equals(packageName)) { 
                            proc = p; 
                        } 
                    } 
                } 
            } 
 
            if (proc == null) { 
                Slog.w(TAG, "crashApplication: nothing for uid=" + uid 
                        + " initialPid=" + initialPid 
                        + " packageName=" + packageName); 
                return
            } 
 
            if (proc.thread != null) { 
                if (proc.pid == Process.myPid()) { 
                    Log.w(TAG, "crashApplication: trying to crash self!"); 
                    return
                } 
                long ident = Binder.clearCallingIdentity(); 
                try { 
                    proc.thread.scheduleCrash(message); 
                } catch (RemoteException e) { 
                } 
                Binder.restoreCallingIdentity(ident); 
            } 
        } 
    } 
 
    public final void finishSubActivity(IBinder token, String resultWho, 
            int requestCode) { 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   */
 
        int stack = getActivityStack(token); 
        ActivityStack targetStack = null
        //Cornerstone Panel 
        if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return
   
        } else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
        } else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
            targetStack = mMainStack; 
        } 
 
        synchronized(this) { 
            ActivityRecord self = targetStack.isInStackLocked(token); 
            if (self == null) { 
                return
            } 
 
            final long origId = Binder.clearCallingIdentity(); 
 
            int i; 
            for (i=targetStack.mHistory.size()-1; i>=0; i--) { 
                ActivityRecord r = (ActivityRecord)targetStack.mHistory.get(i); 
                if (r.resultTo == self && r.requestCode == requestCode) { 
                    if ((r.resultWho == null && resultWho == null) || 
                        (r.resultWho != null && r.resultWho.equals(resultWho))) { 
                        targetStack.finishActivityLocked(r, i, 
                                Activity.RESULT_CANCELED, null"request-sub"); 
                    } 
                } 
            } 
 
            Binder.restoreCallingIdentity(origId); 
        } 
    } 
 
    public boolean willActivityBeVisible(IBinder token) { 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   */
 
        int stack = getActivityStack(token); 
        ActivityStack targetStack = null
        //Cornerstone Panel 
        if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return false
   
        } else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
        } else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
            targetStack = mMainStack; 
        } 
 
        synchronized(this) { 
            int i; 
            for (i=targetStack.mHistory.size()-1; i>=0; i--) { 
                ActivityRecord r = (ActivityRecord)targetStack.mHistory.get(i); 
                if (r.appToken == token) { 
                    return true
                } 
                if (r.fullscreen && !r.finishing) { 
                    return false
                } 
            } 
            return true
        } 
    } 
 
    public void overridePendingTransition(IBinder token, String packageName, 
            int enterAnim, int exitAnim) { 
 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   */
 
        int stack = getActivityStack(token); 
        ActivityStack targetStack = null
        //Cornerstone Panel 
        if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return
   
        } else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
        } else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
            targetStack = mMainStack; 
        } 
 
        synchronized(this) { 
            ActivityRecord self = targetStack.isInStackLocked(token); 
            if (self == null) { 
                return
            } 
 
            final long origId = Binder.clearCallingIdentity(); 
 
            if (self.state == ActivityState.RESUMED 
                    || self.state == ActivityState.PAUSING) { 
                mWindowManager.overridePendingAppTransition(packageName, 
                        enterAnim, exitAnim); 
            } 
 
            Binder.restoreCallingIdentity(origId); 
        } 
    } 
 
    /**
     * Main function for removing an existing process from the activity manager 
     * as a result of that process going away.  Clears out all connections 
     * to the process. 
     */
 
    private final void handleAppDiedLocked(ProcessRecord app, 
            boolean restarting, boolean allowRestart) { 
 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   * Method logic moved to overloaded version. 
   */
 
  handleAppDiedLocked(app, restarting, mMainStack, allowRestart); 
  handleAppDiedLocked(app, restarting, mCornerstoneStack, allowRestart); 
 
  /**
         * Author: Onskreen 
         * Date: 17/06/2011 
         * 
         * Should be called for cornerstone panel stacks too when user forcefully 
         * kills the activities in cornerstone panel in the event of ANR or any other 
         * similar scenario. 
         */
 
  for(int i = 0; i < mCornerstonePanelStacks.size(); i++){ 
            ActivityStack targetStack = mCornerstonePanelStacks.get(i); 
            handleAppDiedLocked(app, restarting, targetStack, allowRestart); 
        } 
    } 
 
    /**
     * Author: Onskreen 
     * Date: 27/01/2011 
     * 
     * Replica of handleAppDiedLocked which acts on a specific ActivityStack. 
     * @param app 
     * @param restarting 
     * @param currStack 
     */
 
    private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, ActivityStack currStack, 
 boolean allowRestart) { 
 
        cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1); 
        if (!restarting) { 
            mLruProcesses.remove(app); 
        } 
 
        if (mProfileProc == app) { 
            clearProfilerLocked(); 
        } 
 
        // Just in case... 
        if (currStack.mPausingActivity != null && currStack.mPausingActivity.app == app) { 
            if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +currStack.mPausingActivity); 
            currStack.mPausingActivity = null
        } 
        if (currStack.mLastPausedActivity != null && currStack.mLastPausedActivity.app == app) { 
            currStack.mLastPausedActivity = null
        } 
 
        // Remove this application's activities from active lists. 
        currStack.removeHistoryRecordsForAppLocked(app); 
 
        boolean atTop = true
        boolean hasVisibleActivities = false
 
        // Clean out the history list. 
        int i = currStack.mHistory.size(); 
        if (localLOGV) Slog.v( 
            TAG, "Removing app " + app + " from history with " + i + " entries"); 
        while (i > 0) { 
            i--; 
            ActivityRecord r = (ActivityRecord)currStack.mHistory.get(i); 
            if (localLOGV) Slog.v( 
                TAG, "Record #" + i + " " + r + ": app=" + r.app); 
            if (r.app == app) { 
                if ((!r.haveState && !r.stateNotNeeded) || r.finishing) { 
                    if (ActivityStack.DEBUG_ADD_REMOVE) { 
                        RuntimeException here = new RuntimeException("here"); 
                        here.fillInStackTrace(); 
                        Slog.i(TAG, "Removing activity " + r + " from stack at " + i 
                                + ": haveState=" + r.haveState 
                                + " stateNotNeeded=" + r.stateNotNeeded 
                                + " finishing=" + r.finishing 
                                + " state=" + r.state, here); 
                    } 
                    if (!r.finishing) { 
                        Slog.w(TAG, "Force removing " + r + ": app died, no saved state"); 
                        EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY, 
                                System.identityHashCode(r), 
                                r.task.taskId, r.shortComponentName, 
                                "proc died without state saved"); 
                    } 
                    r.makeFinishing(); 
                    currStack.mHistory.remove(i); 
                    r.takeFromHistory(); 
                    mWindowManager.removeAppToken(r.appToken); 
                    if (VALIDATE_TOKENS) { 
                        currStack.validateAppTokensLocked(); 
                    } 
                    r.removeUriPermissionsLocked(); 
 
                } else { 
                    // We have the current state for this activity, so 
                    // it can be restarted later when needed. 
                    if (localLOGV) Slog.v( 
                        TAG, "Keeping entry, setting app to null"); 
                    if (r.visible) { 
                        hasVisibleActivities = true
                    } 
                    r.app = null
                    r.nowVisible = false
                    if (!r.haveState) { 
                        if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG, 
                                "App died, clearing saved state of " + r); 
                        r.icicle = null
                    } 
                } 
 
                r.stack.cleanUpActivityLocked(r, truetrue); 
            } 
            atTop = false
        } 
 
        app.activities.clear(); 
 
        if (app.instrumentationClass != null) { 
            Slog.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 (!currStack.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) { 
                    currStack.ensureActivitiesVisibleLocked(null0); 
                } 
            } 
        } 
    } 
 
    private final int getLRURecordIndexForAppLocked(IApplicationThread thread) { 
        IBinder threadBinder = thread.asBinder(); 
 
        // Find the application record. 
        for (int i=mLruProcesses.size()-1; i>=0; i--) { 
            ProcessRecord rec = mLruProcesses.get(i); 
            if (rec.thread != null && rec.thread.asBinder() == threadBinder) { 
                return i; 
            } 
        } 
        return -1
    } 
 
    final ProcessRecord getRecordForAppLocked
            IApplicationThread thread) { 
        if (thread == null) { 
            return null
        } 
 
        int appIndex = getLRURecordIndexForAppLocked(thread); 
        return appIndex >= 0 ? mLruProcesses.get(appIndex) : null
    } 
 
    final void appDiedLocked(ProcessRecord app, int pid, 
            IApplicationThread thread) { 
 
        mProcDeaths[0]++; 
 
        BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); 
        synchronized (stats) { 
            stats.noteProcessDiedLocked(app.info.uid, pid); 
        } 
 
        // Clean up already done if the process has been re-started. 
        if (app.pid == pid && app.thread != null && 
                app.thread.asBinder() == thread.asBinder()) { 
            if (!app.killedBackground) { 
                Slog.i(TAG, "Process " + app.processName + " (pid " + pid 
                        + ") has died."); 
            } 
            EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName); 
            if (localLOGV) Slog.v( 
                TAG, "Dying app: " + app + ", pid: " + pid 
                + ", thread: " + thread.asBinder()); 
            boolean doLowMem = app.instrumentationClass == null
            handleAppDiedLocked(app, falsetrue); 
 
            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
                for (int i=mLruProcesses.size()-1; i>=0; i--) { 
                    ProcessRecord rec = mLruProcesses.get(i); 
                    if (rec.thread != null && rec.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) { 
                        haveBg = true
                        break
                    } 
                } 
 
                if (!haveBg) { 
                    EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size()); 
                    long now = SystemClock.uptimeMillis(); 
                    for (int i=mLruProcesses.size()-1; i>=0; i--) { 
                        ProcessRecord rec = mLruProcesses.get(i); 
                        if (rec != app && rec.thread != null && 
                                (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) { 
                            // The low memory report is overriding any current 
                            // state for a GC request.  Make sure to do 
                            // heavy/important/visible/foreground processes first. 
                            if (rec.setAdj <= ProcessList.HEAVY_WEIGHT_APP_ADJ) { 
                                rec.lastRequestedGc = 0
                            } else { 
                                rec.lastRequestedGc = rec.lastLowMemory; 
                            } 
                            rec.reportLowMemory = true
                            rec.lastLowMemory = now; 
                            mProcessesToGc.remove(rec); 
                            addProcessToGcListLocked(rec); 
                        } 
                    } 
                    mHandler.sendEmptyMessage(REPORT_MEM_USAGE); 
                    scheduleAppGcsLocked(); 
                } 
            } 
        } else if (app.pid != pid) { 
            // A new process has already been started. 
            Slog.i(TAG, "Process " + app.processName + " (pid " + pid 
                    + ") has died and restarted (pid " + app.pid + ")."); 
            EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName); 
        } else if (DEBUG_PROCESSES) { 
            Slog.d(TAG, "Received spurious death notification for thread " 
                    + thread.asBinder()); 
        } 
    } 
 
    /**
     * If a stack trace dump file is configured, dump process stack traces. 
     * @param clearTraces causes the dump file to be erased prior to the new 
     *    traces being written, if true; when false, the new traces will be 
     *    appended to any existing file content. 
     * @param firstPids of dalvik VM processes to dump stack traces for first 
     * @param lastPids of dalvik VM processes to dump stack traces for last 
     * @return file containing stack traces, or null if no dump file is configured 
     */
 
    public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids, 
            ProcessStats processStats, SparseArray<Boolean> lastPids) { 
        String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file"null); 
        if (tracesPath == null || tracesPath.length() == 0) { 
            return null
        } 
 
        File tracesFile = new File(tracesPath); 
        try { 
            File tracesDir = tracesFile.getParentFile(); 
            if (!tracesDir.exists()) tracesFile.mkdirs(); 
            FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1);  // drwxrwxr-x 
 
            if (clearTraces && tracesFile.exists()) tracesFile.delete(); 
            tracesFile.createNewFile(); 
            FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw- 
        } catch (IOException e) { 
            Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e); 
            return null
        } 
 
        // Use a FileObserver to detect when traces finish writing. 
        // The order of traces is considered important to maintain for legibility. 
        FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) { 
            public synchronized void onEvent(int event, String path) { notify(); } 
        }; 
 
        try { 
            observer.startWatching(); 
 
            // First collect all of the stacks of the most important pids. 
            try { 
                int num = firstPids.size(); 
                for (int i = 0; i < num; i++) { 
                    synchronized (observer) { 
                        Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT); 
                        observer.wait(200);  // Wait for write-close, give up after 200msec 
                    } 
                } 
            } catch (InterruptedException e) { 
                Log.wtf(TAG, e); 
            } 
 
            // Next measure CPU usage. 
            if (processStats != null) { 
                processStats.init(); 
                System.gc(); 
                processStats.update(); 
                try { 
                    synchronized (processStats) { 
                        processStats.wait(500); // measure over 1/2 second. 
                    } 
                } catch (InterruptedException e) { 
                } 
                processStats.update(); 
 
                // We'll take the stack crawls of just the top apps using CPU. 
                final int N = processStats.countWorkingStats(); 
                int numProcs = 0
                for (int i=0; i<N && numProcs<5; i++) { 
                    ProcessStats.Stats stats = processStats.getWorkingStats(i); 
                    if (lastPids.indexOfKey(stats.pid) >= 0) { 
                        numProcs++; 
                        try { 
                            synchronized (observer) { 
                                Process.sendSignal(stats.pid, Process.SIGNAL_QUIT); 
                                observer.wait(200);  // Wait for write-close, give up after 200msec 
                            } 
                        } catch (InterruptedException e) { 
                            Log.wtf(TAG, e); 
                        } 
 
                    } 
                } 
            } 
 
            return tracesFile; 
 
        } finally { 
            observer.stopWatching(); 
        } 
    } 
 
    private final class AppNotResponding implements Runnable { 
        private final ProcessRecord mApp; 
        private final String mAnnotation; 
 
        public AppNotResponding(ProcessRecord app, String annotation) { 
            mApp = app; 
            mAnnotation = annotation; 
        } 
 
        @Override 
        public void run() { 
            appNotResponding(mApp, nullnull, mAnnotation); 
        } 
    } 
 
    final void appNotResponding(ProcessRecord app, ActivityRecord activity, 
            ActivityRecord parent, final String annotation) { 
        ArrayList<Integer> firstPids = new ArrayList<Integer>(5); 
        SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20); 
 
        if (mController != null) { 
            try { 
                // 0 == continue, -1 = kill process immediately 
                int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation); 
                if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid); 
            } catch (RemoteException e) { 
                mController = null
            } 
        } 
 
        long anrTime = SystemClock.uptimeMillis(); 
        if (MONITOR_CPU_USAGE) { 
            updateCpuStatsNow(); 
        } 
 
        synchronized (this) { 
            // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down. 
            if (mShuttingDown) { 
                Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation); 
                return
            } else if (app.notResponding) { 
                Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation); 
                return
            } else if (app.crashing) { 
                Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation); 
                return
            } 
 
            // In case we come through here for the same app before completing 
            // this one, mark as anring now so we will bail out. 
            app.notResponding = true
 
            // Log the ANR to the event log. 
            EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags, 
                    annotation); 
 
            // Dump thread traces as quickly as we can, starting with "interesting" processes. 
            firstPids.add(app.pid); 
 
            int parentPid = app.pid; 
            if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid; 
            if (parentPid != app.pid) firstPids.add(parentPid); 
 
            if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID); 
 
            for (int i = mLruProcesses.size() - 1; i >= 0; i--) { 
                ProcessRecord r = mLruProcesses.get(i); 
                if (r != null && r.thread != null) { 
                    int pid = r.pid; 
                    if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) { 
                        if (r.persistent) { 
                            firstPids.add(pid); 
                        } else { 
                            lastPids.put(pid, Boolean.TRUE); 
                        } 
                    } 
                } 
            } 
        } 
 
        // Log the ANR to the main log. 
        StringBuilder info = mStringBuilder; 
        info.setLength(0); 
        info.append("ANR in ").append(app.processName); 
        if (activity != null && activity.shortComponentName != null) { 
            info.append(" (").append(activity.shortComponentName).append(")"); 
        } 
        info.append("\n"); 
        if (annotation != null) { 
            info.append("Reason: ").append(annotation).append("\n"); 
        } 
        if (parent != null && parent != activity) { 
            info.append("Parent: ").append(parent.shortComponentName).append("\n"); 
        } 
 
        final ProcessStats processStats = new ProcessStats(true); 
 
        File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids); 
 
        String cpuInfo = null
        if (MONITOR_CPU_USAGE) { 
            updateCpuStatsNow(); 
            synchronized (mProcessStatsThread) { 
                cpuInfo = mProcessStats.printCurrentState(anrTime); 
            } 
            info.append(processStats.printCurrentLoad()); 
            info.append(cpuInfo); 
        } 
 
        info.append(processStats.printCurrentState(anrTime)); 
 
        Slog.e(TAG, info.toString()); 
        if (tracesFile == null) { 
            // There is no trace file, so dump (only) the alleged culprit's threads to the log 
            Process.sendSignal(app.pid, Process.SIGNAL_QUIT); 
        } 
 
        addErrorToDropBox("anr", app, app.processName, activity, parent, annotation, 
                cpuInfo, tracesFile, null); 
 
        if (mController != null) { 
            try { 
                // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately 
                int res = mController.appNotResponding(app.processName, app.pid, info.toString()); 
                if (res != 0) { 
                    if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid); 
                    return
                } 
            } catch (RemoteException e) { 
                mController = null
            } 
        } 
 
        // Unless configured otherwise, swallow ANRs in background processes & kill the process. 
        boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), 
                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0
 
        synchronized (this) { 
            if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) { 
                Slog.w(TAG, "Killing " + app + ": background ANR"); 
                EventLog.writeEvent(EventLogTags.AM_KILL, app.pid, 
                        app.processName, app.setAdj, "background ANR"); 
                Process.killProcessQuiet(app.pid); 
                return
            } 
 
            // Set the app's notResponding state, and look up the errorReportReceiver 
            makeAppNotRespondingLocked(app, 
                    activity != null ? activity.shortComponentName : null
                    annotation != null ? "ANR " + annotation : "ANR"
                    info.toString()); 
 
            // Bring up the infamous App Not Responding dialog 
            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); 
        } 
    } 
 
    final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) { 
        if (!mLaunchWarningShown) { 
            mLaunchWarningShown = true
            mHandler.post(new Runnable() { 
                @Override 
                public void run() { 
                    synchronized (ActivityManagerService.this) { 
                        final Dialog d = new LaunchWarningWindow(mContext, cur, next); 
                        d.show(); 
                        mHandler.postDelayed(new Runnable() { 
                            @Override 
                            public void run() { 
                                synchronized (ActivityManagerService.this) { 
                                    d.dismiss(); 
                                    mLaunchWarningShown = false
                                } 
                            } 
                        }, 4000); 
                    } 
                } 
            }); 
        } 
    } 
 
    public boolean clearApplicationUserData(final String packageName, 
            final IPackageDataObserver observer) { 
        int uid = Binder.getCallingUid(); 
        int pid = Binder.getCallingPid(); 
        long callingId = Binder.clearCallingIdentity(); 
        try { 
            IPackageManager pm = AppGlobals.getPackageManager(); 
            int pkgUid = -1
            synchronized(this) { 
                try { 
                    pkgUid = pm.getPackageUid(packageName); 
                } catch (RemoteException e) { 
                } 
                if (pkgUid == -1) { 
                    Slog.w(TAG, "Invalid packageName:" + packageName); 
                    return false
                } 
                if (uid == pkgUid || checkComponentPermission( 
                        android.Manifest.permission.CLEAR_APP_USER_DATA, 
                        pid, uid, -1true
                        == PackageManager.PERMISSION_GRANTED) { 
                    forceStopPackageLocked(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); 
                broadcastIntentInPackage("android", Process.SYSTEM_UID, intent, 
                        nullnull0nullnullnullfalsefalse); 
            } catch (RemoteException e) { 
            } 
        } finally { 
            Binder.restoreCallingIdentity(callingId); 
        } 
        return true
    } 
 
    public void killBackgroundProcesses(final String packageName) { 
        if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES) 
                != PackageManager.PERMISSION_GRANTED && 
                checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES) 
                        != PackageManager.PERMISSION_GRANTED) { 
            String msg = "Permission Denial: killBackgroundProcesses() from pid=" 
                    + Binder.getCallingPid() 
                    + ", uid=" + Binder.getCallingUid() 
                    + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES; 
            Slog.w(TAG, msg); 
            throw new SecurityException(msg); 
        } 
 
        long callingId = Binder.clearCallingIdentity(); 
        try { 
            IPackageManager pm = AppGlobals.getPackageManager(); 
            int pkgUid = -1
            synchronized(this) { 
                try { 
                    pkgUid = pm.getPackageUid(packageName); 
                } catch (RemoteException e) { 
                } 
                if (pkgUid == -1) { 
                    Slog.w(TAG, "Invalid packageName: " + packageName); 
                    return
                } 
                killPackageProcessesLocked(packageName, pkgUid, 
                        ProcessList.SERVICE_ADJ, falsetruetruefalse"kill background"); 
            } 
        } finally { 
            Binder.restoreCallingIdentity(callingId); 
        } 
    } 
 
    public void killAllBackgroundProcesses() { 
        if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES) 
                != PackageManager.PERMISSION_GRANTED) { 
            String msg = "Permission Denial: killAllBackgroundProcesses() from pid=" 
                    + Binder.getCallingPid() 
                    + ", uid=" + Binder.getCallingUid() 
                    + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES; 
            Slog.w(TAG, msg); 
            throw new SecurityException(msg); 
        } 
 
        long callingId = Binder.clearCallingIdentity(); 
        try { 
            synchronized(this) { 
                ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(); 
                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.persistent) { 
                            // we don't kill persistent processes 
                            continue
                        } 
                        if (app.removed) { 
                            procs.add(app); 
                        } else if (app.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) { 
                            app.removed = true
                            procs.add(app); 
                        } 
                    } 
                } 
 
                int N = procs.size(); 
                for (int i=0; i<N; i++) { 
                    removeProcessLocked(procs.get(i), falsetrue"kill all background"); 
                } 
            } 
        } finally { 
            Binder.restoreCallingIdentity(callingId); 
        } 
    } 
 
    public void forceStopPackage(final String packageName) { 
        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) 
                != PackageManager.PERMISSION_GRANTED) { 
            String msg = "Permission Denial: forceStopPackage() from pid=" 
                    + Binder.getCallingPid() 
                    + ", uid=" + Binder.getCallingUid() 
                    + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES; 
            Slog.w(TAG, msg); 
            throw new SecurityException(msg); 
        } 
 
        long callingId = Binder.clearCallingIdentity(); 
        try { 
            IPackageManager pm = AppGlobals.getPackageManager(); 
            int pkgUid = -1
            synchronized(this) { 
                try { 
                    pkgUid = pm.getPackageUid(packageName); 
                } catch (RemoteException e) { 
                } 
                if (pkgUid == -1) { 
                    Slog.w(TAG, "Invalid packageName: " + packageName); 
                    return
                } 
                forceStopPackageLocked(packageName, pkgUid); 
                try { 
                    pm.setPackageStoppedState(packageName, true); 
                } catch (RemoteException e) { 
                } catch (IllegalArgumentException e) { 
                    Slog.w(TAG, "Failed trying to unstop package " 
                            + packageName + ": " + e); 
                } 
            } 
        } finally { 
            Binder.restoreCallingIdentity(callingId); 
        } 
    } 
 
    /*
     * The pkg name and uid have to be specified. 
     * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int) 
     */
 
    public void killApplicationWithUid(String pkg, int uid) { 
        if (pkg == null) { 
            return
        } 
        // Make sure the uid is valid. 
        if (uid < 0) { 
            Slog.w(TAG, "Invalid uid specified for pkg : " + pkg); 
            return
        } 
        int callerUid = Binder.getCallingUid(); 
        // Only the system server can kill an application 
        if (callerUid == Process.SYSTEM_UID) { 
            // Post an aysnc message to kill the application 
            Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG); 
            msg.arg1 = uid; 
            msg.arg2 = 0
            msg.obj = pkg; 
            mHandler.sendMessage(msg); 
        } else { 
            throw new SecurityException(callerUid + " cannot kill pkg: " + 
                    pkg); 
        } 
    } 
 
    public void closeSystemDialogs(String reason) { 
        Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 
        if (reason != null) { 
            intent.putExtra("reason", reason); 
        } 
 
        final int uid = Binder.getCallingUid(); 
        final long origId = Binder.clearCallingIdentity(); 
        synchronized (this) { 
            int i = mWatchers.beginBroadcast(); 
            while (i > 0) { 
                i--; 
                IActivityWatcher w = mWatchers.getBroadcastItem(i); 
                if (w != null) { 
                    try { 
                        w.closingSystemDialogs(reason); 
                    } catch (RemoteException e) { 
                    } 
                } 
            } 
            mWatchers.finishBroadcast(); 
 
            mWindowManager.closeSystemDialogs(reason); 
 
            for (i=mMainStack.mHistory.size()-1; i>=0; i--) { 
                ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i); 
                if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) { 
                    r.stack.finishActivityLocked(r, i, 
                            Activity.RESULT_CANCELED, null"close-sys"); 
                } 
            } 
 
   /**
    * Author: Onskreen 
    * Date: 27/01/2011 
    * 
    * Replicating logic for cornerstone stack 
    */
 
            for (i=mCornerstoneStack.mHistory.size()-1; i>=0; i--) { 
                ActivityRecord r = (ActivityRecord)mCornerstoneStack.mHistory.get(i); 
                if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) { 
                    r.stack.finishActivityLocked(r, i, 
                            Activity.RESULT_CANCELED, null"close-sys"); 
                } 
            } 
 
            broadcastIntentLocked(nullnull, intent, null
                    null0nullnullnullfalsefalse, -1, uid); 
        } 
        Binder.restoreCallingIdentity(origId); 
    } 
 
    public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids) 
            throws RemoteException { 
        Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length]; 
        for (int i=pids.length-1; i>=0; i--) { 
            infos[i] = new Debug.MemoryInfo(); 
            Debug.getMemoryInfo(pids[i], infos[i]); 
        } 
        return infos; 
    } 
 
    public long[] getProcessPss(int[] pids) throws RemoteException { 
        long[] pss = new long[pids.length]; 
        for (int i=pids.length-1; i>=0; i--) { 
            pss[i] = Debug.getPss(pids[i]); 
        } 
        return pss; 
    } 
 
    public void killApplicationProcess(String processName, int uid) { 
        if (processName == null) { 
            return
        } 
 
        int callerUid = Binder.getCallingUid(); 
        // Only the system server can kill an application 
        if (callerUid == Process.SYSTEM_UID) { 
            synchronized (this) { 
                ProcessRecord app = getProcessRecordLocked(processName, uid); 
                if (app != null && app.thread != null) { 
                    try { 
                        app.thread.scheduleSuicide(); 
                    } catch (RemoteException e) { 
                        // If the other end already died, then our work here is done. 
                    } 
                } else { 
                    Slog.w(TAG, "Process/uid not found attempting kill of " 
                            + processName + " / " + uid); 
                } 
            } 
        } else { 
            throw new SecurityException(callerUid + " cannot kill app process: " + 
                    processName); 
        } 
    } 
 
    private void forceStopPackageLocked(final String packageName, int uid) { 
        forceStopPackageLocked(packageName, uid, falsefalsetruefalse); 
        Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED, 
                Uri.fromParts("package", packageName, null)); 
        if (!mProcessesReady) { 
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 
        } 
        intent.putExtra(Intent.EXTRA_UID, uid); 
        broadcastIntentLocked(nullnull, intent, 
                nullnull0nullnullnull
                falsefalse, MY_PID, Process.SYSTEM_UID); 
    } 
 
    private final boolean killPackageProcessesLocked(String packageName, int uid, 
            int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit, 
            boolean evenPersistent, String reason) { 
        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. 
        final String procNamePrefix = packageName + ":"
        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.persistent && !evenPersistent) { 
                    // we don't kill persistent processes 
                    continue
                } 
                if (app.removed) { 
                    if (doit) { 
                        procs.add(app); 
                    } 
                } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid) 
                        || app.processName.equals(packageName) 
                        || app.processName.startsWith(procNamePrefix)) { 
                    if (app.setAdj >= minOomAdj) { 
                        if (!doit) { 
                            return true
                        } 
                        app.removed = true
                        procs.add(app); 
                    } 
                } 
            } 
        } 
 
        int N = procs.size(); 
        for (int i=0; i<N; i++) { 
            removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason); 
        } 
        return N > 0
    } 
 
    private final boolean forceStopPackageLocked(String name, int uid, 
            boolean callerWillRestart, boolean purgeCache, boolean doit, 
            boolean evenPersistent) { 
        int i; 
        int N; 
 
        if (uid < 0) { 
            try { 
                uid = AppGlobals.getPackageManager().getPackageUid(name); 
            } catch (RemoteException e) { 
            } 
        } 
 
        if (doit) { 
            Slog.i(TAG, "Force stopping package " + name + " uid=" + uid); 
 
            Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator(); 
            while (badApps.hasNext()) { 
                SparseArray<Long> ba = badApps.next(); 
                if (ba.get(uid) != null) { 
                    badApps.remove(); 
                } 
            } 
        } 
 
        boolean didSomething = killPackageProcessesLocked(name, uid, -100
                callerWillRestart, false, doit, evenPersistent, "force stop"); 
 
        TaskRecord lastTask = null
        for (i=0; i<mMainStack.mHistory.size(); i++) { 
            ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i); 
            final boolean samePackage = r.packageName.equals(name); 
            if ((samePackage || r.task == lastTask) 
                    && (r.app == null || evenPersistent || !r.app.persistent)) { 
                if (!doit) { 
                    if (r.finishing) { 
                        // If this activity is just finishing, then it is not 
                        // interesting as far as something to stop. 
                        continue
                    } 
                    return true
                } 
                didSomething = true
                Slog.i(TAG, "  Force finishing activity " + r); 
                if (samePackage) { 
                    if (r.app != null) { 
                        r.app.removed = true
                    } 
                    r.app = null
                } 
                lastTask = r.task; 
                if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, 
                        null"force-stop")) { 
                    i--; 
                } 
            } 
        } 
 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   * Mirroing logic in cornerstone. 
   */
 
        for (i=mCornerstoneStack.mHistory.size()-1; i>=0; i--) { 
            ActivityRecord r = (ActivityRecord)mCornerstoneStack.mHistory.get(i); 
            if (r.packageName.equals(name)) { 
                if (!doit) { 
                    return true
                } 
                didSomething = true
                Slog.i(TAG, "  Force finishing activity " + r); 
                if (r.app != null) { 
                    r.app.removed = true
                } 
                r.app = null
                r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null"uninstall"); 
            } 
        } 
 
        ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>(); 
        for (ServiceRecord service : mServices.values()) { 
            if (service.packageName.equals(name) 
                    && (service.app == null || evenPersistent || !service.app.persistent)) { 
                if (!doit) { 
                    return true
                } 
                didSomething = true
                Slog.i(TAG, "  Force stopping service " + service); 
                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); 
        } 
 
        ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>(); 
        for (ContentProviderRecord provider : mProvidersByClass.values()) { 
            if (provider.info.packageName.equals(name) 
                    && (provider.proc == null || evenPersistent || !provider.proc.persistent)) { 
                if (!doit) { 
                    return true
                } 
                didSomething = true
                providers.add(provider); 
            } 
        } 
 
        N = providers.size(); 
        for (i=0; i<N; i++) { 
            removeDyingProviderLocked(null, providers.get(i)); 
        } 
 
        if (doit) { 
            if (purgeCache) { 
                AttributeCache ac = AttributeCache.instance(); 
                if (ac != null) { 
                    ac.removePackage(name); 
                } 
            } 
            if (mBooted) { 
                mMainStack.resumeTopActivityLocked(null); 
                mMainStack.scheduleIdleLocked(); 
 
   /**
    * Author: Onskreen 
    * Date: 27/01/2011 
    * 
    * Mirroing logic in cornerstone. 
    */
 
                mCornerstoneStack.resumeTopActivityLocked(null); 
                mCornerstoneStack.scheduleIdleLocked(); 
            } 
        } 
 
        return didSomething; 
    } 
 
    private final boolean removeProcessLocked(ProcessRecord app, 
            boolean callerWillRestart, boolean allowRestart, String reason) { 
        final String name = app.processName; 
        final int uid = app.info.uid; 
        if (DEBUG_PROCESSES) Slog.d( 
            TAG, "Force removing proc " + app.toShortString() + " (" + name 
            + "/" + uid + ")"); 
 
        mProcessNames.remove(name, uid); 
        if (mHeavyWeightProcess == app) { 
            mHeavyWeightProcess = null
            mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG); 
        } 
        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); 
            } 
            Slog.i(TAG, "Killing proc " + app.toShortString() + ": " + reason); 
            handleAppDiedLocked(app, true, allowRestart); 
            mLruProcesses.remove(app); 
            Process.killProcessQuiet(pid); 
 
            if (app.persistent) { 
                if (!callerWillRestart) { 
                    addAppLocked(app.info); 
                } else { 
                    needRestart = true
                } 
            } 
        } else { 
            mRemovedProcesses.add(app); 
        } 
 
        return needRestart; 
    } 
 
    private final void processStartTimedOutLocked(ProcessRecord app) { 
        final int pid = app.pid; 
        boolean gone = false
        synchronized (mPidsSelfLocked) { 
            ProcessRecord knownApp = mPidsSelfLocked.get(pid); 
            if (knownApp != null && knownApp.thread == null) { 
                mPidsSelfLocked.remove(pid); 
                gone = true
            }         
        } 
 
        if (gone) { 
            Slog.w(TAG, "Process " + app + " failed to attach"); 
            EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid, 
                    app.processName); 
            mProcessNames.remove(app.processName, app.info.uid); 
            if (mHeavyWeightProcess == app) { 
                mHeavyWeightProcess = null
                mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG); 
            } 
            // Take care of any launching providers waiting for this process. 
            checkAppInLaunchingProvidersLocked(app, true); 
            // Take care of any services that are waiting for the process. 
            for (int i=0; i<mPendingServices.size(); i++) { 
                ServiceRecord sr = mPendingServices.get(i); 
                if (app.info.uid == sr.appInfo.uid 
                        && app.processName.equals(sr.processName)) { 
                    Slog.w(TAG, "Forcing bringing down service: " + sr); 
                    mPendingServices.remove(i); 
                    i--; 
                    bringDownServiceLocked(sr, true); 
                } 
            } 
            EventLog.writeEvent(EventLogTags.AM_KILL, pid, 
                    app.processName, app.setAdj, "start timeout"); 
            Process.killProcessQuiet(pid); 
            if (mBackupTarget != null && mBackupTarget.app.pid == pid) { 
                Slog.w(TAG, "Unattached app died before backup, skipping"); 
                try { 
                    IBackupManager bm = IBackupManager.Stub.asInterface( 
                            ServiceManager.getService(Context.BACKUP_SERVICE)); 
                    bm.agentDisconnected(app.info.packageName); 
                } catch (RemoteException e) { 
                    // Can't happen; the backup manager is local 
                } 
            } 
            if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) { 
                Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping"); 
                mPendingBroadcast.state = BroadcastRecord.IDLE; 
                mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex; 
                mPendingBroadcast = null
                scheduleBroadcastsLocked(); 
            } 
        } else { 
            Slog.w(TAG, "Spurious process start timeout - pid not known for " + app); 
        } 
    } 
 
    private final boolean attachApplicationLocked(IApplicationThread thread, 
            int pid) { 
 
        // Find the application record that is being attached...  either via 
        // the pid if we are running in multiple processes, or just pull the 
        // next app record if we are emulating process with anonymous threads. 
        ProcessRecord app; 
        if (pid != MY_PID && pid >= 0) { 
            synchronized (mPidsSelfLocked) { 
                app = mPidsSelfLocked.get(pid); 
            } 
        } else { 
            app = null
        } 
 
        if (app == null) { 
            Slog.w(TAG, "No pending application record for pid " + pid 
                    + " (IApplicationThread " + thread + "); dropping process"); 
            EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid); 
            if (pid > 0 && pid != MY_PID) { 
                Process.killProcessQuiet(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, truetrue); 
        } 
 
        // Tell the process all about itself. 
 
        if (localLOGV) Slog.v( 
                TAG, "Binding process pid " + pid + " to record " + app); 
 
        String processName = app.processName; 
        try { 
            AppDeathRecipient adr = new AppDeathRecipient( 
                    app, pid, thread); 
            thread.asBinder().linkToDeath(adr, 0); 
            app.deathRecipient = adr; 
        } catch (RemoteException e) { 
            app.resetPackageList(); 
            startProcessLocked(app, "link fail", processName); 
            return false
        } 
 
        EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName); 
         
        app.thread = thread; 
        app.curAdj = app.setAdj = -100
        app.curSchedGroup = Process.THREAD_GROUP_DEFAULT; 
        app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; 
        app.forcingToForeground = null
        app.foregroundServices = false
        app.hasShownUi = false
        app.debugging = false
 
        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); 
 
        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info); 
        List providers = normalMode ? generateApplicationProvidersLocked(app) : null
 
        if (!normalMode) { 
            Slog.i(TAG, "Launching preboot mode app: " + app); 
        } 
 
        if (localLOGV) Slog.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; 
                } 
            } 
            String profileFile = app.instrumentationProfileFile; 
            ParcelFileDescriptor profileFd = null
            boolean profileAutoStop = false
            if (mProfileApp != null && mProfileApp.equals(processName)) { 
                mProfileProc = app; 
                profileFile = mProfileFile; 
                profileFd = mProfileFd; 
                profileAutoStop = mAutoStopProfiler; 
            } 
 
            // If the app is being launched for restore or full backup, set it up specially 
            boolean isRestrictedBackupMode = false
            if (mBackupTarget != null && mBackupAppName.equals(processName)) { 
                isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE) 
                        || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL) 
                        || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL); 
            } 
 
            ensurePackageDexOpt(app.instrumentationInfo != null 
                    ? app.instrumentationInfo.packageName 
                    : app.info.packageName); 
            if (app.instrumentationClass != null) { 
                ensurePackageDexOpt(app.instrumentationClass.getPackageName()); 
            } 
 
   /**
    * Author: Onskreen 
    * Date: 26/12/2011 
    * 
    * The ActivityRecord is in the mHistory at this point, but has not been attached to a ProcessRecord 
    * as of yet. 
    * TODO There has to be a better way to find the candidate. 
    * 
    */
 
            //Check Main Stack 
            Configuration wpConfig = null
            for(ActivityRecord ar: mMainStack.mHistory) { 
    if(ar.app == null) { 
     wpConfig = mWindowManager.computeWindowPanelConfiguration(WindowManagerService.WP_Panel.MAIN_PANEL); 
     break
    
            } 
            if(wpConfig == null) { 
    //Check CS Stacks 
    for(ActivityStack as: mCornerstonePanelStacks) { 
     for(ActivityRecord ar: as.mHistory) { 
      if(ar.app == null) { 
       if(as.mCornerstonePanelIndex == 0) { 
        wpConfig = mWindowManager.computeWindowPanelConfiguration(WindowManagerService.WP_Panel.CS_APP_0); 
       else { 
        wpConfig = mWindowManager.computeWindowPanelConfiguration(WindowManagerService.WP_Panel.CS_APP_1); 
       
       break
      
     
     if(wpConfig != null) { 
      break
     
    
            } 
            // 
   /**
    * Author: Onskreen 
    * TEST - Why isn't CSPanel in the activitystack before getting here? 
    */
 
           /** if(wpConfig == null) {
                for(ActivityRecord ar: mCornerstoneStack.mHistory) { 
     if(ar.app == null) { 
      wpConfig = mWindowManager.computeWindowPanelConfiguration(WindowManagerService.WP_Panel.CORNERSTONE); 
      break; 
     
                } 
            }**/
 
 
            Configuration configToUse; 
            if(wpConfig != null) { 
    configToUse = wpConfig; 
            } else { 
    /**
     * Author: Onskreen 
     * Date: 05/01/2012 
     * 
     */
 
    configToUse = mConfiguration; 
            } 
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc " 
                    + processName + " with config " +configToUse /**mConfiguration**/); 
 
            ApplicationInfo appInfo = app.instrumentationInfo != null 
                    ? app.instrumentationInfo : app.info; 
            app.compat = compatibilityInfoForPackageLocked(appInfo); 
            if (profileFd != null) { 
                profileFd = profileFd.dup(); 
            } 
            thread.bindApplication(processName, appInfo, providers, 
                    app.instrumentationClass, profileFile, profileFd, profileAutoStop, 
                    app.instrumentationArguments, app.instrumentationWatcher, testMode,  
                    isRestrictedBackupMode || !normalMode, app.persistent, 
                    new Configuration(configToUse /**mConfiguration**/), app.compat, getCommonServicesLocked(), 
                    mCoreSettingsObserver.getCoreSettingsLocked()); 
            updateLruProcessLocked(app, falsetrue); 
            app.lastRequestedGc = app.lastLowMemory = 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... 
            Slog.w(TAG, "Exception thrown during bind!", e); 
 
            app.resetPackageList(); 
            app.unlinkDeathRecipient(); 
            startProcessLocked(app, "bind fail", processName); 
            return false
        } 
 
        // Remove this record from the list of starting applications. 
        mPersistentStartingProcesses.remove(app); 
        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG, 
                "Attach application locked removing on hold: " + app); 
        mProcessesOnHold.remove(app); 
 
        boolean badApp = false
        boolean didSomething = false
 
        // See if the top visible activity is waiting to run in this process... 
        ActivityRecord hr = mMainStack.topRunningActivityLocked(null); 
        if (hr != null && normalMode) { 
            if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid 
                    && processName.equals(hr.processName)) { 
                try { 
                    if (mMainStack.realStartActivityLocked(hr, app, truetrue)) { 
                        didSomething = true
                    } 
                } catch (Exception e) { 
                    Slog.w(TAG, "Exception in new application when starting activity " 
                          + hr.intent.getComponent().flattenToShortString(), e); 
                    badApp = true
                } 
            } else { 
                mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0); 
            } 
        } 
 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   * Mirroring logic in cornerstone. 
   */
 
        ActivityRecord hr_c = mCornerstoneStack.topRunningActivityLocked(null); 
        if (hr_c != null && normalMode) { 
            if (hr_c.app == null && app.info.uid == hr_c.info.applicationInfo.uid 
                    && processName.equals(hr_c.processName)) { 
                try { 
                    if (mCornerstoneStack.realStartActivityLocked(hr_c, app, truetrue)) { 
                        didSomething = true
                    } 
                } catch (Exception e) { 
                    Slog.w(TAG, "Exception in new application when starting activity " 
                          + hr_c.intent.getComponent().flattenToShortString(), e); 
                    badApp = true
                } 
            } else { 
                mCornerstoneStack.ensureActivitiesVisibleLocked(hr_c, null, processName, 0); 
            } 
        } 
 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   * Mirroring logic in cornerstone panels. 
   */
 
        for(int k=0; k<mCornerstonePanelStacks.size(); k++) { 
   ActivityStack currStack = mCornerstonePanelStacks.get(k); 
   ActivityRecord hr_p = currStack.topRunningActivityLocked(null); 
   if (hr_p != null && normalMode) { 
    if (hr_p.app == null && app.info.uid == hr_p.info.applicationInfo.uid 
     && processName.equals(hr_p.processName)) { 
     try { 
      if (currStack.realStartActivityLocked(hr_p, app, truetrue)) { 
       didSomething = true
      
     catch (Exception e) { 
      Slog.w(TAG, "Exception in new application when starting activity " 
       + hr_p.intent.getComponent().flattenToShortString(), e); 
      badApp = true
     
    else { 
     currStack.ensureActivitiesVisibleLocked(hr_p, 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) { 
                Slog.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) { 
                Slog.w(TAG, "Exception in new application when starting receiver " 
                      + br.curComponent.flattenToShortString(), e); 
                badApp = true
                logBroadcastReceiverDiscardLocked(br); 
                finishReceiverLocked(br.receiver, br.resultCode, br.resultData, 
                        br.resultExtras, br.resultAbort, true); 
                scheduleBroadcastsLocked(); 
                // We need to reset the state if we fails to start the receiver. 
                br.state = BroadcastRecord.IDLE; 
            } 
        } 
 
        // Check whether the next backup agent is in this process... 
        if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) { 
            if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app); 
            ensurePackageDexOpt(mBackupTarget.appInfo.packageName); 
            try { 
                thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, 
                        compatibilityInfoForPackageLocked(mBackupTarget.appInfo), 
                        mBackupTarget.backupMode); 
            } catch (Exception e) { 
                Slog.w(TAG, "Exception scheduling backup agent creation: "); 
                e.printStackTrace(); 
            } 
        } 
 
        if (badApp) { 
            // todo: Also need to kill application to deal with all 
            // kinds of exceptions. 
            handleAppDiedLocked(app, falsetrue); 
            return false
        } 
 
        if (!didSomething) { 
            updateOomAdjLocked(); 
        } 
 
        return true
    } 
 
    public final void attachApplication(IApplicationThread thread) { 
        synchronized (this) { 
            int callingPid = Binder.getCallingPid(); 
            final long origId = Binder.clearCallingIdentity(); 
            attachApplicationLocked(thread, callingPid); 
            Binder.restoreCallingIdentity(origId); 
        } 
    } 
 
 /**
  * Author: Onskreen 
  * Date: 27/01/2011 
  * 
  * Utility methods to if an ActivityRecord is the Cornerstone app. Centralizing 
  * logic here so easily changed when we have a richer way of testing than 
  * package name. 
  */
 
    public final boolean isCornerstone(ActivityRecord r) { 
 
        if(r!=null && r.packageName.contains(this.mCornerstoneAppPackageName)) { 
   return true
        } else { 
   return false
        } 
    } 
 
 
 /**
  * Author: Onskreen 
  * Date: 27/01/2011 
  * 
  * Utility methods to dump to debug log brief state of all ActivityStacks 
  */
 
    private final void logActivityStackState() { 
  Log.v(TAG, mMainStack.mStackName); 
        for (int i=mMainStack.mHistory.size()-1; i>=0; i--) { 
   ActivityRecord r = ((ActivityRecord)mMainStack.mHistory.get(i)); 
   Log.v(TAG, "\t" + r.packageName + " State: " + r.state); 
        } 
        if(mMainStack.mHistory.isEmpty()) { 
   Log.v(TAG, "\tEmpty"); 
        } 
 
        for(int k=0; k<mCornerstonePanelStacks.size(); k++) { 
   ActivityStack currStack = mCornerstonePanelStacks.get(k); 
   Log.v(TAG, currStack.mStackName); 
   for (int i=currStack.mHistory.size()-1; i>=0; i--) { 
    ActivityRecord r = ((ActivityRecord)currStack.mHistory.get(i)); 
    Log.v(TAG, "\t" + r.packageName + " State: " + r.state); 
   
            if(currStack.mHistory.isEmpty()) { 
    Log.v(TAG, "\tEmpty"); 
            } 
  
 
  Log.v(TAG, mCornerstoneStack.mStackName); 
        for (int i=mCornerstoneStack.mHistory.size()-1; i>=0; i--) { 
   ActivityRecord r = ((ActivityRecord)mCornerstoneStack.mHistory.get(i)); 
   Log.v(TAG, "\t" + r.packageName + " State: " + r.state); 
        } 
        if(mCornerstoneStack.mHistory.isEmpty()) { 
   Log.v(TAG, "\tEmpty"); 
        } 
    } 
 
 /**
  * Author: Onskreen 
  * Date: 24/01/2011 
  * 
  * Determines which stack an activity will be allocated to when launched. Make 
  * best assumptions based on the intent and resultTo and current state 
  * of the various stacks. 
  */
 
    private int getActivityStack(Intent intent, IBinder resultTo) { 
  if(DEBUG_CORNERSTONE) { 
   Log.v(TAG, "Inspecting intent: " + intent + " resultTo: " + resultTo); 
   logActivityStackState(); 
  
 
  if(intent.getComponent() != null) { 
   if(intent.getComponent().toString().contains(this.mCornerstoneAppPackageName)) { 
    if(DEBUG_CORNERSTONE) { 
     Log.v(TAG, "\tComponent identified as cornerstone"); 
    
    return CORNERSTONE_STACK; 
   
  
 
        //Translate the resultTo to a record in an existing stack 
        ActivityRecord resultToActivityRecord = ActivityRecord.forToken(resultTo); 
 
        //Check the mainstack history 
        for (int i=mMainStack.mHistory.size()-1; i>=0; i--) { 
            Object o = mMainStack.mHistory.get(i); 
            if (o == resultToActivityRecord) { 
    if(DEBUG_CORNERSTONE) { 
     Log.v(TAG, "\tresultTo found in main stack"); 
    
    return MAIN_STACK; 
            } 
        } 
 
        //search the cornerstone panels 
        for (int k=0; k<mCornerstonePanelStacks.size(); k++) { 
   ActivityStack currStack = mCornerstonePanelStacks.get(k); 
   for (int i=currStack.mHistory.size()-1; i>=0; i--) { 
                Object o = currStack.mHistory.get(i); 
                if (o == resultToActivityRecord) { 
     if(DEBUG_CORNERSTONE) { 
      Log.v(TAG, "\tresultTo found in cornerstone panel: " + k); 
     
     return k; 
                } 
   
        } 
 
        //If sending result to home, then assume belongs in main stack 
        if(resultToActivityRecord != null && resultToActivityRecord.isHomeActivity) { 
   return MAIN_STACK; 
        } else if(isCornerstone(resultToActivityRecord)) { 
   return mCornerstonePanelsCreated++; 
        } 
  if(DEBUG_CORNERSTONE) { 
   Log.v(TAG, "\tresultTo found nowhere, default to main stack"); 
  
        //If didn't find anywhere, then fail 
        return NO_STACK; 
    } 
 
 /**
  * Author: Onskreen 
  * Date: 27/01/2011 
  * 
  * Utility methods to check which stack an activity is in. 
  */
 
    private final int getActivityStack(int task) { 
  if(DEBUG_CORNERSTONE) { 
   Log.v(TAG, "Inspecting task: " + task); 
   logActivityStackState(); 
  
 
  //Search Cornerstone 
  for(int i=0; i<mCornerstoneStack.mHistory.size(); i++) { 
   if(task == ((ActivityRecord)mCornerstoneStack.mHistory.get(i)).task.taskId) { 
    if(DEBUG_CORNERSTONE) Log.v(TAG, "\tTask found in cornerstone stack"); 
    return CORNERSTONE_STACK; 
   
        } 
 
  //Search Cornerstone Panels 
        for (int k=0; k<mCornerstonePanelStacks.size(); k++) { 
   ActivityStack currStack = mCornerstonePanelStacks.get(k); 
   for (int i=currStack.mHistory.size()-1; i>=0; i--) { 
    if(task == ((ActivityRecord)currStack.mHistory.get(i)).task.taskId) { 
     if(DEBUG_CORNERSTONE) Log.v(TAG, "\tTask found in cornerstone panel: " + k); 
     return k; 
    
   
        } 
 
        //Search Main Stack 
  for(int i=0; i<mMainStack.mHistory.size(); i++) { 
   if(task == ((ActivityRecord)mMainStack.mHistory.get(i)).task.taskId) { 
    if(DEBUG_CORNERSTONE) Log.v(TAG, "\tTask found in main stack"); 
     return MAIN_STACK; 
   
        } 
 
  if(DEBUG_CORNERSTONE) Log.v(TAG, "\tTask not found"); 
        return NO_STACK; 
    } 
 
 
 /**
  * Author: Onskreen 
  * Date: 27/01/2011 
  * 
  * Utility methods to check which stack an activity is in. 
  */
 
    private final int getActivityStack(ActivityRecord r) { 
  if(DEBUG_CORNERSTONE) { 
   Log.v(TAG, "Inspecting record: " + r); 
   logActivityStackState(); 
  
 
  //Search Main Stack 
        for(int i=0; i<mMainStack.mHistory.size(); i++) { 
   if(r == ((ActivityRecord)mMainStack.mHistory.get(i))) { 
    if(DEBUG_CORNERSTONE) Log.v(TAG, "\tActivityRecord found in main stack"); 
    return MAIN_STACK; 
   
        } 
 
  //Search Cornerstone Panels 
        for (int k=0; k>mCornerstonePanelStacks.size(); k++) { 
   ActivityStack currStack = mCornerstonePanelStacks.get(k); 
   for (int i=currStack.mHistory.size()-1; i>=0; i--) { 
    if(r == ((ActivityRecord)currStack.mHistory.get(i))) { 
     if(DEBUG_CORNERSTONE) Log.v(TAG, "\tTask found in cornerstone panel: " + k); 
     return k; 
    
   
        } 
 
        //Search Cornerstone 
        if(isCornerstone(r)) { 
   if(DEBUG_CORNERSTONE) Log.v(TAG, "\tActivityRecord found to be cornerstone"); 
   return CORNERSTONE_STACK; 
        } 
 
  if(DEBUG_CORNERSTONE) Log.v(TAG, "\tActivityRecord not found"); 
        return NO_STACK; 
    } 
 
 /**
  * Author: Onskreen 
  * Date: 27/01/2011 
  * 
  * Utility methods to check which stack a token is in. 
  */
 
    private final int getActivityStack(IBinder token) { 
  if(DEBUG_CORNERSTONE) { 
   Log.v(TAG, "Inspecting token: " + token); 
   logActivityStackState(); 
  
 
  //Check cornerstone panels 
  for(int k=0; k<mCornerstonePanelStacks.size(); k++) { 
   ActivityStack currStack = mCornerstonePanelStacks.get(k); 
   for(int i=0; i<currStack.mHistory.size(); i++) { 
    Object o = currStack.mHistory.get(i); 
    if(o==ActivityRecord.forToken(token)) { 
     if(DEBUG_CORNERSTONE) Log.v(TAG, "\tToken found to be cornerstone panel: " + k); 
     return k; 
    
   
  
 
  //Search Main Stack 
        for(int i=0; i<mMainStack.mHistory.size(); i++) { 
   Object o = mMainStack.mHistory.get(i); 
   if(o==ActivityRecord.forToken(token)) { 
    if(DEBUG_CORNERSTONE) Log.v(TAG, "\tActivityRecord found in main stack"); 
    return MAIN_STACK; 
   
        } 
 
  //Search Cornerstone 
        for(int i=0; i<mCornerstoneStack.mHistory.size(); i++) { 
   Object o = mCornerstoneStack.mHistory.get(i); 
   if(o==ActivityRecord.forToken(token)) { 
    if(DEBUG_CORNERSTONE) Log.v(TAG, "\tActivityRecord found in cornerstone"); 
    return CORNERSTONE_STACK; 
   
        } 
 
  if(DEBUG_CORNERSTONE) Log.v(TAG, "\tToken not found."); 
        return NO_STACK; 
    } 
 
    public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { 
        final long origId = Binder.clearCallingIdentity(); 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   * Push message to appropriate stack. 
   */
 
        int stack = getActivityStack(token); 
        ActivityStack targetStack = null
        //Cornerstone Panel 
        if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return
   
        } else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
        } else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
            targetStack = mMainStack; 
        } 
        ActivityRecord r = targetStack.activityIdleInternal(token, false, config); 
        if (stopProfiling) { 
            synchronized (this) { 
                if (mProfileProc == r.app) { 
                    if (mProfileFd != null) { 
                        try { 
                            mProfileFd.close(); 
                        } catch (IOException e) { 
                        } 
                        clearProfilerLocked(); 
                    } 
                } 
            } 
        } 
        Binder.restoreCallingIdentity(origId); 
    } 
 
    void enableScreenAfterBoot() { 
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN, 
                SystemClock.uptimeMillis()); 
        mWindowManager.enableScreenAfterBoot(); 
    } 
 
    public void showBootMessage(final CharSequence msg, final boolean always) { 
        mWindowManager.showBootMessage(msg, always); 
    } 
 
    public void dismissKeyguardOnNextActivity() { 
        synchronized (this) { 
            mMainStack.dismissKeyguardOnNextActivityLocked(); 
        } 
    } 
 
    final void finishBooting() { 
        IntentFilter pkgFilter = new IntentFilter(); 
        pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); 
        pkgFilter.addDataScheme("package"); 
        mContext.registerReceiver(new BroadcastReceiver() { 
            @Override 
            public void onReceive(Context context, Intent intent) { 
                String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES); 
                if (pkgs != null) { 
                    for (String pkg : pkgs) { 
                        synchronized (ActivityManagerService.this) { 
                          if (forceStopPackageLocked(pkg, -1falsefalsefalsefalse)) { 
                              setResultCode(Activity.RESULT_OK); 
                              return
                          } 
                       } 
                    } 
                } 
            } 
        }, pkgFilter); 
 
        synchronized (this) { 
            // 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++) { 
                    if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: " 
                            + procs.get(ip)); 
                    startProcessLocked(procs.get(ip), "on-hold"null); 
                } 
            } 
 
            if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { 
                // Start looking for apps that are abusing wake locks. 
                Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); 
                mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY); 
                // Tell anyone interested that we are done booting! 
                SystemProperties.set("sys.boot_completed""1"); 
                broadcastIntentLocked(nullnull
                        new Intent(Intent.ACTION_BOOT_COMPLETED, null), 
                        nullnull0nullnull
                        android.Manifest.permission.RECEIVE_BOOT_COMPLETED, 
                        falsefalse, MY_PID, Process.SYSTEM_UID); 
            } 
        } 
    } 
 
    final void ensureBootCompleted() { 
        boolean booting; 
        boolean enableScreen; 
        synchronized (this) { 
            booting = mBooting; 
            mBooting = false
            enableScreen = !mBooted; 
            mBooted = true
        } 
 
        if (booting) { 
            finishBooting(); 
        } 
 
        if (enableScreen) { 
            enableScreenAfterBoot(); 
        } 
    } 
 
    public final void activityPaused(IBinder token) { 
        final long origId = Binder.clearCallingIdentity(); 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   * Choosing between stacks 
   */
 
        int stack = getActivityStack(token); 
        ActivityStack targetStack = null
        //Cornerstone Panel 
        if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return
   
        } else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
        } else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
            targetStack = mMainStack; 
        } 
        targetStack.activityPaused(token, false); 
        Binder.restoreCallingIdentity(origId); 
    } 
 
    public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail, 
            CharSequence description) { 
        if (localLOGV) Slog.v( 
            TAG, "Activity stopped: token=" + token); 
 
        // Refuse possible leaked file descriptors 
        if (icicle != null && icicle.hasFileDescriptors()) { 
            throw new IllegalArgumentException("File descriptors passed in Bundle"); 
        } 
 
        ActivityRecord r = null
 
        final long origId = Binder.clearCallingIdentity(); 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   * Choosing between stacks 
   */
 
        int stack = getActivityStack(token); 
        ActivityStack targetStack = null
        //Cornerstone Panel 
        if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return
   
        } else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
        } else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
            targetStack = mMainStack; 
        } 
        synchronized (this) { 
            r = targetStack.isInStackLocked(token); 
            if (r != null) { 
                r.stack.activityStoppedLocked(r, icicle, thumbnail, description); 
            } 
        } 
 
        if (r != null) { 
            sendPendingThumbnail(r, nullnullnullfalse); 
        } 
 
        trimApplications(); 
 
        Binder.restoreCallingIdentity(origId); 
    } 
 
    public final void activityDestroyed(IBinder token) { 
        if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token); 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   * Choosing between stacks 
   */
 
        int stack = getActivityStack(token); 
        ActivityStack targetStack = null
        //Cornerstone Panel 
        if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return
   
        } else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
        } else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
            targetStack = mMainStack; 
        } 
        targetStack.activityDestroyed(token); 
    } 
 
    public String getCallingPackage(IBinder token) { 
        synchronized (this) { 
            ActivityRecord r = getCallingRecordLocked(token); 
            return r != null && r.app != null ? r.info.packageName : null
        } 
    } 
 
    public ComponentName getCallingActivity(IBinder token) { 
        synchronized (this) { 
            ActivityRecord r = getCallingRecordLocked(token); 
            return r != null ? r.intent.getComponent() : null
        } 
    } 
 
    private ActivityRecord getCallingRecordLocked(IBinder token) { 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   * Choosing between stacks 
   */
 
        int stack = getActivityStack(token); 
        ActivityStack targetStack = null
        //Cornerstone Panel 
        if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return null
   
        } else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
        } else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
            targetStack = mMainStack; 
        } 
        ActivityRecord r = targetStack.isInStackLocked(token); 
        if (r == null) { 
            return null
        } 
        return r.resultTo; 
    } 
 
    public ComponentName getActivityClassForToken(IBinder token) { 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   * Choosing between stacks 
   */
 
        int stack = getActivityStack(token); 
        ActivityStack targetStack = null
        //Cornerstone Panel 
        if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return null
   
        } else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
        } else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
            targetStack = mMainStack; 
        } 
        synchronized(this) { 
            ActivityRecord r = targetStack.isInStackLocked(token); 
            if (r == null) { 
                return null
            } 
            return r.intent.getComponent(); 
        } 
    } 
 
    public String getPackageForToken(IBinder token) { 
  /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   * 
   * Choosing between stacks 
   */
 
        int stack = getActivityStack(token); 
        ActivityStack targetStack = null
        //Cornerstone Panel 
        if(stack >= 0) { 
   if(stack < mCornerstonePanelStacks.size()) { 
    targetStack = mCornerstonePanelStacks.get(stack); 
   else { 
    Log.e(TAG, "Found in Non-Existent Stack"); 
    return null
   
        } else if(stack == CORNERSTONE_STACK) { 
   //Cornerstone 
   targetStack = mCornerstoneStack; 
        } else if(stack == MAIN_STACK || stack == NO_STACK) { 
   //Main stack or Unknown 
            targetStack = mMainStack; 
        } 
        synchronized(this) { 
            ActivityRecord r = targetStack.isInStackLocked(token); 
            if (r == null) { 
                return null
            } 
            return r.packageName; 
        } 
    } 
 
    public IIntentSender getIntentSender(int type, 
            String packageName, IBinder token, String resultWho, 
            int requestCode, Intent[] intents, String[] resolvedTypes, int flags) { 
        // Refuse possible leaked file descriptors 
        if (intents != null) { 
            if (intents.length < 1) { 
                throw new IllegalArgumentException("Intents array length must be >= 1"); 
            } 
            for (int i=0; i<intents.length; i++) { 
                Intent intent = intents[i]; 
                if (intent != null) { 
                    if (intent.hasFileDescriptors()) { 
                        throw new IllegalArgumentException("File descriptors passed in Intent"); 
                    } 
                    if (type == INTENT_SENDER_BROADCAST && 
                            (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) { 
                        throw new IllegalArgumentException( 
                                "Can't use FLAG_RECEIVER_BOOT_UPGRADE here"); 
                    } 
                    intents[i] = new Intent(intent); 
                } 
            } 
            if (resolvedTypes != null && resolvedTypes.length != intents.length) { 
                throw new IllegalArgumentException( 
                        "Intent array length does not match resolvedTypes length"); 
            } 
        } 
 
        synchronized(this) { 
            int callingUid = Binder.getCallingUid(); 
            try { 
                if (callingUid != 0 && callingUid != Process.SYSTEM_UID) { 
                    int uid = AppGlobals.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; 
                        Slog.w(TAG, msg); 
                        throw new SecurityException(msg); 
                    } 
                } 
 
                return getIntentSenderLocked(type, packageName, callingUid, 
                        token, resultWho, requestCode, intents, resolvedTypes, flags); 
 
            } catch (RemoteException e) { 
                throw new SecurityException(e); 
            } 
        } 
    } 
 
    IIntentSender getIntentSenderLocked(int type, 
            String packageName, int callingUid, IBinder token, String resultWho, 
            int requestCode, Intent[] intents, String[] resolvedTypes, int flags) { 
        ActivityRecord activity = null
        if (type == INTENT_SENDER_ACTIVITY_RESULT) { 
           /**
   * Author: Onskreen 
   * Date: 27/01/2011 
   
   * Choosing between stacks 
   */
 
   int stack = getActivityStack(token); 
   ActivityStack targetStack = null
   //Cornerstone Panel 
   if(stack >= 0) { 
    if(stack < mCornerstonePanelStacks.size()) { 
     targetStack = mCornerstonePanelStacks.get(stack); 
    else { 
     Log.e(TAG, "Found in Non-Existent Stack"); 
     return null
    
   else if(stack == CORNERSTONE_STACK) { 
    //Cornerstone 
    targetStack = mCornerstoneStack; 
   else if(stack == MAIN_STACK || stack == NO_STACK) { 
    //Main stack or Unknown 
    targetStack = mMainStack; 
   
            activity = targetStack.isInStackLocked(token); 
            if (activity&