/* * Copyright (C) 2006-2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.am; import com.android.internal.os.BatteryStatsImpl; import com.android.server.AttributeCache; import com.android.server.IntentResolver; import com.android.server.ProcessMap; import com.android.server.ProcessStats; import com.android.server.SystemServer; import com.android.server.Watchdog; import com.android.server.WindowManagerService; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.ActivityThread; import android.app.AlertDialog; import android.app.ApplicationErrorReport; import android.app.Dialog; import android.app.IActivityWatcher; import android.app.IApplicationThread; import android.app.IInstrumentationWatcher; import android.app.IServiceConnection; import android.app.IThumbnailReceiver; import android.app.Instrumentation; import android.app.PendingIntent; import android.app.ResultInfo; import android.backup.IBackupManager; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.IIntentReceiver; import android.content.IIntentSender; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.res.Configuration; import android.graphics.Bitmap; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; import android.os.IBinder; import android.os.IPermissionController; import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.provider.Checkin; import android.provider.Settings; import android.server.data.CrashData; import android.server.data.StackTraceElementData; import android.server.data.ThrowableData; import android.text.TextUtils; import android.util.Config; import android.util.EventLog; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.SparseArray; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.view.WindowManagerPolicy; import dalvik.system.Zygote; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.lang.IllegalStateException; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor { static final String TAG = "ActivityManager"; static final boolean DEBUG = false; static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; static final boolean DEBUG_SWITCH = localLOGV || false; static final boolean DEBUG_TASKS = localLOGV || false; static final boolean DEBUG_PAUSE = localLOGV || false; static final boolean DEBUG_OOM_ADJ = localLOGV || false; static final boolean DEBUG_TRANSITION = localLOGV || false; static final boolean DEBUG_BROADCAST = localLOGV || false; static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false; static final boolean DEBUG_SERVICE = localLOGV || false; static final boolean DEBUG_VISBILITY = localLOGV || false; static final boolean DEBUG_PROCESSES = localLOGV || false; static final boolean DEBUG_USER_LEAVING = localLOGV || false; static final boolean DEBUG_RESULTS = localLOGV || false; static final boolean DEBUG_BACKUP = localLOGV || true; static final boolean VALIDATE_TOKENS = false; static final boolean SHOW_ACTIVITY_START_TIME = true; // Control over CPU and battery monitoring. static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes. static final boolean MONITOR_CPU_USAGE = true; static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds. static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample. static final boolean MONITOR_THREAD_CPU_USAGE = false; // Event log tags static final int LOG_CONFIGURATION_CHANGED = 2719; static final int LOG_CPU = 2721; static final int LOG_AM_FINISH_ACTIVITY = 30001; static final int LOG_TASK_TO_FRONT = 30002; static final int LOG_AM_NEW_INTENT = 30003; static final int LOG_AM_CREATE_TASK = 30004; static final int LOG_AM_CREATE_ACTIVITY = 30005; static final int LOG_AM_RESTART_ACTIVITY = 30006; static final int LOG_AM_RESUME_ACTIVITY = 30007; static final int LOG_ANR = 30008; static final int LOG_ACTIVITY_LAUNCH_TIME = 30009; static final int LOG_AM_PROCESS_BOUND = 30010; static final int LOG_AM_PROCESS_DIED = 30011; static final int LOG_AM_FAILED_TO_PAUSE_ACTIVITY = 30012; static final int LOG_AM_PAUSE_ACTIVITY = 30013; static final int LOG_AM_PROCESS_START = 30014; static final int LOG_AM_PROCESS_BAD = 30015; static final int LOG_AM_PROCESS_GOOD = 30016; static final int LOG_AM_LOW_MEMORY = 30017; static final int LOG_AM_DESTROY_ACTIVITY = 30018; static final int LOG_AM_RELAUNCH_RESUME_ACTIVITY = 30019; static final int LOG_AM_RELAUNCH_ACTIVITY = 30020; static final int LOG_AM_KILL_FOR_MEMORY = 30023; static final int LOG_AM_BROADCAST_DISCARD_FILTER = 30024; static final int LOG_AM_BROADCAST_DISCARD_APP = 30025; static final int LOG_AM_CREATE_SERVICE = 30030; static final int LOG_AM_DESTROY_SERVICE = 30031; static final int LOG_AM_PROCESS_CRASHED_TOO_MUCH = 30032; static final int LOG_AM_DROP_PROCESS = 30033; static final int LOG_AM_SERVICE_CRASHED_TOO_MUCH = 30034; static final int LOG_AM_SCHEDULE_SERVICE_RESTART = 30035; static final int LOG_AM_PROVIDER_LOST_PROCESS = 30036; static final int LOG_BOOT_PROGRESS_AMS_READY = 3040; static final int LOG_BOOT_PROGRESS_ENABLE_SCREEN = 3050; // 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 | PackageManager.GET_SUPPORTS_DENSITIES; private static final String SYSTEM_SECURE = "ro.secure"; // This is the maximum number of application processes we would like // to have running. Due to the asynchronous nature of things, we can // temporarily go beyond this limit. static final int MAX_PROCESSES = 2; // Set to false to leave processes running indefinitely, relying on // the kernel killing them as resources are required. static final boolean ENFORCE_PROCESS_LIMIT = false; // This is the maximum number of activities that we would like to have // running at a given time. static final int MAX_ACTIVITIES = 20; // Maximum number of recent tasks that we can remember. static final int MAX_RECENT_TASKS = 20; // 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 until we reset a task when the user returns to it. Currently // 30 minutes. static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30; // Set to true to disable the icon that is shown while a new activity // is being started. static final boolean SHOW_APP_STARTING_ICON = true; // How long we wait until giving up on the last activity to pause. This // is short because it directly impacts the responsiveness of starting the // next activity. static final int PAUSE_TIMEOUT = 500; /** * How long we can hold the launch wake lock before giving up. */ static final int LAUNCH_TIMEOUT = 10*1000; // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real. static final int PROC_START_TIMEOUT = 10*1000; // How long we wait until giving up on the last activity telling us it // is idle. static final int IDLE_TIMEOUT = 10*1000; // How long to wait after going idle before forcing apps to GC. static final int GC_TIMEOUT = 5*1000; // How long we wait until giving up on an activity telling us it has // finished destroying itself. static final int DESTROY_TIMEOUT = 10*1000; // How long we allow a receiver to run before giving up on it. static final int BROADCAST_TIMEOUT = 10*1000; // How long we wait for a service to finish executing. static final int SERVICE_TIMEOUT = 20*1000; // How long a service needs to be running until restarting its process // is no longer considered to be a relaunch of the service. static final int SERVICE_RESTART_DURATION = 5*1000; // Maximum amount of time for there to be no activity on a service before // we consider it non-essential and allow its process to go on the // LRU background list. static final int MAX_SERVICE_INACTIVITY = 10*60*1000; // How long we wait until we timeout on key dispatching. static final int KEY_DISPATCHING_TIMEOUT = 5*1000; // The minimum time we allow between crashes, for us to consider this // application to be bad and stop and its services and reject broadcasts. static final int MIN_CRASH_INTERVAL = 60*1000; // How long we wait until we timeout on key dispatching during instrumentation. static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000; // OOM adjustments for processes in various states: // This is a process without anything currently running in it. Definitely // the first to go! Value set in system/rootdir/init.rc on startup. // This value is initalized in the constructor, careful when refering to // this static variable externally. static int EMPTY_APP_ADJ; // This is a process with a content provider that does not have any clients // attached to it. If it did have any clients, its adjustment would be the // one for the highest-priority of those processes. static int CONTENT_PROVIDER_ADJ; // This is a process only hosting activities that are not visible, // so it can be killed without any disruption. Value set in // system/rootdir/init.rc on startup. final int HIDDEN_APP_MAX_ADJ; static int HIDDEN_APP_MIN_ADJ; // This is a process holding the home application -- we want to try // avoiding killing it, even if it would normally be in the background, // because the user interacts with it so much. final int HOME_APP_ADJ; // This is a process currently hosting a backup operation. Killing it // is not entirely fatal but is generally a bad idea. final int BACKUP_APP_ADJ; // This is a process holding a secondary server -- killing it will not // have much of an impact as far as the user is concerned. Value set in // system/rootdir/init.rc on startup. final int SECONDARY_SERVER_ADJ; // This is a process only hosting activities that are visible to the // user, so we'd prefer they don't disappear. Value set in // system/rootdir/init.rc on startup. final int VISIBLE_APP_ADJ; // This is the process running the current foreground app. We'd really // rather not kill it! Value set in system/rootdir/init.rc on startup. final int FOREGROUND_APP_ADJ; // This is a process running a core server, such as telephony. Definitely // don't want to kill it, but doing so is not completely fatal. static final int CORE_SERVER_ADJ = -12; // The system process runs at the default adjustment. static final int SYSTEM_ADJ = -16; // Memory pages are 4K. static final int PAGE_SIZE = 4*1024; // Corresponding memory levels for above adjustments. final int EMPTY_APP_MEM; final int HIDDEN_APP_MEM; final int HOME_APP_MEM; final int BACKUP_APP_MEM; final int SECONDARY_SERVER_MEM; final int VISIBLE_APP_MEM; final int FOREGROUND_APP_MEM; final int MY_PID; static final String[] EMPTY_STRING_ARRAY = new String[0]; enum ActivityState { INITIALIZING, RESUMED, PAUSING, PAUSED, STOPPING, STOPPED, FINISHING, DESTROYING, DESTROYED } /** * The back history of all previous (and possibly still * running) activities. It contains HistoryRecord objects. */ final ArrayList mHistory = new ArrayList(); /** * Description of a request to start a new activity, which has been held * due to app switches being disabled. */ class PendingActivityLaunch { HistoryRecord r; HistoryRecord sourceRecord; Uri[] grantedUriPermissions; int grantedMode; boolean onlyIfNeeded; } final ArrayList mPendingActivityLaunches = new ArrayList(); /** * List of all active broadcasts that are to be executed immediately * (without waiting for another broadcast to finish). Currently this only * contains broadcasts to registered receivers, to avoid spinning up * a bunch of processes to execute IntentReceiver components. */ final ArrayList mParallelBroadcasts = new ArrayList(); /** * 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 mOrderedBroadcasts = new ArrayList(); /** * Set when we current have a BROADCAST_INTENT_MSG in flight. */ boolean mBroadcastsScheduled = false; /** * Set to indicate whether to issue an onUserLeaving callback when a * newly launched activity is being brought in front of us. */ boolean mUserLeaving = false; /** * When we are in the process of pausing an activity, before starting the * next one, this variable holds the activity that is currently being paused. */ HistoryRecord mPausingActivity = null; /** * Current activity that is resumed, or null if there is none. */ HistoryRecord mResumedActivity = null; /** * Activity we have told the window manager to have key focus. */ HistoryRecord mFocusedActivity = null; /** * This is the last activity that we put into the paused state. This is * used to determine if we need to do an activity transition while sleeping, * when we normally hold the top activity paused. */ HistoryRecord mLastPausedActivity = null; /** * List of activities that are waiting for a new activity * to become visible before completing whatever operation they are * supposed to do. */ final ArrayList mWaitingVisibleActivities = new ArrayList(); /** * List of activities that are ready to be stopped, but waiting * for the next activity to settle down before doing so. It contains * HistoryRecord objects. */ final ArrayList mStoppingActivities = new ArrayList(); /** * List of intents that were used to start the most recent tasks. */ final ArrayList mRecentTasks = new ArrayList(); /** * List of activities that are ready to be finished, but waiting * for the previous activity to settle down before doing so. It contains * HistoryRecord objects. */ final ArrayList mFinishingActivities = new ArrayList(); /** * All of the applications we currently have running organized by name. * The keys are strings of the application package name (as * returned by the package manager), and the keys are ApplicationRecord * objects. */ final ProcessMap mProcessNames = new ProcessMap(); /** * The last time that various processes have crashed. */ final ProcessMap mProcessCrashTimes = new ProcessMap(); /** * 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 mBadProcesses = new ProcessMap(); /** * All of the processes we currently have running organized by pid. * The keys are the pid running the application. * *

NOTE: This object is protected by its own lock, NOT the global * activity manager lock! */ final SparseArray mPidsSelfLocked = new SparseArray(); /** * 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 mForegroundProcesses = new SparseArray(); /** * 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 mProcessesOnHold = new ArrayList(); /** * List of records for processes that we have started and are waiting * for them to call back. This is really only needed when running in * single processes mode, in which case we do not have a unique pid for * each process. */ final ArrayList mStartingProcesses = new ArrayList(); /** * List of persistent applications that are in the process * of being started. */ final ArrayList mPersistentStartingProcesses = new ArrayList(); /** * Processes that are being forcibly torn down. */ final ArrayList mRemovedProcesses = new ArrayList(); /** * 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 mLRUProcesses = new ArrayList(); /** * List of processes that should gc as soon as things are idle. */ final ArrayList mProcessesToGc = new ArrayList(); /** * This is the process holding what we currently consider to be * the "home" activity. */ private ProcessRecord mHomeProcess; /** * List of running activities, sorted by recent usage. * The first entry in the list is the least recently used. * It contains HistoryRecord objects. */ private final ArrayList mLRUActivities = new ArrayList(); /** * Set of PendingResultRecord objects that are currently active. */ final HashSet mPendingResultRecords = new HashSet(); /** * Set of IntentSenderRecord objects that are currently active. */ final HashMap> mIntentSenderRecords = new HashMap>(); /** * Intent broadcast that we have tried to start, but are * waiting for its application's process to be created. We only * need one (instead of a list) because we always process broadcasts * one at a time, so no others can be started while waiting for this * one. */ BroadcastRecord mPendingBroadcast = null; /** * Keeps track of all IIntentReceivers that have been registered for * broadcasts. Hash keys are the receiver IBinder, hash value is * a ReceiverList. */ final HashMap mRegisteredReceivers = new HashMap(); /** * Resolver for broadcast intents to registered receivers. * Holds BroadcastFilter (subclass of IntentFilter). */ final IntentResolver mReceiverResolver = new IntentResolver() { @Override protected boolean allowFilterResult( BroadcastFilter filter, List dest) { IBinder target = filter.receiverList.receiver.asBinder(); for (int i=dest.size()-1; i>=0; i--) { if (dest.get(i).receiverList.receiver.asBinder() == target) { return false; } } return true; } }; /** * State of all active sticky broadcasts. Keys are the action of the * sticky Intent, values are an ArrayList of all broadcasted intents with * that action (which should usually be one). */ final HashMap> mStickyBroadcasts = new HashMap>(); /** * All currently running services. */ final HashMap mServices = new HashMap(); /** * All currently running services indexed by the Intent used to start them. */ final HashMap mServicesByIntent = new HashMap(); /** * All currently bound service connections. Keys are the IBinder of * the client's IServiceConnection. */ final HashMap mServiceConnections = new HashMap(); /** * 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 mPendingServices = new ArrayList(); /** * List of services that are scheduled to restart following a crash. */ final ArrayList mRestartingServices = new ArrayList(); /** * List of services that are in the process of being stopped. */ final ArrayList mStoppingServices = new ArrayList(); /** * 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 mProvidersByName = new HashMap(); /** * All of the currently running global content providers. Keys are a * string containing the provider's implementation class and values are a * ContentProviderRecord object containing the data about it. */ final HashMap mProvidersByClass = new HashMap(); /** * List of content providers who have clients waiting for them. The * application is currently being launched and the provider will be * removed from this list once it is published. */ final ArrayList mLaunchingProviders = new ArrayList(); /** * Global set of specific Uri permissions that have been granted. */ final private SparseArray> mGrantedUriPermissions = new SparseArray>(); /** * 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 sCallerIdentity = new ThreadLocal(); /** * All information we have collected about the runtime performance of * any user id that can impact battery performance. */ final BatteryStatsService mBatteryStatsService; /** * information about component usage */ final UsageStatsService mUsageStatsService; /** * Current configuration information. HistoryRecord objects are given * a reference to this object to indicate which configuration they are * currently running in, so this object must be kept immutable. */ Configuration mConfiguration = new Configuration(); /** * List of initialization arguments to pass to all processes when binding applications to them. * For example, references to the commonly used services. */ HashMap 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 mSystemReady = false; boolean mBooting = 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; /** * 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; /** * Set when the system is going to sleep, until we have * successfully paused the current activity and released our wake lock. * At that point the system is allowed to actually sleep. */ PowerManager.WakeLock mGoingToSleep; /** * We don't want to allow the device to go to sleep while in the process * of launching an activity. This is primarily to allow alarm intent * receivers to launch an activity and get that to run before the device * goes back to sleep. */ PowerManager.WakeLock mLaunchingActivity; /** * Task identifier that activities are currently being started * in. Incremented each time a new task is created. * todo: Replace this with a TokenSpace class that generates non-repeating * integers that won't wrap. */ int mCurTask = 1; /** * Current sequence id for oom_adj computation traversal. */ int mAdjSeq = 0; /** * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar * is set, indicating the user wants processes started in such a way * that they can use ANDROID_PROCESS_WRAPPER and know what will be * running in each process (thus no pre-initialized process, etc). */ boolean mSimpleProcessManagement = false; /** * System monitoring: number of processes that died since the last * N procs were started. */ int[] mProcDeaths = new int[20]; /** * 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; IActivityWatcher mWatcher = null; /** * Callback of last caller to {@link #requestPss}. */ Runnable mRequestPssCallback; /** * Remaining processes for which we are waiting results from the last * call to {@link #requestPss}. */ final ArrayList mRequestPssList = new ArrayList(); /** * Runtime statistics collection thread. This object's lock is used to * protect all related state. */ final Thread mProcessStatsThread; /** * Used to collect process stats when showing not responding dialog. * Protected by mProcessStatsThread. */ final ProcessStats mProcessStats = new ProcessStats( MONITOR_THREAD_CPU_USAGE); long mLastCpuTime = 0; long mLastWriteTime = 0; long mInitialStartTime = 0; /** * Set to true after the system has finished booting. */ boolean mBooted = false; int mProcessLimit = 0; WindowManagerService mWindowManager; static ActivityManagerService mSelf; static ActivityThread mSystemThread; private final class AppDeathRecipient implements IBinder.DeathRecipient { final ProcessRecord mApp; final int mPid; final IApplicationThread mAppThread; AppDeathRecipient(ProcessRecord app, int pid, IApplicationThread thread) { if (localLOGV) Log.v( TAG, "New death recipient " + this + " for thread " + thread.asBinder()); mApp = app; mPid = pid; mAppThread = thread; } public void binderDied() { if (localLOGV) Log.v( TAG, "Death received in " + this + " for thread " + mAppThread.asBinder()); removeRequestedPss(mApp); synchronized(ActivityManagerService.this) { appDiedLocked(mApp, mPid, mAppThread); } } } static final int SHOW_ERROR_MSG = 1; static final int SHOW_NOT_RESPONDING_MSG = 2; static final int SHOW_FACTORY_ERROR_MSG = 3; static final int UPDATE_CONFIGURATION_MSG = 4; static final int GC_BACKGROUND_PROCESSES_MSG = 5; static final int WAIT_FOR_DEBUGGER_MSG = 6; static final int BROADCAST_INTENT_MSG = 7; static final int BROADCAST_TIMEOUT_MSG = 8; static final int PAUSE_TIMEOUT_MSG = 9; static final int IDLE_TIMEOUT_MSG = 10; static final int IDLE_NOW_MSG = 11; static final int SERVICE_TIMEOUT_MSG = 12; static final int UPDATE_TIME_ZONE = 13; static final int SHOW_UID_ERROR_MSG = 14; static final int IM_FEELING_LUCKY_MSG = 15; static final int LAUNCH_TIMEOUT_MSG = 16; static final int DESTROY_TIMEOUT_MSG = 17; static final int SERVICE_ERROR_MSG = 18; static final int RESUME_TOP_ACTIVITY_MSG = 19; static final int PROC_START_TIMEOUT_MSG = 20; static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21; AlertDialog mUidAlert; final Handler mHandler = new Handler() { //public Handler() { // if (localLOGV) Log.v(TAG, "Handler started!"); //} public void handleMessage(Message msg) { switch (msg.what) { case SHOW_ERROR_MSG: { HashMap data = (HashMap) msg.obj; byte[] crashData = (byte[])data.get("crashData"); if (crashData != null) { // This needs to be *un*synchronized to avoid deadlock. ContentResolver resolver = mContext.getContentResolver(); Checkin.reportCrash(resolver, crashData); } synchronized (ActivityManagerService.this) { ProcessRecord proc = (ProcessRecord)data.get("app"); if (proc != null && proc.crashDialog != null) { Log.e(TAG, "App already has crash dialog: " + proc); return; } AppErrorResult res = (AppErrorResult) data.get("result"); if (!mSleeping && !mShuttingDown) { Dialog d = new AppErrorDialog( mContext, res, proc, (Integer)data.get("flags"), (String)data.get("shortMsg"), (String)data.get("longMsg")); d.show(); proc.crashDialog = d; } else { // The device is asleep, so just pretend that the user // saw a crash dialog and hit "force quit". res.set(0); } } } break; case SHOW_NOT_RESPONDING_MSG: { synchronized (ActivityManagerService.this) { HashMap data = (HashMap) msg.obj; ProcessRecord proc = (ProcessRecord)data.get("app"); if (proc != null && proc.anrDialog != null) { Log.e(TAG, "App already has anr dialog: " + proc); return; } broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"), null, null, 0, null, null, null, false, false, MY_PID, Process.SYSTEM_UID); Dialog d = new AppNotRespondingDialog(ActivityManagerService.this, mContext, proc, (HistoryRecord)data.get("activity")); d.show(); proc.anrDialog = d; } ensureScreenEnabled(); } break; case SHOW_FACTORY_ERROR_MSG: { Dialog d = new FactoryErrorDialog( mContext, msg.getData().getCharSequence("msg")); d.show(); enableScreenAfterBoot(); } break; case UPDATE_CONFIGURATION_MSG: { final ContentResolver resolver = mContext.getContentResolver(); Settings.System.putConfiguration(resolver, (Configuration)msg.obj); } break; case GC_BACKGROUND_PROCESSES_MSG: { synchronized (ActivityManagerService.this) { performAppGcsIfAppropriateLocked(); } } break; case WAIT_FOR_DEBUGGER_MSG: { synchronized (ActivityManagerService.this) { ProcessRecord app = (ProcessRecord)msg.obj; if (msg.arg1 != 0) { if (!app.waitedForDebugger) { Dialog d = new AppWaitingForDebuggerDialog( ActivityManagerService.this, mContext, app); app.waitDialog = d; app.waitedForDebugger = true; d.show(); } } else { if (app.waitDialog != null) { app.waitDialog.dismiss(); app.waitDialog = null; } } } } break; case BROADCAST_INTENT_MSG: { if (DEBUG_BROADCAST) Log.v( TAG, "Received BROADCAST_INTENT_MSG"); processNextBroadcast(true); } break; case BROADCAST_TIMEOUT_MSG: { if (mDidDexOpt) { mDidDexOpt = false; Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG); mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT); return; } broadcastTimeout(); } break; case PAUSE_TIMEOUT_MSG: { IBinder token = (IBinder)msg.obj; // We don't at this point know if the activity is fullscreen, // so we need to be conservative and assume it isn't. Log.w(TAG, "Activity pause timeout for " + token); activityPaused(token, null, true); } break; case IDLE_TIMEOUT_MSG: { if (mDidDexOpt) { mDidDexOpt = false; Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG); nmsg.obj = msg.obj; mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT); return; } // We don't at this point know if the activity is fullscreen, // so we need to be conservative and assume it isn't. IBinder token = (IBinder)msg.obj; Log.w(TAG, "Activity idle timeout for " + token); activityIdleInternal(token, true); } break; case DESTROY_TIMEOUT_MSG: { IBinder token = (IBinder)msg.obj; // We don't at this point know if the activity is fullscreen, // so we need to be conservative and assume it isn't. Log.w(TAG, "Activity destroy timeout for " + token); activityDestroyed(token); } break; case IDLE_NOW_MSG: { IBinder token = (IBinder)msg.obj; activityIdle(token); } break; case SERVICE_TIMEOUT_MSG: { 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) { Log.w(TAG, "Failed to update time zone for: " + r.info.processName); } } } } break; } case SHOW_UID_ERROR_MSG: { // XXX This is a temporary dialog, no need to localize. AlertDialog d = new BaseErrorDialog(mContext); d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); d.setCancelable(false); d.setTitle("System UIDs Inconsistent"); d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable."); d.setButton("I'm Feeling Lucky", mHandler.obtainMessage(IM_FEELING_LUCKY_MSG)); mUidAlert = d; d.show(); } break; case IM_FEELING_LUCKY_MSG: { if (mUidAlert != null) { mUidAlert.dismiss(); mUidAlert = null; } } break; case LAUNCH_TIMEOUT_MSG: { if (mDidDexOpt) { mDidDexOpt = false; Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG); mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT); return; } synchronized (ActivityManagerService.this) { if (mLaunchingActivity.isHeld()) { Log.w(TAG, "Launch timeout has expired, giving up wake lock!"); mLaunchingActivity.release(); } } } break; case SERVICE_ERROR_MSG: { ServiceRecord srv = (ServiceRecord)msg.obj; // This needs to be *un*synchronized to avoid deadlock. Checkin.logEvent(mContext.getContentResolver(), Checkin.Events.Tag.SYSTEM_SERVICE_LOOPING, srv.name.toShortString()); } break; case RESUME_TOP_ACTIVITY_MSG: { synchronized (ActivityManagerService.this) { resumeTopActivityLocked(null); } } case PROC_START_TIMEOUT_MSG: { 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); } } case DO_PENDING_ACTIVITY_LAUNCHES_MSG: { synchronized (ActivityManagerService.this) { doPendingActivityLaunchesLocked(true); } } } } }; public static void setSystemProcess() { try { ActivityManagerService m = mSelf; ServiceManager.addService("activity", m); ServiceManager.addService("meminfo", new MemBinder(m)); if (MONITOR_CPU_USAGE) { ServiceManager.addService("cpuinfo", new CpuBinder(m)); } ServiceManager.addService("activity.broadcasts", new BroadcastsBinder(m)); ServiceManager.addService("activity.services", new ServicesBinder(m)); ServiceManager.addService("activity.senders", new SendersBinder(m)); ServiceManager.addService("activity.providers", new ProvidersBinder(m)); ServiceManager.addService("permission", new PermissionController(m)); ApplicationInfo info = mSelf.mContext.getPackageManager().getApplicationInfo( "android", STOCK_PM_FLAGS); synchronized (mSelf) { ProcessRecord app = mSelf.newProcessRecordLocked( mSystemThread.getApplicationThread(), info, info.processName); app.persistent = true; app.pid = Process.myPid(); app.maxAdj = SYSTEM_ADJ; mSelf.mProcessNames.put(app.processName, app.info.uid, app); synchronized (mSelf.mPidsSelfLocked) { mSelf.mPidsSelfLocked.put(app.pid, app); } mSelf.updateLRUListLocked(app, true); } } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException( "Unable to find android system package", e); } } public void setWindowManager(WindowManagerService wm) { mWindowManager = wm; } public static final Context main(int factoryTest) { AThread thr = new AThread(); thr.start(); synchronized (thr) { while (thr.mService == null) { try { thr.wait(); } catch (InterruptedException e) { } } } ActivityManagerService m = thr.mService; mSelf = m; ActivityThread at = ActivityThread.systemMain(); mSystemThread = at; Context context = at.getSystemContext(); m.mContext = context; m.mFactoryTest = factoryTest; PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep"); m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch"); m.mLaunchingActivity.setReferenceCounted(false); m.mBatteryStatsService.publish(context); m.mUsageStatsService.publish(context); synchronized (thr) { thr.mReady = true; thr.notifyAll(); } m.startRunning(null, null, null, null); return context; } public static ActivityManagerService self() { return mSelf; } static class AThread extends Thread { ActivityManagerService mService; boolean mReady = false; public AThread() { super("ActivityManager"); } public void run() { Looper.prepare(); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); ActivityManagerService m = new ActivityManagerService(); synchronized (this) { mService = m; notifyAll(); } synchronized (this) { while (!mReady) { try { wait(); } catch (InterruptedException e) { } } } Looper.loop(); } } static class BroadcastsBinder extends Binder { ActivityManagerService mActivityManagerService; BroadcastsBinder(ActivityManagerService activityManagerService) { mActivityManagerService = activityManagerService; } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mActivityManagerService.dumpBroadcasts(pw); } } static class ServicesBinder extends Binder { ActivityManagerService mActivityManagerService; ServicesBinder(ActivityManagerService activityManagerService) { mActivityManagerService = activityManagerService; } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mActivityManagerService.dumpServices(pw); } } static class SendersBinder extends Binder { ActivityManagerService mActivityManagerService; SendersBinder(ActivityManagerService activityManagerService) { mActivityManagerService = activityManagerService; } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mActivityManagerService.dumpSenders(pw); } } static class ProvidersBinder extends Binder { ActivityManagerService mActivityManagerService; ProvidersBinder(ActivityManagerService activityManagerService) { mActivityManagerService = activityManagerService; } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mActivityManagerService.dumpProviders(pw); } } static class MemBinder extends Binder { ActivityManagerService mActivityManagerService; MemBinder(ActivityManagerService activityManagerService) { mActivityManagerService = activityManagerService; } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { ActivityManagerService service = mActivityManagerService; ArrayList procs; synchronized (mActivityManagerService) { if (args != null && args.length > 0 && args[0].charAt(0) != '-') { procs = new ArrayList(); int pid = -1; try { pid = Integer.parseInt(args[0]); } catch (NumberFormatException e) { } for (int i=0; i getCommonServicesLocked() { if (mAppBindArgs == null) { mAppBindArgs = new HashMap(); // Setup the application init args mAppBindArgs.put("package", ServiceManager.getService("package")); mAppBindArgs.put("window", ServiceManager.getService("window")); mAppBindArgs.put(Context.ALARM_SERVICE, ServiceManager.getService(Context.ALARM_SERVICE)); } return mAppBindArgs; } private final void setFocusedActivityLocked(HistoryRecord r) { if (mFocusedActivity != r) { mFocusedActivity = r; mWindowManager.setFocusedApp(r, true); } } private final void updateLRUListLocked(ProcessRecord app, boolean oomAdj) { // put it on the LRU to keep track of when it should be exited. int lrui = mLRUProcesses.indexOf(app); if (lrui >= 0) mLRUProcesses.remove(lrui); mLRUProcesses.add(app); //Log.i(TAG, "Putting proc to front: " + app.processName); if (oomAdj) { updateOomAdjLocked(); } } private final boolean updateLRUListLocked(HistoryRecord r) { final boolean hadit = mLRUActivities.remove(r); mLRUActivities.add(r); return hadit; } private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) { int i = mHistory.size()-1; while (i >= 0) { HistoryRecord r = (HistoryRecord)mHistory.get(i); if (!r.finishing && r != notTop) { return r; } i--; } return null; } private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) { int i = mHistory.size()-1; while (i >= 0) { HistoryRecord r = (HistoryRecord)mHistory.get(i); if (!r.finishing && !r.delayedResume && r != notTop) { return r; } i--; } return null; } /** * This is a simplified version of topRunningActivityLocked that provides a number of * optional skip-over modes. It is intended for use with the ActivityWatcher hook only. * * @param token If non-null, any history records matching this token will be skipped. * @param taskId If non-zero, we'll attempt to skip over records with the same task ID. * * @return Returns the HistoryRecord of the next activity on the stack. */ private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) { int i = mHistory.size()-1; while (i >= 0) { HistoryRecord r = (HistoryRecord)mHistory.get(i); // Note: the taskId check depends on real taskId fields being non-zero if (!r.finishing && (token != r) && (taskId != r.task.taskId)) { return r; } i--; } return null; } private final ProcessRecord getProcessRecordLocked( String processName, int uid) { if (uid == Process.SYSTEM_UID) { // The system gets to run in any process. If there are multiple // processes with the same uid, just pick the first (this // should never happen). SparseArray procs = mProcessNames.getMap().get( processName); return procs != null ? procs.valueAt(0) : null; } ProcessRecord proc = mProcessNames.get(processName, uid); return proc; } private void ensurePackageDexOpt(String packageName) { IPackageManager pm = ActivityThread.getPackageManager(); try { if (pm.performDexOpt(packageName)) { mDidDexOpt = true; } } catch (RemoteException e) { } } private boolean isNextTransitionForward() { int transit = mWindowManager.getPendingAppTransition(); return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT; } private final boolean realStartActivityLocked(HistoryRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { r.startFreezingScreenLocked(app, 0); mWindowManager.setAppVisibility(r, true); // Have the window manager re-evaluate the orientation of // the screen based on the new activity order. Note that // as a result of this, it can call back into the activity // manager with a new orientation. We don't care about that, // because the activity is not currently running so we are // just restarting it anyway. if (checkConfig) { Configuration config = mWindowManager.updateOrientationFromAppTokens( mConfiguration, r.mayFreezeScreenLocked(app) ? r : null); updateConfigurationLocked(config, r); } r.app = app; if (localLOGV) Log.v(TAG, "Launching: " + r); int idx = app.activities.indexOf(r); if (idx < 0) { app.activities.add(r); } updateLRUListLocked(app, true); try { if (app.thread == null) { throw new RemoteException(); } List results = null; List newIntents = null; if (andResume) { results = r.results; newIntents = r.newIntents; } if (DEBUG_SWITCH) Log.v(TAG, "Launching: " + r + " icicle=" + r.icicle + " with results=" + results + " newIntents=" + newIntents + " andResume=" + andResume); if (andResume) { EventLog.writeEvent(LOG_AM_RESTART_ACTIVITY, System.identityHashCode(r), r.task.taskId, r.shortComponentName); } if (r.isHomeActivity) { mHomeProcess = app; } ensurePackageDexOpt(r.intent.getComponent().getPackageName()); app.thread.scheduleLaunchActivity(new Intent(r.intent), r, r.info, r.icicle, results, newIntents, !andResume, isNextTransitionForward()); // Update usage stats for launched activity updateUsageStats(r, true); } catch (RemoteException e) { if (r.launchFailed) { // This is the second time we failed -- finish activity // and give up. Log.e(TAG, "Second failure launching " + r.intent.getComponent().flattenToShortString() + ", giving up", e); appDiedLocked(app, app.pid, app.thread); requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null, "2nd-crash"); return false; } // This is the first time we failed -- restart process and // retry. app.activities.remove(r); throw e; } r.launchFailed = false; if (updateLRUListLocked(r)) { Log.w(TAG, "Activity " + r + " being launched, but already in LRU list"); } if (andResume) { // As part of the process of launching, ActivityThread also performs // a resume. r.state = ActivityState.RESUMED; r.icicle = null; r.haveState = false; r.stopped = false; mResumedActivity = r; r.task.touchActiveTime(); completeResumeLocked(r); pauseIfSleepingLocked(); } else { // This activity is not starting in the resumed state... which // should look like we asked it to pause+stop (but remain visible), // and it has done so and reported back the current icicle and // other state. r.state = ActivityState.STOPPED; r.stopped = true; } // Launch the new version setup screen if needed. We do this -after- // launching the initial activity (that is, home), so that it can have // a chance to initialize itself while in the background, making the // switch back to it faster and look better. startSetupActivityLocked(); return true; } private final void startSpecificActivityLocked(HistoryRecord r, boolean andResume, boolean checkConfig) { // Is this activity's application already running? ProcessRecord app = getProcessRecordLocked(r.processName, r.info.applicationInfo.uid); if (r.startTime == 0) { r.startTime = SystemClock.uptimeMillis(); if (mInitialStartTime == 0) { mInitialStartTime = r.startTime; } } else if (mInitialStartTime == 0) { mInitialStartTime = SystemClock.uptimeMillis(); } if (app != null && app.thread != null) { try { realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Log.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); } // If a dead object exception was thrown -- fall through to // restart the application. } startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent()); } private final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName) { ProcessRecord app = getProcessRecordLocked(processName, info.uid); // We don't have to do anything more if: // (1) There is an existing application record; and // (2) The caller doesn't think it is dead, OR there is no thread // object attached to it so we know it couldn't have crashed; and // (3) There is a pid assigned to it, so it is either starting or // already running. if (DEBUG_PROCESSES) Log.v(TAG, "startProcess: name=" + processName + " app=" + app + " knownToBeDead=" + knownToBeDead + " thread=" + (app != null ? app.thread : null) + " pid=" + (app != null ? app.pid : -1)); if (app != null && (!knownToBeDead || app.thread == null) && app.pid > 0) { return app; } String hostingNameStr = hostingName != null ? hostingName.flattenToShortString() : null; if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) { // If we are in the background, then check to see if this process // is bad. If so, we will just silently fail. if (mBadProcesses.get(info.processName, info.uid) != null) { return null; } } else { // When the user is explicitly starting a process, then clear its // crash count so that we won't make it bad until they see at // least one crash dialog again, and make the process good again // if it had been bad. mProcessCrashTimes.remove(info.processName, info.uid); if (mBadProcesses.get(info.processName, info.uid) != null) { EventLog.writeEvent(LOG_AM_PROCESS_GOOD, info.uid, info.processName); mBadProcesses.remove(info.processName, info.uid); if (app != null) { app.bad = false; } } } if (app == null) { app = newProcessRecordLocked(null, info, processName); mProcessNames.put(processName, info.uid, app); } else { // If this is a new package in the process, add the package to the list app.addPackage(info.packageName); } // If the system is not ready yet, then hold off on starting this // process until it is. if (!mSystemReady && (info.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) { if (!mProcessesOnHold.contains(app)) { mProcessesOnHold.add(app); } return app; } startProcessLocked(app, hostingType, hostingNameStr); return (app.pid != 0) ? app : null; } private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) { if (app.pid > 0 && app.pid != MY_PID) { synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(app.pid); mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } app.pid = 0; } mProcessesOnHold.remove(app); updateCpuStats(); System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1); mProcDeaths[0] = 0; try { int uid = app.info.uid; int[] gids = null; try { gids = mContext.getPackageManager().getPackageGids( app.info.packageName); } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "Unable to retrieve gids", e); } if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) { if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL && mTopComponent != null && app.processName.equals(mTopComponent.getPackageName())) { uid = 0; } if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) { uid = 0; } } int debugFlags = 0; if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER; } if ("1".equals(SystemProperties.get("debug.checkjni"))) { debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; } if ("1".equals(SystemProperties.get("debug.assert"))) { debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } int pid = Process.start("android.app.ActivityThread", mSimpleProcessManagement ? app.processName : null, uid, uid, gids, debugFlags, null); BatteryStatsImpl bs = app.batteryStats.getBatteryStats(); synchronized (bs) { if (bs.isOnBattery()) { app.batteryStats.incStartsLocked(); } } EventLog.writeEvent(LOG_AM_PROCESS_START, pid, uid, app.processName, hostingType, hostingNameStr != null ? hostingNameStr : ""); if (app.persistent) { Watchdog.getInstance().processStarted(app, app.processName, pid); } StringBuilder buf = 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(pid); buf.append(" uid="); buf.append(uid); buf.append(" gids={"); if (gids != null) { for (int gi=0; gi 0) { app.pid = pid; app.removed = false; synchronized (mPidsSelfLocked) { this.mPidsSelfLocked.put(pid, app); Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); msg.obj = app; mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT); } } else { app.pid = 0; RuntimeException e = new RuntimeException( "Failure starting process " + app.processName + ": returned pid=" + pid); Log.e(TAG, e.getMessage(), e); } } catch (RuntimeException e) { // XXX do better error recovery. app.pid = 0; Log.e(TAG, "Failure starting process " + app.processName, e); } } private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) { if (mPausingActivity != null) { RuntimeException e = new RuntimeException(); Log.e(TAG, "Trying to pause when pause is already pending for " + mPausingActivity, e); } HistoryRecord prev = mResumedActivity; if (prev == null) { RuntimeException e = new RuntimeException(); Log.e(TAG, "Trying to pause when nothing is resumed", e); resumeTopActivityLocked(null); return; } if (DEBUG_PAUSE) Log.v(TAG, "Start pausing: " + prev); mResumedActivity = null; mPausingActivity = prev; mLastPausedActivity = prev; prev.state = ActivityState.PAUSING; prev.task.touchActiveTime(); updateCpuStats(); if (prev.app != null && prev.app.thread != null) { if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending pause: " + prev); try { EventLog.writeEvent(LOG_AM_PAUSE_ACTIVITY, System.identityHashCode(prev), prev.shortComponentName); prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving, prev.configChangeFlags); updateUsageStats(prev, false); } catch (Exception e) { // Ignore exception, if process died other code will cleanup. Log.w(TAG, "Exception thrown during pause", e); mPausingActivity = null; mLastPausedActivity = null; } } else { mPausingActivity = null; mLastPausedActivity = null; } // If we are not going to sleep, we want to ensure the device is // awake until the next activity is started. if (!mSleeping && !mShuttingDown) { mLaunchingActivity.acquire(); if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) { // To be safe, don't allow the wake lock to be held for too long. Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG); mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT); } } if (mPausingActivity != null) { // Have the window manager pause its key dispatching until the new // activity has started. If we're pausing the activity just because // the screen is being turned off and the UI is sleeping, don't interrupt // key dispatch; the same activity will pick it up again on wakeup. if (!uiSleeping) { prev.pauseKeyDispatchingLocked(); } else { if (DEBUG_PAUSE) Log.v(TAG, "Key dispatch not paused for screen off"); } // Schedule a pause timeout in case the app doesn't respond. // We don't give it much time because this directly impacts the // responsiveness seen by the user. Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG); msg.obj = prev; mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT); if (DEBUG_PAUSE) Log.v(TAG, "Waiting for pause to complete..."); } else { // This activity failed to schedule the // pause, so just treat it as being paused now. if (DEBUG_PAUSE) Log.v(TAG, "Activity not running, resuming next."); resumeTopActivityLocked(null); } } private final void completePauseLocked() { HistoryRecord prev = mPausingActivity; if (DEBUG_PAUSE) Log.v(TAG, "Complete pause: " + prev); if (prev != null) { if (prev.finishing) { if (DEBUG_PAUSE) Log.v(TAG, "Executing finish of activity: " + prev); prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE); } else if (prev.app != null) { if (DEBUG_PAUSE) Log.v(TAG, "Enqueueing pending stop: " + prev); if (prev.waitingVisible) { prev.waitingVisible = false; mWaitingVisibleActivities.remove(prev); if (DEBUG_SWITCH || DEBUG_PAUSE) Log.v( TAG, "Complete pause, no longer waiting: " + prev); } if (prev.configDestroy) { // The previous is being paused because the configuration // is changing, which means it is actually stopping... // To juggle the fact that we are also starting a new // instance right now, we need to first completely stop // the current instance before starting the new one. if (DEBUG_PAUSE) Log.v(TAG, "Destroying after pause: " + prev); destroyActivityLocked(prev, true); } else { mStoppingActivities.add(prev); if (mStoppingActivities.size() > 3) { // If we already have a few activities waiting to stop, // then give up on things going idle and start clearing // them out. if (DEBUG_PAUSE) Log.v(TAG, "To many pending stops, forcing idle"); Message msg = Message.obtain(); msg.what = ActivityManagerService.IDLE_NOW_MSG; mHandler.sendMessage(msg); } } } else { if (DEBUG_PAUSE) Log.v(TAG, "App died during pause, not stopping: " + prev); prev = null; } mPausingActivity = null; } if (!mSleeping && !mShuttingDown) { resumeTopActivityLocked(prev); } else { if (mGoingToSleep.isHeld()) { mGoingToSleep.release(); } if (mShuttingDown) { notifyAll(); } } if (prev != null) { prev.resumeKeyDispatchingLocked(); } if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) { long diff = 0; synchronized (mProcessStatsThread) { diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume; } if (diff > 0) { BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics(); synchronized (bsi) { BatteryStatsImpl.Uid.Proc ps = bsi.getProcessStatsLocked(prev.info.applicationInfo.uid, prev.info.packageName); if (ps != null) { ps.addForegroundTimeLocked(diff); } } } } prev.cpuTimeAtResume = 0; // reset it } /** * Once we know that we have asked an application to put an activity in * the resumed state (either by launching it or explicitly telling it), * this function updates the rest of our state to match that fact. */ private final void completeResumeLocked(HistoryRecord next) { next.idle = false; next.results = null; next.newIntents = null; // schedule an idle timeout in case the app doesn't do it for us. Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG); msg.obj = next; mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT); if (false) { // The activity was never told to pause, so just keep // things going as-is. To maintain our own state, // we need to emulate it coming back and saying it is // idle. msg = mHandler.obtainMessage(IDLE_NOW_MSG); msg.obj = next; mHandler.sendMessage(msg); } next.thumbnail = null; setFocusedActivityLocked(next); next.resumeKeyDispatchingLocked(); ensureActivitiesVisibleLocked(null, 0); mWindowManager.executeAppTransition(); // Mark the point when the activity is resuming // TODO: To be more accurate, the mark should be before the onCreate, // not after the onResume. But for subsequent starts, onResume is fine. if (next.app != null) { synchronized (mProcessStatsThread) { next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid); } } else { next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process } } /** * Make sure that all activities that need to be visible (that is, they * currently can be seen by the user) actually are. */ private final void ensureActivitiesVisibleLocked(HistoryRecord top, HistoryRecord starting, String onlyThisProcess, int configChanges) { if (DEBUG_VISBILITY) Log.v( TAG, "ensureActivitiesVisible behind " + top + " configChanges=0x" + Integer.toHexString(configChanges)); // If the top activity is not fullscreen, then we need to // make sure any activities under it are now visible. final int count = mHistory.size(); int i = count-1; while (mHistory.get(i) != top) { i--; } HistoryRecord r; boolean behindFullscreen = false; for (; i>=0; i--) { r = (HistoryRecord)mHistory.get(i); if (DEBUG_VISBILITY) Log.v( TAG, "Make visible? " + r + " finishing=" + r.finishing + " state=" + r.state); if (r.finishing) { continue; } final boolean doThisProcess = onlyThisProcess == null || onlyThisProcess.equals(r.processName); // First: if this is not the current activity being started, make // sure it matches the current configuration. if (r != starting && doThisProcess) { ensureActivityConfigurationLocked(r, 0); } if (r.app == null || r.app.thread == null) { if (onlyThisProcess == null || onlyThisProcess.equals(r.processName)) { // This activity needs to be visible, but isn't even // running... get it started, but don't resume it // at this point. if (DEBUG_VISBILITY) Log.v( TAG, "Start and freeze screen for " + r); if (r != starting) { r.startFreezingScreenLocked(r.app, configChanges); } if (!r.visible) { if (DEBUG_VISBILITY) Log.v( TAG, "Starting and making visible: " + r); mWindowManager.setAppVisibility(r, true); } if (r != starting) { startSpecificActivityLocked(r, false, false); } } } else if (r.visible) { // If this activity is already visible, then there is nothing // else to do here. if (DEBUG_VISBILITY) Log.v( TAG, "Skipping: already visible at " + r); r.stopFreezingScreenLocked(false); } else if (onlyThisProcess == null) { // This activity is not currently visible, but is running. // Tell it to become visible. r.visible = true; if (r.state != ActivityState.RESUMED && r != starting) { // If this activity is paused, tell it // to now show its window. if (DEBUG_VISBILITY) Log.v( TAG, "Making visible and scheduling visibility: " + r); try { mWindowManager.setAppVisibility(r, true); r.app.thread.scheduleWindowVisibility(r, true); r.stopFreezingScreenLocked(false); } catch (Exception e) { // Just skip on any failure; we'll make it // visible when it next restarts. Log.w(TAG, "Exception thrown making visibile: " + r.intent.getComponent(), e); } } } // Aggregate current change flags. configChanges |= r.configChangeFlags; if (r.fullscreen) { // At this point, nothing else needs to be shown if (DEBUG_VISBILITY) Log.v( TAG, "Stopping: fullscreen at " + r); behindFullscreen = true; i--; break; } } // Now for any activities that aren't visible to the user, make // sure they no longer are keeping the screen frozen. while (i >= 0) { r = (HistoryRecord)mHistory.get(i); if (DEBUG_VISBILITY) Log.v( TAG, "Make invisible? " + r + " finishing=" + r.finishing + " state=" + r.state + " behindFullscreen=" + behindFullscreen); if (!r.finishing) { if (behindFullscreen) { if (r.visible) { if (DEBUG_VISBILITY) Log.v( TAG, "Making invisible: " + r); r.visible = false; try { mWindowManager.setAppVisibility(r, false); if ((r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) && r.app != null && r.app.thread != null) { if (DEBUG_VISBILITY) Log.v( TAG, "Scheduling invisibility: " + r); r.app.thread.scheduleWindowVisibility(r, false); } } catch (Exception e) { // Just skip on any failure; we'll make it // visible when it next restarts. Log.w(TAG, "Exception thrown making hidden: " + r.intent.getComponent(), e); } } else { if (DEBUG_VISBILITY) Log.v( TAG, "Already invisible: " + r); } } else if (r.fullscreen) { if (DEBUG_VISBILITY) Log.v( TAG, "Now behindFullscreen: " + r); behindFullscreen = true; } } i--; } } /** * Version of ensureActivitiesVisible that can easily be called anywhere. */ private final void ensureActivitiesVisibleLocked(HistoryRecord starting, int configChanges) { HistoryRecord r = topRunningActivityLocked(null); if (r != null) { ensureActivitiesVisibleLocked(r, starting, null, configChanges); } } private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) { if (resumed) { mUsageStatsService.noteResumeComponent(resumedComponent.realActivity); } else { mUsageStatsService.notePauseComponent(resumedComponent.realActivity); } } private 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); startActivityLocked(null, intent, null, null, 0, aInfo, null, null, 0, 0, 0, false, false); } } return true; } /** * Starts the "new version setup screen" if appropriate. */ private 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 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