Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.app;
     18 
     19 import android.app.backup.BackupAgent;
     20 import android.content.BroadcastReceiver;
     21 import android.content.ComponentCallbacks;
     22 import android.content.ComponentName;
     23 import android.content.ContentProvider;
     24 import android.content.Context;
     25 import android.content.IContentProvider;
     26 import android.content.Intent;
     27 import android.content.IIntentReceiver;
     28 import android.content.ServiceConnection;
     29 import android.content.pm.ActivityInfo;
     30 import android.content.pm.ApplicationInfo;
     31 import android.content.pm.IPackageManager;
     32 import android.content.pm.InstrumentationInfo;
     33 import android.content.pm.PackageManager;
     34 import android.content.pm.ProviderInfo;
     35 import android.content.pm.ServiceInfo;
     36 import android.content.res.AssetManager;
     37 import android.content.res.CompatibilityInfo;
     38 import android.content.res.Configuration;
     39 import android.content.res.Resources;
     40 import android.database.sqlite.SQLiteDatabase;
     41 import android.database.sqlite.SQLiteDebug;
     42 import android.database.sqlite.SQLiteDebug.DbStats;
     43 import android.graphics.Bitmap;
     44 import android.graphics.Canvas;
     45 import android.os.Bundle;
     46 import android.os.Debug;
     47 import android.os.Handler;
     48 import android.os.IBinder;
     49 import android.os.Looper;
     50 import android.os.Message;
     51 import android.os.MessageQueue;
     52 import android.os.ParcelFileDescriptor;
     53 import android.os.Process;
     54 import android.os.RemoteException;
     55 import android.os.ServiceManager;
     56 import android.os.SystemClock;
     57 import android.util.AndroidRuntimeException;
     58 import android.util.Config;
     59 import android.util.DisplayMetrics;
     60 import android.util.EventLog;
     61 import android.util.Log;
     62 import android.util.Slog;
     63 import android.view.Display;
     64 import android.view.View;
     65 import android.view.ViewDebug;
     66 import android.view.ViewManager;
     67 import android.view.ViewRoot;
     68 import android.view.Window;
     69 import android.view.WindowManager;
     70 import android.view.WindowManagerImpl;
     71 
     72 import com.android.internal.os.BinderInternal;
     73 import com.android.internal.os.RuntimeInit;
     74 import com.android.internal.os.SamplingProfilerIntegration;
     75 import com.android.internal.util.ArrayUtils;
     76 
     77 import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
     78 
     79 import java.io.File;
     80 import java.io.FileDescriptor;
     81 import java.io.FileOutputStream;
     82 import java.io.IOException;
     83 import java.io.InputStream;
     84 import java.io.PrintWriter;
     85 import java.lang.ref.WeakReference;
     86 import java.net.URL;
     87 import java.util.ArrayList;
     88 import java.util.Enumeration;
     89 import java.util.HashMap;
     90 import java.util.Iterator;
     91 import java.util.List;
     92 import java.util.Locale;
     93 import java.util.Map;
     94 import java.util.TimeZone;
     95 import java.util.regex.Pattern;
     96 
     97 import dalvik.system.SamplingProfiler;
     98 
     99 final class IntentReceiverLeaked extends AndroidRuntimeException {
    100     public IntentReceiverLeaked(String msg) {
    101         super(msg);
    102     }
    103 }
    104 
    105 final class ServiceConnectionLeaked extends AndroidRuntimeException {
    106     public ServiceConnectionLeaked(String msg) {
    107         super(msg);
    108     }
    109 }
    110 
    111 final class SuperNotCalledException extends AndroidRuntimeException {
    112     public SuperNotCalledException(String msg) {
    113         super(msg);
    114     }
    115 }
    116 
    117 /**
    118  * This manages the execution of the main thread in an
    119  * application process, scheduling and executing activities,
    120  * broadcasts, and other operations on it as the activity
    121  * manager requests.
    122  *
    123  * {@hide}
    124  */
    125 public final class ActivityThread {
    126     private static final String TAG = "ActivityThread";
    127     private static final boolean DEBUG = false;
    128     private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
    129     private static final boolean DEBUG_BROADCAST = false;
    130     private static final boolean DEBUG_RESULTS = false;
    131     private static final boolean DEBUG_BACKUP = false;
    132     private static final boolean DEBUG_CONFIGURATION = false;
    133     private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
    134     private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
    135     private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
    136     private static final int LOG_ON_PAUSE_CALLED = 30021;
    137     private static final int LOG_ON_RESUME_CALLED = 30022;
    138 
    139 
    140     public static final ActivityThread currentActivityThread() {
    141         return (ActivityThread)sThreadLocal.get();
    142     }
    143 
    144     public static final String currentPackageName()
    145     {
    146         ActivityThread am = currentActivityThread();
    147         return (am != null && am.mBoundApplication != null)
    148             ? am.mBoundApplication.processName : null;
    149     }
    150 
    151     public static IPackageManager getPackageManager() {
    152         if (sPackageManager != null) {
    153             //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
    154             return sPackageManager;
    155         }
    156         IBinder b = ServiceManager.getService("package");
    157         //Slog.v("PackageManager", "default service binder = " + b);
    158         sPackageManager = IPackageManager.Stub.asInterface(b);
    159         //Slog.v("PackageManager", "default service = " + sPackageManager);
    160         return sPackageManager;
    161     }
    162 
    163     DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
    164         if (mDisplayMetrics != null && !forceUpdate) {
    165             return mDisplayMetrics;
    166         }
    167         if (mDisplay == null) {
    168             WindowManager wm = WindowManagerImpl.getDefault();
    169             mDisplay = wm.getDefaultDisplay();
    170         }
    171         DisplayMetrics metrics = mDisplayMetrics = new DisplayMetrics();
    172         mDisplay.getMetrics(metrics);
    173         //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
    174         //        + metrics.heightPixels + " den=" + metrics.density
    175         //        + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
    176         return metrics;
    177     }
    178 
    179     /**
    180      * Creates the top level Resources for applications with the given compatibility info.
    181      *
    182      * @param resDir the resource directory.
    183      * @param compInfo the compability info. It will use the default compatibility info when it's
    184      * null.
    185      */
    186     Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
    187         ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
    188         Resources r;
    189         synchronized (mPackages) {
    190             // Resources is app scale dependent.
    191             if (false) {
    192                 Slog.w(TAG, "getTopLevelResources: " + resDir + " / "
    193                         + compInfo.applicationScale);
    194             }
    195             WeakReference<Resources> wr = mActiveResources.get(key);
    196             r = wr != null ? wr.get() : null;
    197             //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
    198             if (r != null && r.getAssets().isUpToDate()) {
    199                 if (false) {
    200                     Slog.w(TAG, "Returning cached resources " + r + " " + resDir
    201                             + ": appScale=" + r.getCompatibilityInfo().applicationScale);
    202                 }
    203                 return r;
    204             }
    205         }
    206 
    207         //if (r != null) {
    208         //    Slog.w(TAG, "Throwing away out-of-date resources!!!! "
    209         //            + r + " " + resDir);
    210         //}
    211 
    212         AssetManager assets = new AssetManager();
    213         if (assets.addAssetPath(resDir) == 0) {
    214             return null;
    215         }
    216 
    217         //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
    218         DisplayMetrics metrics = getDisplayMetricsLocked(false);
    219         r = new Resources(assets, metrics, getConfiguration(), compInfo);
    220         if (false) {
    221             Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
    222                     + r.getConfiguration() + " appScale="
    223                     + r.getCompatibilityInfo().applicationScale);
    224         }
    225 
    226         synchronized (mPackages) {
    227             WeakReference<Resources> wr = mActiveResources.get(key);
    228             Resources existing = wr != null ? wr.get() : null;
    229             if (existing != null && existing.getAssets().isUpToDate()) {
    230                 // Someone else already created the resources while we were
    231                 // unlocked; go ahead and use theirs.
    232                 r.getAssets().close();
    233                 return existing;
    234             }
    235 
    236             // XXX need to remove entries when weak references go away
    237             mActiveResources.put(key, new WeakReference<Resources>(r));
    238             return r;
    239         }
    240     }
    241 
    242     /**
    243      * Creates the top level resources for the given package.
    244      */
    245     Resources getTopLevelResources(String resDir, PackageInfo pkgInfo) {
    246         return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo);
    247     }
    248 
    249     final Handler getHandler() {
    250         return mH;
    251     }
    252 
    253     public final static class PackageInfo {
    254 
    255         private final ActivityThread mActivityThread;
    256         private final ApplicationInfo mApplicationInfo;
    257         private final String mPackageName;
    258         private final String mAppDir;
    259         private final String mResDir;
    260         private final String[] mSharedLibraries;
    261         private final String mDataDir;
    262         private final File mDataDirFile;
    263         private final ClassLoader mBaseClassLoader;
    264         private final boolean mSecurityViolation;
    265         private final boolean mIncludeCode;
    266         private Resources mResources;
    267         private ClassLoader mClassLoader;
    268         private Application mApplication;
    269         private CompatibilityInfo mCompatibilityInfo;
    270 
    271         private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
    272             = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
    273         private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mUnregisteredReceivers
    274         = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
    275         private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mServices
    276             = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
    277         private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mUnboundServices
    278             = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
    279 
    280         int mClientCount = 0;
    281 
    282         Application getApplication() {
    283             return mApplication;
    284         }
    285 
    286         public PackageInfo(ActivityThread activityThread, ApplicationInfo aInfo,
    287                 ActivityThread mainThread, ClassLoader baseLoader,
    288                 boolean securityViolation, boolean includeCode) {
    289             mActivityThread = activityThread;
    290             mApplicationInfo = aInfo;
    291             mPackageName = aInfo.packageName;
    292             mAppDir = aInfo.sourceDir;
    293             mResDir = aInfo.uid == Process.myUid() ? aInfo.sourceDir
    294                     : aInfo.publicSourceDir;
    295             mSharedLibraries = aInfo.sharedLibraryFiles;
    296             mDataDir = aInfo.dataDir;
    297             mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
    298             mBaseClassLoader = baseLoader;
    299             mSecurityViolation = securityViolation;
    300             mIncludeCode = includeCode;
    301             mCompatibilityInfo = new CompatibilityInfo(aInfo);
    302 
    303             if (mAppDir == null) {
    304                 if (mSystemContext == null) {
    305                     mSystemContext =
    306                         ContextImpl.createSystemContext(mainThread);
    307                     mSystemContext.getResources().updateConfiguration(
    308                              mainThread.getConfiguration(),
    309                              mainThread.getDisplayMetricsLocked(false));
    310                     //Slog.i(TAG, "Created system resources "
    311                     //        + mSystemContext.getResources() + ": "
    312                     //        + mSystemContext.getResources().getConfiguration());
    313                 }
    314                 mClassLoader = mSystemContext.getClassLoader();
    315                 mResources = mSystemContext.getResources();
    316             }
    317         }
    318 
    319         public PackageInfo(ActivityThread activityThread, String name,
    320                 Context systemContext, ApplicationInfo info) {
    321             mActivityThread = activityThread;
    322             mApplicationInfo = info != null ? info : new ApplicationInfo();
    323             mApplicationInfo.packageName = name;
    324             mPackageName = name;
    325             mAppDir = null;
    326             mResDir = null;
    327             mSharedLibraries = null;
    328             mDataDir = null;
    329             mDataDirFile = null;
    330             mBaseClassLoader = null;
    331             mSecurityViolation = false;
    332             mIncludeCode = true;
    333             mClassLoader = systemContext.getClassLoader();
    334             mResources = systemContext.getResources();
    335             mCompatibilityInfo = new CompatibilityInfo(mApplicationInfo);
    336         }
    337 
    338         public String getPackageName() {
    339             return mPackageName;
    340         }
    341 
    342         public ApplicationInfo getApplicationInfo() {
    343             return mApplicationInfo;
    344         }
    345 
    346         public boolean isSecurityViolation() {
    347             return mSecurityViolation;
    348         }
    349 
    350         /**
    351          * Gets the array of shared libraries that are listed as
    352          * used by the given package.
    353          *
    354          * @param packageName the name of the package (note: not its
    355          * file name)
    356          * @return null-ok; the array of shared libraries, each one
    357          * a fully-qualified path
    358          */
    359         private static String[] getLibrariesFor(String packageName) {
    360             ApplicationInfo ai = null;
    361             try {
    362                 ai = getPackageManager().getApplicationInfo(packageName,
    363                         PackageManager.GET_SHARED_LIBRARY_FILES);
    364             } catch (RemoteException e) {
    365                 throw new AssertionError(e);
    366             }
    367 
    368             if (ai == null) {
    369                 return null;
    370             }
    371 
    372             return ai.sharedLibraryFiles;
    373         }
    374 
    375         /**
    376          * Combines two arrays (of library names) such that they are
    377          * concatenated in order but are devoid of duplicates. The
    378          * result is a single string with the names of the libraries
    379          * separated by colons, or <code>null</code> if both lists
    380          * were <code>null</code> or empty.
    381          *
    382          * @param list1 null-ok; the first list
    383          * @param list2 null-ok; the second list
    384          * @return null-ok; the combination
    385          */
    386         private static String combineLibs(String[] list1, String[] list2) {
    387             StringBuilder result = new StringBuilder(300);
    388             boolean first = true;
    389 
    390             if (list1 != null) {
    391                 for (String s : list1) {
    392                     if (first) {
    393                         first = false;
    394                     } else {
    395                         result.append(':');
    396                     }
    397                     result.append(s);
    398                 }
    399             }
    400 
    401             // Only need to check for duplicates if list1 was non-empty.
    402             boolean dupCheck = !first;
    403 
    404             if (list2 != null) {
    405                 for (String s : list2) {
    406                     if (dupCheck && ArrayUtils.contains(list1, s)) {
    407                         continue;
    408                     }
    409 
    410                     if (first) {
    411                         first = false;
    412                     } else {
    413                         result.append(':');
    414                     }
    415                     result.append(s);
    416                 }
    417             }
    418 
    419             return result.toString();
    420         }
    421 
    422         public ClassLoader getClassLoader() {
    423             synchronized (this) {
    424                 if (mClassLoader != null) {
    425                     return mClassLoader;
    426                 }
    427 
    428                 if (mIncludeCode && !mPackageName.equals("android")) {
    429                     String zip = mAppDir;
    430 
    431                     /*
    432                      * The following is a bit of a hack to inject
    433                      * instrumentation into the system: If the app
    434                      * being started matches one of the instrumentation names,
    435                      * then we combine both the "instrumentation" and
    436                      * "instrumented" app into the path, along with the
    437                      * concatenation of both apps' shared library lists.
    438                      */
    439 
    440                     String instrumentationAppDir =
    441                             mActivityThread.mInstrumentationAppDir;
    442                     String instrumentationAppPackage =
    443                             mActivityThread.mInstrumentationAppPackage;
    444                     String instrumentedAppDir =
    445                             mActivityThread.mInstrumentedAppDir;
    446                     String[] instrumentationLibs = null;
    447 
    448                     if (mAppDir.equals(instrumentationAppDir)
    449                             || mAppDir.equals(instrumentedAppDir)) {
    450                         zip = instrumentationAppDir + ":" + instrumentedAppDir;
    451                         if (! instrumentedAppDir.equals(instrumentationAppDir)) {
    452                             instrumentationLibs =
    453                                 getLibrariesFor(instrumentationAppPackage);
    454                         }
    455                     }
    456 
    457                     if ((mSharedLibraries != null) ||
    458                             (instrumentationLibs != null)) {
    459                         zip =
    460                             combineLibs(mSharedLibraries, instrumentationLibs)
    461                             + ':' + zip;
    462                     }
    463 
    464                     /*
    465                      * With all the combination done (if necessary, actually
    466                      * create the class loader.
    467                      */
    468 
    469                     if (localLOGV) Slog.v(TAG, "Class path: " + zip);
    470 
    471                     mClassLoader =
    472                         ApplicationLoaders.getDefault().getClassLoader(
    473                             zip, mDataDir, mBaseClassLoader);
    474                     initializeJavaContextClassLoader();
    475                 } else {
    476                     if (mBaseClassLoader == null) {
    477                         mClassLoader = ClassLoader.getSystemClassLoader();
    478                     } else {
    479                         mClassLoader = mBaseClassLoader;
    480                     }
    481                 }
    482                 return mClassLoader;
    483             }
    484         }
    485 
    486         /**
    487          * Setup value for Thread.getContextClassLoader(). If the
    488          * package will not run in in a VM with other packages, we set
    489          * the Java context ClassLoader to the
    490          * PackageInfo.getClassLoader value. However, if this VM can
    491          * contain multiple packages, we intead set the Java context
    492          * ClassLoader to a proxy that will warn about the use of Java
    493          * context ClassLoaders and then fall through to use the
    494          * system ClassLoader.
    495          *
    496          * <p> Note that this is similar to but not the same as the
    497          * android.content.Context.getClassLoader(). While both
    498          * context class loaders are typically set to the
    499          * PathClassLoader used to load the package archive in the
    500          * single application per VM case, a single Android process
    501          * may contain several Contexts executing on one thread with
    502          * their own logical ClassLoaders while the Java context
    503          * ClassLoader is a thread local. This is why in the case when
    504          * we have multiple packages per VM we do not set the Java
    505          * context ClassLoader to an arbitrary but instead warn the
    506          * user to set their own if we detect that they are using a
    507          * Java library that expects it to be set.
    508          */
    509         private void initializeJavaContextClassLoader() {
    510             IPackageManager pm = getPackageManager();
    511             android.content.pm.PackageInfo pi;
    512             try {
    513                 pi = pm.getPackageInfo(mPackageName, 0);
    514             } catch (RemoteException e) {
    515                 throw new AssertionError(e);
    516             }
    517             /*
    518              * Two possible indications that this package could be
    519              * sharing its virtual machine with other packages:
    520              *
    521              * 1.) the sharedUserId attribute is set in the manifest,
    522              *     indicating a request to share a VM with other
    523              *     packages with the same sharedUserId.
    524              *
    525              * 2.) the application element of the manifest has an
    526              *     attribute specifying a non-default process name,
    527              *     indicating the desire to run in another packages VM.
    528              */
    529             boolean sharedUserIdSet = (pi.sharedUserId != null);
    530             boolean processNameNotDefault =
    531                 (pi.applicationInfo != null &&
    532                  !mPackageName.equals(pi.applicationInfo.processName));
    533             boolean sharable = (sharedUserIdSet || processNameNotDefault);
    534             ClassLoader contextClassLoader =
    535                 (sharable)
    536                 ? new WarningContextClassLoader()
    537                 : mClassLoader;
    538             Thread.currentThread().setContextClassLoader(contextClassLoader);
    539         }
    540 
    541         private static class WarningContextClassLoader extends ClassLoader {
    542 
    543             private static boolean warned = false;
    544 
    545             private void warn(String methodName) {
    546                 if (warned) {
    547                     return;
    548                 }
    549                 warned = true;
    550                 Thread.currentThread().setContextClassLoader(getParent());
    551                 Slog.w(TAG, "ClassLoader." + methodName + ": " +
    552                       "The class loader returned by " +
    553                       "Thread.getContextClassLoader() may fail for processes " +
    554                       "that host multiple applications. You should explicitly " +
    555                       "specify a context class loader. For example: " +
    556                       "Thread.setContextClassLoader(getClass().getClassLoader());");
    557             }
    558 
    559             @Override public URL getResource(String resName) {
    560                 warn("getResource");
    561                 return getParent().getResource(resName);
    562             }
    563 
    564             @Override public Enumeration<URL> getResources(String resName) throws IOException {
    565                 warn("getResources");
    566                 return getParent().getResources(resName);
    567             }
    568 
    569             @Override public InputStream getResourceAsStream(String resName) {
    570                 warn("getResourceAsStream");
    571                 return getParent().getResourceAsStream(resName);
    572             }
    573 
    574             @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
    575                 warn("loadClass");
    576                 return getParent().loadClass(className);
    577             }
    578 
    579             @Override public void setClassAssertionStatus(String cname, boolean enable) {
    580                 warn("setClassAssertionStatus");
    581                 getParent().setClassAssertionStatus(cname, enable);
    582             }
    583 
    584             @Override public void setPackageAssertionStatus(String pname, boolean enable) {
    585                 warn("setPackageAssertionStatus");
    586                 getParent().setPackageAssertionStatus(pname, enable);
    587             }
    588 
    589             @Override public void setDefaultAssertionStatus(boolean enable) {
    590                 warn("setDefaultAssertionStatus");
    591                 getParent().setDefaultAssertionStatus(enable);
    592             }
    593 
    594             @Override public void clearAssertionStatus() {
    595                 warn("clearAssertionStatus");
    596                 getParent().clearAssertionStatus();
    597             }
    598         }
    599 
    600         public String getAppDir() {
    601             return mAppDir;
    602         }
    603 
    604         public String getResDir() {
    605             return mResDir;
    606         }
    607 
    608         public String getDataDir() {
    609             return mDataDir;
    610         }
    611 
    612         public File getDataDirFile() {
    613             return mDataDirFile;
    614         }
    615 
    616         public AssetManager getAssets(ActivityThread mainThread) {
    617             return getResources(mainThread).getAssets();
    618         }
    619 
    620         public Resources getResources(ActivityThread mainThread) {
    621             if (mResources == null) {
    622                 mResources = mainThread.getTopLevelResources(mResDir, this);
    623             }
    624             return mResources;
    625         }
    626 
    627         public Application makeApplication(boolean forceDefaultAppClass,
    628                 Instrumentation instrumentation) {
    629             if (mApplication != null) {
    630                 return mApplication;
    631             }
    632 
    633             Application app = null;
    634 
    635             String appClass = mApplicationInfo.className;
    636             if (forceDefaultAppClass || (appClass == null)) {
    637                 appClass = "android.app.Application";
    638             }
    639 
    640             try {
    641                 java.lang.ClassLoader cl = getClassLoader();
    642                 ContextImpl appContext = new ContextImpl();
    643                 appContext.init(this, null, mActivityThread);
    644                 app = mActivityThread.mInstrumentation.newApplication(
    645                         cl, appClass, appContext);
    646                 appContext.setOuterContext(app);
    647             } catch (Exception e) {
    648                 if (!mActivityThread.mInstrumentation.onException(app, e)) {
    649                     throw new RuntimeException(
    650                         "Unable to instantiate application " + appClass
    651                         + ": " + e.toString(), e);
    652                 }
    653             }
    654             mActivityThread.mAllApplications.add(app);
    655             mApplication = app;
    656 
    657             if (instrumentation != null) {
    658                 try {
    659                     instrumentation.callApplicationOnCreate(app);
    660                 } catch (Exception e) {
    661                     if (!instrumentation.onException(app, e)) {
    662                         throw new RuntimeException(
    663                             "Unable to create application " + app.getClass().getName()
    664                             + ": " + e.toString(), e);
    665                     }
    666                 }
    667             }
    668 
    669             return app;
    670         }
    671 
    672         public void removeContextRegistrations(Context context,
    673                 String who, String what) {
    674             HashMap<BroadcastReceiver, ReceiverDispatcher> rmap =
    675                 mReceivers.remove(context);
    676             if (rmap != null) {
    677                 Iterator<ReceiverDispatcher> it = rmap.values().iterator();
    678                 while (it.hasNext()) {
    679                     ReceiverDispatcher rd = it.next();
    680                     IntentReceiverLeaked leak = new IntentReceiverLeaked(
    681                             what + " " + who + " has leaked IntentReceiver "
    682                             + rd.getIntentReceiver() + " that was " +
    683                             "originally registered here. Are you missing a " +
    684                             "call to unregisterReceiver()?");
    685                     leak.setStackTrace(rd.getLocation().getStackTrace());
    686                     Slog.e(TAG, leak.getMessage(), leak);
    687                     try {
    688                         ActivityManagerNative.getDefault().unregisterReceiver(
    689                                 rd.getIIntentReceiver());
    690                     } catch (RemoteException e) {
    691                         // system crashed, nothing we can do
    692                     }
    693                 }
    694             }
    695             mUnregisteredReceivers.remove(context);
    696             //Slog.i(TAG, "Receiver registrations: " + mReceivers);
    697             HashMap<ServiceConnection, ServiceDispatcher> smap =
    698                 mServices.remove(context);
    699             if (smap != null) {
    700                 Iterator<ServiceDispatcher> it = smap.values().iterator();
    701                 while (it.hasNext()) {
    702                     ServiceDispatcher sd = it.next();
    703                     ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
    704                             what + " " + who + " has leaked ServiceConnection "
    705                             + sd.getServiceConnection() + " that was originally bound here");
    706                     leak.setStackTrace(sd.getLocation().getStackTrace());
    707                     Slog.e(TAG, leak.getMessage(), leak);
    708                     try {
    709                         ActivityManagerNative.getDefault().unbindService(
    710                                 sd.getIServiceConnection());
    711                     } catch (RemoteException e) {
    712                         // system crashed, nothing we can do
    713                     }
    714                     sd.doForget();
    715                 }
    716             }
    717             mUnboundServices.remove(context);
    718             //Slog.i(TAG, "Service registrations: " + mServices);
    719         }
    720 
    721         public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
    722                 Context context, Handler handler,
    723                 Instrumentation instrumentation, boolean registered) {
    724             synchronized (mReceivers) {
    725                 ReceiverDispatcher rd = null;
    726                 HashMap<BroadcastReceiver, ReceiverDispatcher> map = null;
    727                 if (registered) {
    728                     map = mReceivers.get(context);
    729                     if (map != null) {
    730                         rd = map.get(r);
    731                     }
    732                 }
    733                 if (rd == null) {
    734                     rd = new ReceiverDispatcher(r, context, handler,
    735                             instrumentation, registered);
    736                     if (registered) {
    737                         if (map == null) {
    738                             map = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
    739                             mReceivers.put(context, map);
    740                         }
    741                         map.put(r, rd);
    742                     }
    743                 } else {
    744                     rd.validate(context, handler);
    745                 }
    746                 return rd.getIIntentReceiver();
    747             }
    748         }
    749 
    750         public IIntentReceiver forgetReceiverDispatcher(Context context,
    751                 BroadcastReceiver r) {
    752             synchronized (mReceivers) {
    753                 HashMap<BroadcastReceiver, ReceiverDispatcher> map = mReceivers.get(context);
    754                 ReceiverDispatcher rd = null;
    755                 if (map != null) {
    756                     rd = map.get(r);
    757                     if (rd != null) {
    758                         map.remove(r);
    759                         if (map.size() == 0) {
    760                             mReceivers.remove(context);
    761                         }
    762                         if (r.getDebugUnregister()) {
    763                             HashMap<BroadcastReceiver, ReceiverDispatcher> holder
    764                                     = mUnregisteredReceivers.get(context);
    765                             if (holder == null) {
    766                                 holder = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
    767                                 mUnregisteredReceivers.put(context, holder);
    768                             }
    769                             RuntimeException ex = new IllegalArgumentException(
    770                                     "Originally unregistered here:");
    771                             ex.fillInStackTrace();
    772                             rd.setUnregisterLocation(ex);
    773                             holder.put(r, rd);
    774                         }
    775                         return rd.getIIntentReceiver();
    776                     }
    777                 }
    778                 HashMap<BroadcastReceiver, ReceiverDispatcher> holder
    779                         = mUnregisteredReceivers.get(context);
    780                 if (holder != null) {
    781                     rd = holder.get(r);
    782                     if (rd != null) {
    783                         RuntimeException ex = rd.getUnregisterLocation();
    784                         throw new IllegalArgumentException(
    785                                 "Unregistering Receiver " + r
    786                                 + " that was already unregistered", ex);
    787                     }
    788                 }
    789                 if (context == null) {
    790                     throw new IllegalStateException("Unbinding Receiver " + r
    791                             + " from Context that is no longer in use: " + context);
    792                 } else {
    793                     throw new IllegalArgumentException("Receiver not registered: " + r);
    794                 }
    795 
    796             }
    797         }
    798 
    799         static final class ReceiverDispatcher {
    800 
    801             final static class InnerReceiver extends IIntentReceiver.Stub {
    802                 final WeakReference<ReceiverDispatcher> mDispatcher;
    803                 final ReceiverDispatcher mStrongRef;
    804 
    805                 InnerReceiver(ReceiverDispatcher rd, boolean strong) {
    806                     mDispatcher = new WeakReference<ReceiverDispatcher>(rd);
    807                     mStrongRef = strong ? rd : null;
    808                 }
    809                 public void performReceive(Intent intent, int resultCode,
    810                         String data, Bundle extras, boolean ordered, boolean sticky) {
    811                     ReceiverDispatcher rd = mDispatcher.get();
    812                     if (DEBUG_BROADCAST) {
    813                         int seq = intent.getIntExtra("seq", -1);
    814                         Slog.i(TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
    815                                 + " to " + (rd != null ? rd.mReceiver : null));
    816                     }
    817                     if (rd != null) {
    818                         rd.performReceive(intent, resultCode, data, extras,
    819                                 ordered, sticky);
    820                     } else {
    821                         // The activity manager dispatched a broadcast to a registered
    822                         // receiver in this process, but before it could be delivered the
    823                         // receiver was unregistered.  Acknowledge the broadcast on its
    824                         // behalf so that the system's broadcast sequence can continue.
    825                         if (DEBUG_BROADCAST) Slog.i(TAG,
    826                                 "Finishing broadcast to unregistered receiver");
    827                         IActivityManager mgr = ActivityManagerNative.getDefault();
    828                         try {
    829                             mgr.finishReceiver(this, resultCode, data, extras, false);
    830                         } catch (RemoteException e) {
    831                             Slog.w(TAG, "Couldn't finish broadcast to unregistered receiver");
    832                         }
    833                     }
    834                 }
    835             }
    836 
    837             final IIntentReceiver.Stub mIIntentReceiver;
    838             final BroadcastReceiver mReceiver;
    839             final Context mContext;
    840             final Handler mActivityThread;
    841             final Instrumentation mInstrumentation;
    842             final boolean mRegistered;
    843             final IntentReceiverLeaked mLocation;
    844             RuntimeException mUnregisterLocation;
    845 
    846             final class Args implements Runnable {
    847                 private Intent mCurIntent;
    848                 private int mCurCode;
    849                 private String mCurData;
    850                 private Bundle mCurMap;
    851                 private boolean mCurOrdered;
    852                 private boolean mCurSticky;
    853 
    854                 public void run() {
    855                     BroadcastReceiver receiver = mReceiver;
    856                     if (DEBUG_BROADCAST) {
    857                         int seq = mCurIntent.getIntExtra("seq", -1);
    858                         Slog.i(TAG, "Dispatching broadcast " + mCurIntent.getAction()
    859                                 + " seq=" + seq + " to " + mReceiver);
    860                         Slog.i(TAG, "  mRegistered=" + mRegistered
    861                                 + " mCurOrdered=" + mCurOrdered);
    862                     }
    863 
    864                     IActivityManager mgr = ActivityManagerNative.getDefault();
    865                     Intent intent = mCurIntent;
    866                     mCurIntent = null;
    867 
    868                     if (receiver == null) {
    869                         if (mRegistered && mCurOrdered) {
    870                             try {
    871                                 if (DEBUG_BROADCAST) Slog.i(TAG,
    872                                         "Finishing null broadcast to " + mReceiver);
    873                                 mgr.finishReceiver(mIIntentReceiver,
    874                                         mCurCode, mCurData, mCurMap, false);
    875                             } catch (RemoteException ex) {
    876                             }
    877                         }
    878                         return;
    879                     }
    880 
    881                     try {
    882                         ClassLoader cl =  mReceiver.getClass().getClassLoader();
    883                         intent.setExtrasClassLoader(cl);
    884                         if (mCurMap != null) {
    885                             mCurMap.setClassLoader(cl);
    886                         }
    887                         receiver.setOrderedHint(true);
    888                         receiver.setResult(mCurCode, mCurData, mCurMap);
    889                         receiver.clearAbortBroadcast();
    890                         receiver.setOrderedHint(mCurOrdered);
    891                         receiver.setInitialStickyHint(mCurSticky);
    892                         receiver.onReceive(mContext, intent);
    893                     } catch (Exception e) {
    894                         if (mRegistered && mCurOrdered) {
    895                             try {
    896                                 if (DEBUG_BROADCAST) Slog.i(TAG,
    897                                         "Finishing failed broadcast to " + mReceiver);
    898                                 mgr.finishReceiver(mIIntentReceiver,
    899                                         mCurCode, mCurData, mCurMap, false);
    900                             } catch (RemoteException ex) {
    901                             }
    902                         }
    903                         if (mInstrumentation == null ||
    904                                 !mInstrumentation.onException(mReceiver, e)) {
    905                             throw new RuntimeException(
    906                                 "Error receiving broadcast " + intent
    907                                 + " in " + mReceiver, e);
    908                         }
    909                     }
    910                     if (mRegistered && mCurOrdered) {
    911                         try {
    912                             if (DEBUG_BROADCAST) Slog.i(TAG,
    913                                     "Finishing broadcast to " + mReceiver);
    914                             mgr.finishReceiver(mIIntentReceiver,
    915                                     receiver.getResultCode(),
    916                                     receiver.getResultData(),
    917                                     receiver.getResultExtras(false),
    918                                     receiver.getAbortBroadcast());
    919                         } catch (RemoteException ex) {
    920                         }
    921                     }
    922                 }
    923             }
    924 
    925             ReceiverDispatcher(BroadcastReceiver receiver, Context context,
    926                     Handler activityThread, Instrumentation instrumentation,
    927                     boolean registered) {
    928                 if (activityThread == null) {
    929                     throw new NullPointerException("Handler must not be null");
    930                 }
    931 
    932                 mIIntentReceiver = new InnerReceiver(this, !registered);
    933                 mReceiver = receiver;
    934                 mContext = context;
    935                 mActivityThread = activityThread;
    936                 mInstrumentation = instrumentation;
    937                 mRegistered = registered;
    938                 mLocation = new IntentReceiverLeaked(null);
    939                 mLocation.fillInStackTrace();
    940             }
    941 
    942             void validate(Context context, Handler activityThread) {
    943                 if (mContext != context) {
    944                     throw new IllegalStateException(
    945                         "Receiver " + mReceiver +
    946                         " registered with differing Context (was " +
    947                         mContext + " now " + context + ")");
    948                 }
    949                 if (mActivityThread != activityThread) {
    950                     throw new IllegalStateException(
    951                         "Receiver " + mReceiver +
    952                         " registered with differing handler (was " +
    953                         mActivityThread + " now " + activityThread + ")");
    954                 }
    955             }
    956 
    957             IntentReceiverLeaked getLocation() {
    958                 return mLocation;
    959             }
    960 
    961             BroadcastReceiver getIntentReceiver() {
    962                 return mReceiver;
    963             }
    964 
    965             IIntentReceiver getIIntentReceiver() {
    966                 return mIIntentReceiver;
    967             }
    968 
    969             void setUnregisterLocation(RuntimeException ex) {
    970                 mUnregisterLocation = ex;
    971             }
    972 
    973             RuntimeException getUnregisterLocation() {
    974                 return mUnregisterLocation;
    975             }
    976 
    977             public void performReceive(Intent intent, int resultCode,
    978                     String data, Bundle extras, boolean ordered, boolean sticky) {
    979                 if (DEBUG_BROADCAST) {
    980                     int seq = intent.getIntExtra("seq", -1);
    981                     Slog.i(TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
    982                             + " to " + mReceiver);
    983                 }
    984                 Args args = new Args();
    985                 args.mCurIntent = intent;
    986                 args.mCurCode = resultCode;
    987                 args.mCurData = data;
    988                 args.mCurMap = extras;
    989                 args.mCurOrdered = ordered;
    990                 args.mCurSticky = sticky;
    991                 if (!mActivityThread.post(args)) {
    992                     if (mRegistered && ordered) {
    993                         IActivityManager mgr = ActivityManagerNative.getDefault();
    994                         try {
    995                             if (DEBUG_BROADCAST) Slog.i(TAG,
    996                                     "Finishing sync broadcast to " + mReceiver);
    997                             mgr.finishReceiver(mIIntentReceiver, args.mCurCode,
    998                                     args.mCurData, args.mCurMap, false);
    999                         } catch (RemoteException ex) {
   1000                         }
   1001                     }
   1002                 }
   1003             }
   1004 
   1005         }
   1006 
   1007         public final IServiceConnection getServiceDispatcher(ServiceConnection c,
   1008                 Context context, Handler handler, int flags) {
   1009             synchronized (mServices) {
   1010                 ServiceDispatcher sd = null;
   1011                 HashMap<ServiceConnection, ServiceDispatcher> map = mServices.get(context);
   1012                 if (map != null) {
   1013                     sd = map.get(c);
   1014                 }
   1015                 if (sd == null) {
   1016                     sd = new ServiceDispatcher(c, context, handler, flags);
   1017                     if (map == null) {
   1018                         map = new HashMap<ServiceConnection, ServiceDispatcher>();
   1019                         mServices.put(context, map);
   1020                     }
   1021                     map.put(c, sd);
   1022                 } else {
   1023                     sd.validate(context, handler);
   1024                 }
   1025                 return sd.getIServiceConnection();
   1026             }
   1027         }
   1028 
   1029         public final IServiceConnection forgetServiceDispatcher(Context context,
   1030                 ServiceConnection c) {
   1031             synchronized (mServices) {
   1032                 HashMap<ServiceConnection, ServiceDispatcher> map
   1033                         = mServices.get(context);
   1034                 ServiceDispatcher sd = null;
   1035                 if (map != null) {
   1036                     sd = map.get(c);
   1037                     if (sd != null) {
   1038                         map.remove(c);
   1039                         sd.doForget();
   1040                         if (map.size() == 0) {
   1041                             mServices.remove(context);
   1042                         }
   1043                         if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
   1044                             HashMap<ServiceConnection, ServiceDispatcher> holder
   1045                                     = mUnboundServices.get(context);
   1046                             if (holder == null) {
   1047                                 holder = new HashMap<ServiceConnection, ServiceDispatcher>();
   1048                                 mUnboundServices.put(context, holder);
   1049                             }
   1050                             RuntimeException ex = new IllegalArgumentException(
   1051                                     "Originally unbound here:");
   1052                             ex.fillInStackTrace();
   1053                             sd.setUnbindLocation(ex);
   1054                             holder.put(c, sd);
   1055                         }
   1056                         return sd.getIServiceConnection();
   1057                     }
   1058                 }
   1059                 HashMap<ServiceConnection, ServiceDispatcher> holder
   1060                         = mUnboundServices.get(context);
   1061                 if (holder != null) {
   1062                     sd = holder.get(c);
   1063                     if (sd != null) {
   1064                         RuntimeException ex = sd.getUnbindLocation();
   1065                         throw new IllegalArgumentException(
   1066                                 "Unbinding Service " + c
   1067                                 + " that was already unbound", ex);
   1068                     }
   1069                 }
   1070                 if (context == null) {
   1071                     throw new IllegalStateException("Unbinding Service " + c
   1072                             + " from Context that is no longer in use: " + context);
   1073                 } else {
   1074                     throw new IllegalArgumentException("Service not registered: " + c);
   1075                 }
   1076             }
   1077         }
   1078 
   1079         static final class ServiceDispatcher {
   1080             private final InnerConnection mIServiceConnection;
   1081             private final ServiceConnection mConnection;
   1082             private final Context mContext;
   1083             private final Handler mActivityThread;
   1084             private final ServiceConnectionLeaked mLocation;
   1085             private final int mFlags;
   1086 
   1087             private RuntimeException mUnbindLocation;
   1088 
   1089             private boolean mDied;
   1090 
   1091             private static class ConnectionInfo {
   1092                 IBinder binder;
   1093                 IBinder.DeathRecipient deathMonitor;
   1094             }
   1095 
   1096             private static class InnerConnection extends IServiceConnection.Stub {
   1097                 final WeakReference<ServiceDispatcher> mDispatcher;
   1098 
   1099                 InnerConnection(ServiceDispatcher sd) {
   1100                     mDispatcher = new WeakReference<ServiceDispatcher>(sd);
   1101                 }
   1102 
   1103                 public void connected(ComponentName name, IBinder service) throws RemoteException {
   1104                     ServiceDispatcher sd = mDispatcher.get();
   1105                     if (sd != null) {
   1106                         sd.connected(name, service);
   1107                     }
   1108                 }
   1109             }
   1110 
   1111             private final HashMap<ComponentName, ConnectionInfo> mActiveConnections
   1112                 = new HashMap<ComponentName, ConnectionInfo>();
   1113 
   1114             ServiceDispatcher(ServiceConnection conn,
   1115                     Context context, Handler activityThread, int flags) {
   1116                 mIServiceConnection = new InnerConnection(this);
   1117                 mConnection = conn;
   1118                 mContext = context;
   1119                 mActivityThread = activityThread;
   1120                 mLocation = new ServiceConnectionLeaked(null);
   1121                 mLocation.fillInStackTrace();
   1122                 mFlags = flags;
   1123             }
   1124 
   1125             void validate(Context context, Handler activityThread) {
   1126                 if (mContext != context) {
   1127                     throw new RuntimeException(
   1128                         "ServiceConnection " + mConnection +
   1129                         " registered with differing Context (was " +
   1130                         mContext + " now " + context + ")");
   1131                 }
   1132                 if (mActivityThread != activityThread) {
   1133                     throw new RuntimeException(
   1134                         "ServiceConnection " + mConnection +
   1135                         " registered with differing handler (was " +
   1136                         mActivityThread + " now " + activityThread + ")");
   1137                 }
   1138             }
   1139 
   1140             void doForget() {
   1141                 synchronized(this) {
   1142                     Iterator<ConnectionInfo> it = mActiveConnections.values().iterator();
   1143                     while (it.hasNext()) {
   1144                         ConnectionInfo ci = it.next();
   1145                         ci.binder.unlinkToDeath(ci.deathMonitor, 0);
   1146                     }
   1147                     mActiveConnections.clear();
   1148                 }
   1149             }
   1150 
   1151             ServiceConnectionLeaked getLocation() {
   1152                 return mLocation;
   1153             }
   1154 
   1155             ServiceConnection getServiceConnection() {
   1156                 return mConnection;
   1157             }
   1158 
   1159             IServiceConnection getIServiceConnection() {
   1160                 return mIServiceConnection;
   1161             }
   1162 
   1163             int getFlags() {
   1164                 return mFlags;
   1165             }
   1166 
   1167             void setUnbindLocation(RuntimeException ex) {
   1168                 mUnbindLocation = ex;
   1169             }
   1170 
   1171             RuntimeException getUnbindLocation() {
   1172                 return mUnbindLocation;
   1173             }
   1174 
   1175             public void connected(ComponentName name, IBinder service) {
   1176                 if (mActivityThread != null) {
   1177                     mActivityThread.post(new RunConnection(name, service, 0));
   1178                 } else {
   1179                     doConnected(name, service);
   1180                 }
   1181             }
   1182 
   1183             public void death(ComponentName name, IBinder service) {
   1184                 ConnectionInfo old;
   1185 
   1186                 synchronized (this) {
   1187                     mDied = true;
   1188                     old = mActiveConnections.remove(name);
   1189                     if (old == null || old.binder != service) {
   1190                         // Death for someone different than who we last
   1191                         // reported...  just ignore it.
   1192                         return;
   1193                     }
   1194                     old.binder.unlinkToDeath(old.deathMonitor, 0);
   1195                 }
   1196 
   1197                 if (mActivityThread != null) {
   1198                     mActivityThread.post(new RunConnection(name, service, 1));
   1199                 } else {
   1200                     doDeath(name, service);
   1201                 }
   1202             }
   1203 
   1204             public void doConnected(ComponentName name, IBinder service) {
   1205                 ConnectionInfo old;
   1206                 ConnectionInfo info;
   1207 
   1208                 synchronized (this) {
   1209                     old = mActiveConnections.get(name);
   1210                     if (old != null && old.binder == service) {
   1211                         // Huh, already have this one.  Oh well!
   1212                         return;
   1213                     }
   1214 
   1215                     if (service != null) {
   1216                         // A new service is being connected... set it all up.
   1217                         mDied = false;
   1218                         info = new ConnectionInfo();
   1219                         info.binder = service;
   1220                         info.deathMonitor = new DeathMonitor(name, service);
   1221                         try {
   1222                             service.linkToDeath(info.deathMonitor, 0);
   1223                             mActiveConnections.put(name, info);
   1224                         } catch (RemoteException e) {
   1225                             // This service was dead before we got it...  just
   1226                             // don't do anything with it.
   1227                             mActiveConnections.remove(name);
   1228                             return;
   1229                         }
   1230 
   1231                     } else {
   1232                         // The named service is being disconnected... clean up.
   1233                         mActiveConnections.remove(name);
   1234                     }
   1235 
   1236                     if (old != null) {
   1237                         old.binder.unlinkToDeath(old.deathMonitor, 0);
   1238                     }
   1239                 }
   1240 
   1241                 // If there was an old service, it is not disconnected.
   1242                 if (old != null) {
   1243                     mConnection.onServiceDisconnected(name);
   1244                 }
   1245                 // If there is a new service, it is now connected.
   1246                 if (service != null) {
   1247                     mConnection.onServiceConnected(name, service);
   1248                 }
   1249             }
   1250 
   1251             public void doDeath(ComponentName name, IBinder service) {
   1252                 mConnection.onServiceDisconnected(name);
   1253             }
   1254 
   1255             private final class RunConnection implements Runnable {
   1256                 RunConnection(ComponentName name, IBinder service, int command) {
   1257                     mName = name;
   1258                     mService = service;
   1259                     mCommand = command;
   1260                 }
   1261 
   1262                 public void run() {
   1263                     if (mCommand == 0) {
   1264                         doConnected(mName, mService);
   1265                     } else if (mCommand == 1) {
   1266                         doDeath(mName, mService);
   1267                     }
   1268                 }
   1269 
   1270                 final ComponentName mName;
   1271                 final IBinder mService;
   1272                 final int mCommand;
   1273             }
   1274 
   1275             private final class DeathMonitor implements IBinder.DeathRecipient
   1276             {
   1277                 DeathMonitor(ComponentName name, IBinder service) {
   1278                     mName = name;
   1279                     mService = service;
   1280                 }
   1281 
   1282                 public void binderDied() {
   1283                     death(mName, mService);
   1284                 }
   1285 
   1286                 final ComponentName mName;
   1287                 final IBinder mService;
   1288             }
   1289         }
   1290     }
   1291 
   1292     private static ContextImpl mSystemContext = null;
   1293 
   1294     private static final class ActivityRecord {
   1295         IBinder token;
   1296         int ident;
   1297         Intent intent;
   1298         Bundle state;
   1299         Activity activity;
   1300         Window window;
   1301         Activity parent;
   1302         String embeddedID;
   1303         Object lastNonConfigurationInstance;
   1304         HashMap<String,Object> lastNonConfigurationChildInstances;
   1305         boolean paused;
   1306         boolean stopped;
   1307         boolean hideForNow;
   1308         Configuration newConfig;
   1309         Configuration createdConfig;
   1310         ActivityRecord nextIdle;
   1311 
   1312         ActivityInfo activityInfo;
   1313         PackageInfo packageInfo;
   1314 
   1315         List<ResultInfo> pendingResults;
   1316         List<Intent> pendingIntents;
   1317 
   1318         boolean startsNotResumed;
   1319         boolean isForward;
   1320 
   1321         ActivityRecord() {
   1322             parent = null;
   1323             embeddedID = null;
   1324             paused = false;
   1325             stopped = false;
   1326             hideForNow = false;
   1327             nextIdle = null;
   1328         }
   1329 
   1330         public String toString() {
   1331             ComponentName componentName = intent.getComponent();
   1332             return "ActivityRecord{"
   1333                 + Integer.toHexString(System.identityHashCode(this))
   1334                 + " token=" + token + " " + (componentName == null
   1335                         ? "no component name" : componentName.toShortString())
   1336                 + "}";
   1337         }
   1338     }
   1339 
   1340     private final class ProviderRecord implements IBinder.DeathRecipient {
   1341         final String mName;
   1342         final IContentProvider mProvider;
   1343         final ContentProvider mLocalProvider;
   1344 
   1345         ProviderRecord(String name, IContentProvider provider,
   1346                 ContentProvider localProvider) {
   1347             mName = name;
   1348             mProvider = provider;
   1349             mLocalProvider = localProvider;
   1350         }
   1351 
   1352         public void binderDied() {
   1353             removeDeadProvider(mName, mProvider);
   1354         }
   1355     }
   1356 
   1357     private static final class NewIntentData {
   1358         List<Intent> intents;
   1359         IBinder token;
   1360         public String toString() {
   1361             return "NewIntentData{intents=" + intents + " token=" + token + "}";
   1362         }
   1363     }
   1364 
   1365     private static final class ReceiverData {
   1366         Intent intent;
   1367         ActivityInfo info;
   1368         int resultCode;
   1369         String resultData;
   1370         Bundle resultExtras;
   1371         boolean sync;
   1372         boolean resultAbort;
   1373         public String toString() {
   1374             return "ReceiverData{intent=" + intent + " packageName=" +
   1375             info.packageName + " resultCode=" + resultCode
   1376             + " resultData=" + resultData + " resultExtras=" + resultExtras + "}";
   1377         }
   1378     }
   1379 
   1380     private static final class CreateBackupAgentData {
   1381         ApplicationInfo appInfo;
   1382         int backupMode;
   1383         public String toString() {
   1384             return "CreateBackupAgentData{appInfo=" + appInfo
   1385                     + " backupAgent=" + appInfo.backupAgentName
   1386                     + " mode=" + backupMode + "}";
   1387         }
   1388     }
   1389 
   1390     private static final class CreateServiceData {
   1391         IBinder token;
   1392         ServiceInfo info;
   1393         Intent intent;
   1394         public String toString() {
   1395             return "CreateServiceData{token=" + token + " className="
   1396             + info.name + " packageName=" + info.packageName
   1397             + " intent=" + intent + "}";
   1398         }
   1399     }
   1400 
   1401     private static final class BindServiceData {
   1402         IBinder token;
   1403         Intent intent;
   1404         boolean rebind;
   1405         public String toString() {
   1406             return "BindServiceData{token=" + token + " intent=" + intent + "}";
   1407         }
   1408     }
   1409 
   1410     private static final class ServiceArgsData {
   1411         IBinder token;
   1412         int startId;
   1413         int flags;
   1414         Intent args;
   1415         public String toString() {
   1416             return "ServiceArgsData{token=" + token + " startId=" + startId
   1417             + " args=" + args + "}";
   1418         }
   1419     }
   1420 
   1421     private static final class AppBindData {
   1422         PackageInfo info;
   1423         String processName;
   1424         ApplicationInfo appInfo;
   1425         List<ProviderInfo> providers;
   1426         ComponentName instrumentationName;
   1427         String profileFile;
   1428         Bundle instrumentationArgs;
   1429         IInstrumentationWatcher instrumentationWatcher;
   1430         int debugMode;
   1431         boolean restrictedBackupMode;
   1432         Configuration config;
   1433         boolean handlingProfiling;
   1434         public String toString() {
   1435             return "AppBindData{appInfo=" + appInfo + "}";
   1436         }
   1437     }
   1438 
   1439     private static final class DumpServiceInfo {
   1440         FileDescriptor fd;
   1441         IBinder service;
   1442         String[] args;
   1443         boolean dumped;
   1444     }
   1445 
   1446     private static final class ResultData {
   1447         IBinder token;
   1448         List<ResultInfo> results;
   1449         public String toString() {
   1450             return "ResultData{token=" + token + " results" + results + "}";
   1451         }
   1452     }
   1453 
   1454     private static final class ContextCleanupInfo {
   1455         ContextImpl context;
   1456         String what;
   1457         String who;
   1458     }
   1459 
   1460     private static final class ProfilerControlData {
   1461         String path;
   1462         ParcelFileDescriptor fd;
   1463     }
   1464 
   1465     private final class ApplicationThread extends ApplicationThreadNative {
   1466         private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
   1467         private static final String ONE_COUNT_COLUMN = "%17s %8d";
   1468         private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
   1469         private static final String DB_INFO_FORMAT = "  %8d %8d %10d  %s";
   1470 
   1471         // Formatting for checkin service - update version if row format changes
   1472         private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
   1473 
   1474         public final void schedulePauseActivity(IBinder token, boolean finished,
   1475                 boolean userLeaving, int configChanges) {
   1476             queueOrSendMessage(
   1477                     finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
   1478                     token,
   1479                     (userLeaving ? 1 : 0),
   1480                     configChanges);
   1481         }
   1482 
   1483         public final void scheduleStopActivity(IBinder token, boolean showWindow,
   1484                 int configChanges) {
   1485            queueOrSendMessage(
   1486                 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
   1487                 token, 0, configChanges);
   1488         }
   1489 
   1490         public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
   1491             queueOrSendMessage(
   1492                 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
   1493                 token);
   1494         }
   1495 
   1496         public final void scheduleResumeActivity(IBinder token, boolean isForward) {
   1497             queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
   1498         }
   1499 
   1500         public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
   1501             ResultData res = new ResultData();
   1502             res.token = token;
   1503             res.results = results;
   1504             queueOrSendMessage(H.SEND_RESULT, res);
   1505         }
   1506 
   1507         // we use token to identify this activity without having to send the
   1508         // activity itself back to the activity manager. (matters more with ipc)
   1509         public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
   1510                 ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
   1511                 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
   1512             ActivityRecord r = new ActivityRecord();
   1513 
   1514             r.token = token;
   1515             r.ident = ident;
   1516             r.intent = intent;
   1517             r.activityInfo = info;
   1518             r.state = state;
   1519 
   1520             r.pendingResults = pendingResults;
   1521             r.pendingIntents = pendingNewIntents;
   1522 
   1523             r.startsNotResumed = notResumed;
   1524             r.isForward = isForward;
   1525 
   1526             queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
   1527         }
   1528 
   1529         public final void scheduleRelaunchActivity(IBinder token,
   1530                 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
   1531                 int configChanges, boolean notResumed, Configuration config) {
   1532             ActivityRecord r = new ActivityRecord();
   1533 
   1534             r.token = token;
   1535             r.pendingResults = pendingResults;
   1536             r.pendingIntents = pendingNewIntents;
   1537             r.startsNotResumed = notResumed;
   1538             r.createdConfig = config;
   1539 
   1540             synchronized (mPackages) {
   1541                 mRelaunchingActivities.add(r);
   1542             }
   1543 
   1544             queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges);
   1545         }
   1546 
   1547         public final void scheduleNewIntent(List<Intent> intents, IBinder token) {
   1548             NewIntentData data = new NewIntentData();
   1549             data.intents = intents;
   1550             data.token = token;
   1551 
   1552             queueOrSendMessage(H.NEW_INTENT, data);
   1553         }
   1554 
   1555         public final void scheduleDestroyActivity(IBinder token, boolean finishing,
   1556                 int configChanges) {
   1557             queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
   1558                     configChanges);
   1559         }
   1560 
   1561         public final void scheduleReceiver(Intent intent, ActivityInfo info,
   1562                 int resultCode, String data, Bundle extras, boolean sync) {
   1563             ReceiverData r = new ReceiverData();
   1564 
   1565             r.intent = intent;
   1566             r.info = info;
   1567             r.resultCode = resultCode;
   1568             r.resultData = data;
   1569             r.resultExtras = extras;
   1570             r.sync = sync;
   1571 
   1572             queueOrSendMessage(H.RECEIVER, r);
   1573         }
   1574 
   1575         public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) {
   1576             CreateBackupAgentData d = new CreateBackupAgentData();
   1577             d.appInfo = app;
   1578             d.backupMode = backupMode;
   1579 
   1580             queueOrSendMessage(H.CREATE_BACKUP_AGENT, d);
   1581         }
   1582 
   1583         public final void scheduleDestroyBackupAgent(ApplicationInfo app) {
   1584             CreateBackupAgentData d = new CreateBackupAgentData();
   1585             d.appInfo = app;
   1586 
   1587             queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d);
   1588         }
   1589 
   1590         public final void scheduleCreateService(IBinder token,
   1591                 ServiceInfo info) {
   1592             CreateServiceData s = new CreateServiceData();
   1593             s.token = token;
   1594             s.info = info;
   1595 
   1596             queueOrSendMessage(H.CREATE_SERVICE, s);
   1597         }
   1598 
   1599         public final void scheduleBindService(IBinder token, Intent intent,
   1600                 boolean rebind) {
   1601             BindServiceData s = new BindServiceData();
   1602             s.token = token;
   1603             s.intent = intent;
   1604             s.rebind = rebind;
   1605 
   1606             queueOrSendMessage(H.BIND_SERVICE, s);
   1607         }
   1608 
   1609         public final void scheduleUnbindService(IBinder token, Intent intent) {
   1610             BindServiceData s = new BindServiceData();
   1611             s.token = token;
   1612             s.intent = intent;
   1613 
   1614             queueOrSendMessage(H.UNBIND_SERVICE, s);
   1615         }
   1616 
   1617         public final void scheduleServiceArgs(IBinder token, int startId,
   1618             int flags ,Intent args) {
   1619             ServiceArgsData s = new ServiceArgsData();
   1620             s.token = token;
   1621             s.startId = startId;
   1622             s.flags = flags;
   1623             s.args = args;
   1624 
   1625             queueOrSendMessage(H.SERVICE_ARGS, s);
   1626         }
   1627 
   1628         public final void scheduleStopService(IBinder token) {
   1629             queueOrSendMessage(H.STOP_SERVICE, token);
   1630         }
   1631 
   1632         public final void bindApplication(String processName,
   1633                 ApplicationInfo appInfo, List<ProviderInfo> providers,
   1634                 ComponentName instrumentationName, String profileFile,
   1635                 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
   1636                 int debugMode, boolean isRestrictedBackupMode, Configuration config,
   1637                 Map<String, IBinder> services) {
   1638 
   1639             if (services != null) {
   1640                 // Setup the service cache in the ServiceManager
   1641                 ServiceManager.initServiceCache(services);
   1642             }
   1643 
   1644             AppBindData data = new AppBindData();
   1645             data.processName = processName;
   1646             data.appInfo = appInfo;
   1647             data.providers = providers;
   1648             data.instrumentationName = instrumentationName;
   1649             data.profileFile = profileFile;
   1650             data.instrumentationArgs = instrumentationArgs;
   1651             data.instrumentationWatcher = instrumentationWatcher;
   1652             data.debugMode = debugMode;
   1653             data.restrictedBackupMode = isRestrictedBackupMode;
   1654             data.config = config;
   1655             queueOrSendMessage(H.BIND_APPLICATION, data);
   1656         }
   1657 
   1658         public final void scheduleExit() {
   1659             queueOrSendMessage(H.EXIT_APPLICATION, null);
   1660         }
   1661 
   1662         public final void scheduleSuicide() {
   1663             queueOrSendMessage(H.SUICIDE, null);
   1664         }
   1665 
   1666         public void requestThumbnail(IBinder token) {
   1667             queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
   1668         }
   1669 
   1670         public void scheduleConfigurationChanged(Configuration config) {
   1671             synchronized (mPackages) {
   1672                 if (mPendingConfiguration == null ||
   1673                         mPendingConfiguration.isOtherSeqNewer(config)) {
   1674                     mPendingConfiguration = config;
   1675                 }
   1676             }
   1677             queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
   1678         }
   1679 
   1680         public void updateTimeZone() {
   1681             TimeZone.setDefault(null);
   1682         }
   1683 
   1684         public void processInBackground() {
   1685             mH.removeMessages(H.GC_WHEN_IDLE);
   1686             mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
   1687         }
   1688 
   1689         public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
   1690             DumpServiceInfo data = new DumpServiceInfo();
   1691             data.fd = fd;
   1692             data.service = servicetoken;
   1693             data.args = args;
   1694             data.dumped = false;
   1695             queueOrSendMessage(H.DUMP_SERVICE, data);
   1696             synchronized (data) {
   1697                 while (!data.dumped) {
   1698                     try {
   1699                         data.wait();
   1700                     } catch (InterruptedException e) {
   1701                         // no need to do anything here, we will keep waiting until
   1702                         // dumped is set
   1703                     }
   1704                 }
   1705             }
   1706         }
   1707 
   1708         // This function exists to make sure all receiver dispatching is
   1709         // correctly ordered, since these are one-way calls and the binder driver
   1710         // applies transaction ordering per object for such calls.
   1711         public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
   1712                 int resultCode, String dataStr, Bundle extras, boolean ordered,
   1713                 boolean sticky) throws RemoteException {
   1714             receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
   1715         }
   1716 
   1717         public void scheduleLowMemory() {
   1718             queueOrSendMessage(H.LOW_MEMORY, null);
   1719         }
   1720 
   1721         public void scheduleActivityConfigurationChanged(IBinder token) {
   1722             queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
   1723         }
   1724 
   1725         public void requestPss() {
   1726             try {
   1727                 ActivityManagerNative.getDefault().reportPss(this,
   1728                         (int)Process.getPss(Process.myPid()));
   1729             } catch (RemoteException e) {
   1730             }
   1731         }
   1732 
   1733         public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
   1734             ProfilerControlData pcd = new ProfilerControlData();
   1735             pcd.path = path;
   1736             pcd.fd = fd;
   1737             queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
   1738         }
   1739 
   1740         public void setSchedulingGroup(int group) {
   1741             // Note: do this immediately, since going into the foreground
   1742             // should happen regardless of what pending work we have to do
   1743             // and the activity manager will wait for us to report back that
   1744             // we are done before sending us to the background.
   1745             try {
   1746                 Process.setProcessGroup(Process.myPid(), group);
   1747             } catch (Exception e) {
   1748                 Slog.w(TAG, "Failed setting process group to " + group, e);
   1749             }
   1750         }
   1751 
   1752         public void getMemoryInfo(Debug.MemoryInfo outInfo) {
   1753             Debug.getMemoryInfo(outInfo);
   1754         }
   1755 
   1756         public void dispatchPackageBroadcast(int cmd, String[] packages) {
   1757             queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
   1758         }
   1759 
   1760         @Override
   1761         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1762             long nativeMax = Debug.getNativeHeapSize() / 1024;
   1763             long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
   1764             long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
   1765 
   1766             Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
   1767             Debug.getMemoryInfo(memInfo);
   1768 
   1769             final int nativeShared = memInfo.nativeSharedDirty;
   1770             final int dalvikShared = memInfo.dalvikSharedDirty;
   1771             final int otherShared = memInfo.otherSharedDirty;
   1772 
   1773             final int nativePrivate = memInfo.nativePrivateDirty;
   1774             final int dalvikPrivate = memInfo.dalvikPrivateDirty;
   1775             final int otherPrivate = memInfo.otherPrivateDirty;
   1776 
   1777             Runtime runtime = Runtime.getRuntime();
   1778 
   1779             long dalvikMax = runtime.totalMemory() / 1024;
   1780             long dalvikFree = runtime.freeMemory() / 1024;
   1781             long dalvikAllocated = dalvikMax - dalvikFree;
   1782             long viewInstanceCount = ViewDebug.getViewInstanceCount();
   1783             long viewRootInstanceCount = ViewDebug.getViewRootInstanceCount();
   1784             long appContextInstanceCount = ContextImpl.getInstanceCount();
   1785             long activityInstanceCount = Activity.getInstanceCount();
   1786             int globalAssetCount = AssetManager.getGlobalAssetCount();
   1787             int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
   1788             int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
   1789             int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
   1790             int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
   1791             int openSslSocketCount = OpenSSLSocketImpl.getInstanceCount();
   1792             long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024;
   1793             SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
   1794 
   1795             // Check to see if we were called by checkin server. If so, print terse format.
   1796             boolean doCheckinFormat = false;
   1797             if (args != null) {
   1798                 for (String arg : args) {
   1799                     if ("-c".equals(arg)) doCheckinFormat = true;
   1800                 }
   1801             }
   1802 
   1803             // For checkin, we print one long comma-separated list of values
   1804             if (doCheckinFormat) {
   1805                 // NOTE: if you change anything significant below, also consider changing
   1806                 // ACTIVITY_THREAD_CHECKIN_VERSION.
   1807                 String processName = (mBoundApplication != null)
   1808                         ? mBoundApplication.processName : "unknown";
   1809 
   1810                 // Header
   1811                 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
   1812                 pw.print(Process.myPid()); pw.print(',');
   1813                 pw.print(processName); pw.print(',');
   1814 
   1815                 // Heap info - max
   1816                 pw.print(nativeMax); pw.print(',');
   1817                 pw.print(dalvikMax); pw.print(',');
   1818                 pw.print("N/A,");
   1819                 pw.print(nativeMax + dalvikMax); pw.print(',');
   1820 
   1821                 // Heap info - allocated
   1822                 pw.print(nativeAllocated); pw.print(',');
   1823                 pw.print(dalvikAllocated); pw.print(',');
   1824                 pw.print("N/A,");
   1825                 pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
   1826 
   1827                 // Heap info - free
   1828                 pw.print(nativeFree); pw.print(',');
   1829                 pw.print(dalvikFree); pw.print(',');
   1830                 pw.print("N/A,");
   1831                 pw.print(nativeFree + dalvikFree); pw.print(',');
   1832 
   1833                 // Heap info - proportional set size
   1834                 pw.print(memInfo.nativePss); pw.print(',');
   1835                 pw.print(memInfo.dalvikPss); pw.print(',');
   1836                 pw.print(memInfo.otherPss); pw.print(',');
   1837                 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
   1838 
   1839                 // Heap info - shared
   1840                 pw.print(nativeShared); pw.print(',');
   1841                 pw.print(dalvikShared); pw.print(',');
   1842                 pw.print(otherShared); pw.print(',');
   1843                 pw.print(nativeShared + dalvikShared + otherShared); pw.print(',');
   1844 
   1845                 // Heap info - private
   1846                 pw.print(nativePrivate); pw.print(',');
   1847                 pw.print(dalvikPrivate); pw.print(',');
   1848                 pw.print(otherPrivate); pw.print(',');
   1849                 pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(',');
   1850 
   1851                 // Object counts
   1852                 pw.print(viewInstanceCount); pw.print(',');
   1853                 pw.print(viewRootInstanceCount); pw.print(',');
   1854                 pw.print(appContextInstanceCount); pw.print(',');
   1855                 pw.print(activityInstanceCount); pw.print(',');
   1856 
   1857                 pw.print(globalAssetCount); pw.print(',');
   1858                 pw.print(globalAssetManagerCount); pw.print(',');
   1859                 pw.print(binderLocalObjectCount); pw.print(',');
   1860                 pw.print(binderProxyObjectCount); pw.print(',');
   1861 
   1862                 pw.print(binderDeathObjectCount); pw.print(',');
   1863                 pw.print(openSslSocketCount); pw.print(',');
   1864 
   1865                 // SQL
   1866                 pw.print(sqliteAllocated); pw.print(',');
   1867                 pw.print(stats.memoryUsed / 1024); pw.print(',');
   1868                 pw.print(stats.pageCacheOverflo / 1024); pw.print(',');
   1869                 pw.print(stats.largestMemAlloc / 1024); pw.print(',');
   1870                 for (int i = 0; i < stats.dbStats.size(); i++) {
   1871                     DbStats dbStats = stats.dbStats.get(i);
   1872                     printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
   1873                             dbStats.lookaside, dbStats.dbName);
   1874                     pw.print(',');
   1875                 }
   1876 
   1877                 return;
   1878             }
   1879 
   1880             // otherwise, show human-readable format
   1881             printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total");
   1882             printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
   1883             printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
   1884                     nativeAllocated + dalvikAllocated);
   1885             printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A",
   1886                     nativeFree + dalvikFree);
   1887 
   1888             printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
   1889                     memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);
   1890 
   1891             printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared,
   1892                     nativeShared + dalvikShared + otherShared);
   1893             printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
   1894                     nativePrivate + dalvikPrivate + otherPrivate);
   1895 
   1896             pw.println(" ");
   1897             pw.println(" Objects");
   1898             printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRoots:",
   1899                     viewRootInstanceCount);
   1900 
   1901             printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
   1902                     "Activities:", activityInstanceCount);
   1903 
   1904             printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
   1905                     "AssetManagers:", globalAssetManagerCount);
   1906 
   1907             printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
   1908                     "Proxy Binders:", binderProxyObjectCount);
   1909             printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount);
   1910 
   1911             printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount);
   1912 
   1913             // SQLite mem info
   1914             pw.println(" ");
   1915             pw.println(" SQL");
   1916             printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "memoryUsed:",
   1917                     stats.memoryUsed / 1024);
   1918             printRow(pw, TWO_COUNT_COLUMNS, "pageCacheOverflo:", stats.pageCacheOverflo / 1024,
   1919                     "largestMemAlloc:", stats.largestMemAlloc / 1024);
   1920             pw.println(" ");
   1921             int N = stats.dbStats.size();
   1922             if (N > 0) {
   1923                 pw.println(" DATABASES");
   1924                 printRow(pw, "  %8s %8s %10s  %s", "Pagesize", "Dbsize", "Lookaside", "Dbname");
   1925                 for (int i = 0; i < N; i++) {
   1926                     DbStats dbStats = stats.dbStats.get(i);
   1927                     printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
   1928                             dbStats.lookaside, dbStats.dbName);
   1929                 }
   1930             }
   1931 
   1932             // Asset details.
   1933             String assetAlloc = AssetManager.getAssetAllocations();
   1934             if (assetAlloc != null) {
   1935                 pw.println(" ");
   1936                 pw.println(" Asset Allocations");
   1937                 pw.print(assetAlloc);
   1938             }
   1939         }
   1940 
   1941         private void printRow(PrintWriter pw, String format, Object...objs) {
   1942             pw.println(String.format(format, objs));
   1943         }
   1944     }
   1945 
   1946     private final class H extends Handler {
   1947         private H() {
   1948             SamplingProfiler.getInstance().setEventThread(mLooper.getThread());
   1949         }
   1950 
   1951         public static final int LAUNCH_ACTIVITY         = 100;
   1952         public static final int PAUSE_ACTIVITY          = 101;
   1953         public static final int PAUSE_ACTIVITY_FINISHING= 102;
   1954         public static final int STOP_ACTIVITY_SHOW      = 103;
   1955         public static final int STOP_ACTIVITY_HIDE      = 104;
   1956         public static final int SHOW_WINDOW             = 105;
   1957         public static final int HIDE_WINDOW             = 106;
   1958         public static final int RESUME_ACTIVITY         = 107;
   1959         public static final int SEND_RESULT             = 108;
   1960         public static final int DESTROY_ACTIVITY         = 109;
   1961         public static final int BIND_APPLICATION        = 110;
   1962         public static final int EXIT_APPLICATION        = 111;
   1963         public static final int NEW_INTENT              = 112;
   1964         public static final int RECEIVER                = 113;
   1965         public static final int CREATE_SERVICE          = 114;
   1966         public static final int SERVICE_ARGS            = 115;
   1967         public static final int STOP_SERVICE            = 116;
   1968         public static final int REQUEST_THUMBNAIL       = 117;
   1969         public static final int CONFIGURATION_CHANGED   = 118;
   1970         public static final int CLEAN_UP_CONTEXT        = 119;
   1971         public static final int GC_WHEN_IDLE            = 120;
   1972         public static final int BIND_SERVICE            = 121;
   1973         public static final int UNBIND_SERVICE          = 122;
   1974         public static final int DUMP_SERVICE            = 123;
   1975         public static final int LOW_MEMORY              = 124;
   1976         public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
   1977         public static final int RELAUNCH_ACTIVITY       = 126;
   1978         public static final int PROFILER_CONTROL        = 127;
   1979         public static final int CREATE_BACKUP_AGENT     = 128;
   1980         public static final int DESTROY_BACKUP_AGENT    = 129;
   1981         public static final int SUICIDE                 = 130;
   1982         public static final int REMOVE_PROVIDER         = 131;
   1983         public static final int ENABLE_JIT              = 132;
   1984         public static final int DISPATCH_PACKAGE_BROADCAST = 133;
   1985         String codeToString(int code) {
   1986             if (localLOGV) {
   1987                 switch (code) {
   1988                     case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
   1989                     case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
   1990                     case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
   1991                     case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
   1992                     case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
   1993                     case SHOW_WINDOW: return "SHOW_WINDOW";
   1994                     case HIDE_WINDOW: return "HIDE_WINDOW";
   1995                     case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
   1996                     case SEND_RESULT: return "SEND_RESULT";
   1997                     case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
   1998                     case BIND_APPLICATION: return "BIND_APPLICATION";
   1999                     case EXIT_APPLICATION: return "EXIT_APPLICATION";
   2000                     case NEW_INTENT: return "NEW_INTENT";
   2001                     case RECEIVER: return "RECEIVER";
   2002                     case CREATE_SERVICE: return "CREATE_SERVICE";
   2003                     case SERVICE_ARGS: return "SERVICE_ARGS";
   2004                     case STOP_SERVICE: return "STOP_SERVICE";
   2005                     case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
   2006                     case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
   2007                     case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
   2008                     case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
   2009                     case BIND_SERVICE: return "BIND_SERVICE";
   2010                     case UNBIND_SERVICE: return "UNBIND_SERVICE";
   2011                     case DUMP_SERVICE: return "DUMP_SERVICE";
   2012                     case LOW_MEMORY: return "LOW_MEMORY";
   2013                     case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
   2014                     case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
   2015                     case PROFILER_CONTROL: return "PROFILER_CONTROL";
   2016                     case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
   2017                     case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
   2018                     case SUICIDE: return "SUICIDE";
   2019                     case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
   2020                     case ENABLE_JIT: return "ENABLE_JIT";
   2021                     case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
   2022                 }
   2023             }
   2024             return "(unknown)";
   2025         }
   2026         public void handleMessage(Message msg) {
   2027             switch (msg.what) {
   2028                 case LAUNCH_ACTIVITY: {
   2029                     ActivityRecord r = (ActivityRecord)msg.obj;
   2030 
   2031                     r.packageInfo = getPackageInfoNoCheck(
   2032                             r.activityInfo.applicationInfo);
   2033                     handleLaunchActivity(r, null);
   2034                 } break;
   2035                 case RELAUNCH_ACTIVITY: {
   2036                     ActivityRecord r = (ActivityRecord)msg.obj;
   2037                     handleRelaunchActivity(r, msg.arg1);
   2038                 } break;
   2039                 case PAUSE_ACTIVITY:
   2040                     handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
   2041                     maybeSnapshot();
   2042                     break;
   2043                 case PAUSE_ACTIVITY_FINISHING:
   2044                     handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
   2045                     break;
   2046                 case STOP_ACTIVITY_SHOW:
   2047                     handleStopActivity((IBinder)msg.obj, true, msg.arg2);
   2048                     break;
   2049                 case STOP_ACTIVITY_HIDE:
   2050                     handleStopActivity((IBinder)msg.obj, false, msg.arg2);
   2051                     break;
   2052                 case SHOW_WINDOW:
   2053                     handleWindowVisibility((IBinder)msg.obj, true);
   2054                     break;
   2055                 case HIDE_WINDOW:
   2056                     handleWindowVisibility((IBinder)msg.obj, false);
   2057                     break;
   2058                 case RESUME_ACTIVITY:
   2059                     handleResumeActivity((IBinder)msg.obj, true,
   2060                             msg.arg1 != 0);
   2061                     break;
   2062                 case SEND_RESULT:
   2063                     handleSendResult((ResultData)msg.obj);
   2064                     break;
   2065                 case DESTROY_ACTIVITY:
   2066                     handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
   2067                             msg.arg2, false);
   2068                     break;
   2069                 case BIND_APPLICATION:
   2070                     AppBindData data = (AppBindData)msg.obj;
   2071                     handleBindApplication(data);
   2072                     break;
   2073                 case EXIT_APPLICATION:
   2074                     if (mInitialApplication != null) {
   2075                         mInitialApplication.onTerminate();
   2076                     }
   2077                     Looper.myLooper().quit();
   2078                     break;
   2079                 case NEW_INTENT:
   2080                     handleNewIntent((NewIntentData)msg.obj);
   2081                     break;
   2082                 case RECEIVER:
   2083                     handleReceiver((ReceiverData)msg.obj);
   2084                     maybeSnapshot();
   2085                     break;
   2086                 case CREATE_SERVICE:
   2087                     handleCreateService((CreateServiceData)msg.obj);
   2088                     break;
   2089                 case BIND_SERVICE:
   2090                     handleBindService((BindServiceData)msg.obj);
   2091                     break;
   2092                 case UNBIND_SERVICE:
   2093                     handleUnbindService((BindServiceData)msg.obj);
   2094                     break;
   2095                 case SERVICE_ARGS:
   2096                     handleServiceArgs((ServiceArgsData)msg.obj);
   2097                     break;
   2098                 case STOP_SERVICE:
   2099                     handleStopService((IBinder)msg.obj);
   2100                     maybeSnapshot();
   2101                     break;
   2102                 case REQUEST_THUMBNAIL:
   2103                     handleRequestThumbnail((IBinder)msg.obj);
   2104                     break;
   2105                 case CONFIGURATION_CHANGED:
   2106                     handleConfigurationChanged((Configuration)msg.obj);
   2107                     break;
   2108                 case CLEAN_UP_CONTEXT:
   2109                     ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
   2110                     cci.context.performFinalCleanup(cci.who, cci.what);
   2111                     break;
   2112                 case GC_WHEN_IDLE:
   2113                     scheduleGcIdler();
   2114                     break;
   2115                 case DUMP_SERVICE:
   2116                     handleDumpService((DumpServiceInfo)msg.obj);
   2117                     break;
   2118                 case LOW_MEMORY:
   2119                     handleLowMemory();
   2120                     break;
   2121                 case ACTIVITY_CONFIGURATION_CHANGED:
   2122                     handleActivityConfigurationChanged((IBinder)msg.obj);
   2123                     break;
   2124                 case PROFILER_CONTROL:
   2125                     handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
   2126                     break;
   2127                 case CREATE_BACKUP_AGENT:
   2128                     handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
   2129                     break;
   2130                 case DESTROY_BACKUP_AGENT:
   2131                     handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
   2132                     break;
   2133                 case SUICIDE:
   2134                     Process.killProcess(Process.myPid());
   2135                     break;
   2136                 case REMOVE_PROVIDER:
   2137                     completeRemoveProvider((IContentProvider)msg.obj);
   2138                     break;
   2139                 case ENABLE_JIT:
   2140                     ensureJitEnabled();
   2141                     break;
   2142                 case DISPATCH_PACKAGE_BROADCAST:
   2143                     handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
   2144                     break;
   2145             }
   2146         }
   2147 
   2148         void maybeSnapshot() {
   2149             if (mBoundApplication != null) {
   2150                 SamplingProfilerIntegration.writeSnapshot(
   2151                         mBoundApplication.processName);
   2152             }
   2153         }
   2154     }
   2155 
   2156     private final class Idler implements MessageQueue.IdleHandler {
   2157         public final boolean queueIdle() {
   2158             ActivityRecord a = mNewActivities;
   2159             if (a != null) {
   2160                 mNewActivities = null;
   2161                 IActivityManager am = ActivityManagerNative.getDefault();
   2162                 ActivityRecord prev;
   2163                 do {
   2164                     if (localLOGV) Slog.v(
   2165                         TAG, "Reporting idle of " + a +
   2166                         " finished=" +
   2167                         (a.activity != null ? a.activity.mFinished : false));
   2168                     if (a.activity != null && !a.activity.mFinished) {
   2169                         try {
   2170                             am.activityIdle(a.token, a.createdConfig);
   2171                             a.createdConfig = null;
   2172                         } catch (RemoteException ex) {
   2173                         }
   2174                     }
   2175                     prev = a;
   2176                     a = a.nextIdle;
   2177                     prev.nextIdle = null;
   2178                 } while (a != null);
   2179             }
   2180             ensureJitEnabled();
   2181             return false;
   2182         }
   2183     }
   2184 
   2185     final class GcIdler implements MessageQueue.IdleHandler {
   2186         public final boolean queueIdle() {
   2187             doGcIfNeeded();
   2188             return false;
   2189         }
   2190     }
   2191 
   2192     private final static class ResourcesKey {
   2193         final private String mResDir;
   2194         final private float mScale;
   2195         final private int mHash;
   2196 
   2197         ResourcesKey(String resDir, float scale) {
   2198             mResDir = resDir;
   2199             mScale = scale;
   2200             mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
   2201         }
   2202 
   2203         @Override
   2204         public int hashCode() {
   2205             return mHash;
   2206         }
   2207 
   2208         @Override
   2209         public boolean equals(Object obj) {
   2210             if (!(obj instanceof ResourcesKey)) {
   2211                 return false;
   2212             }
   2213             ResourcesKey peer = (ResourcesKey) obj;
   2214             return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
   2215         }
   2216     }
   2217 
   2218     static IPackageManager sPackageManager;
   2219 
   2220     final ApplicationThread mAppThread = new ApplicationThread();
   2221     final Looper mLooper = Looper.myLooper();
   2222     final H mH = new H();
   2223     final HashMap<IBinder, ActivityRecord> mActivities
   2224             = new HashMap<IBinder, ActivityRecord>();
   2225     // List of new activities (via ActivityRecord.nextIdle) that should
   2226     // be reported when next we idle.
   2227     ActivityRecord mNewActivities = null;
   2228     // Number of activities that are currently visible on-screen.
   2229     int mNumVisibleActivities = 0;
   2230     final HashMap<IBinder, Service> mServices
   2231             = new HashMap<IBinder, Service>();
   2232     AppBindData mBoundApplication;
   2233     Configuration mConfiguration;
   2234     Configuration mResConfiguration;
   2235     Application mInitialApplication;
   2236     final ArrayList<Application> mAllApplications
   2237             = new ArrayList<Application>();
   2238     // set of instantiated backup agents, keyed by package name
   2239     final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
   2240     static final ThreadLocal sThreadLocal = new ThreadLocal();
   2241     Instrumentation mInstrumentation;
   2242     String mInstrumentationAppDir = null;
   2243     String mInstrumentationAppPackage = null;
   2244     String mInstrumentedAppDir = null;
   2245     boolean mSystemThread = false;
   2246     boolean mJitEnabled = false;
   2247 
   2248     // These can be accessed by multiple threads; mPackages is the lock.
   2249     // XXX For now we keep around information about all packages we have
   2250     // seen, not removing entries from this map.
   2251     final HashMap<String, WeakReference<PackageInfo>> mPackages
   2252             = new HashMap<String, WeakReference<PackageInfo>>();
   2253     final HashMap<String, WeakReference<PackageInfo>> mResourcePackages
   2254             = new HashMap<String, WeakReference<PackageInfo>>();
   2255     Display mDisplay = null;
   2256     DisplayMetrics mDisplayMetrics = null;
   2257     final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
   2258             = new HashMap<ResourcesKey, WeakReference<Resources> >();
   2259     final ArrayList<ActivityRecord> mRelaunchingActivities
   2260             = new ArrayList<ActivityRecord>();
   2261     Configuration mPendingConfiguration = null;
   2262 
   2263     // The lock of mProviderMap protects the following variables.
   2264     final HashMap<String, ProviderRecord> mProviderMap
   2265         = new HashMap<String, ProviderRecord>();
   2266     final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
   2267         = new HashMap<IBinder, ProviderRefCount>();
   2268     final HashMap<IBinder, ProviderRecord> mLocalProviders
   2269         = new HashMap<IBinder, ProviderRecord>();
   2270 
   2271     final GcIdler mGcIdler = new GcIdler();
   2272     boolean mGcIdlerScheduled = false;
   2273 
   2274     public final PackageInfo getPackageInfo(String packageName, int flags) {
   2275         synchronized (mPackages) {
   2276             WeakReference<PackageInfo> ref;
   2277             if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
   2278                 ref = mPackages.get(packageName);
   2279             } else {
   2280                 ref = mResourcePackages.get(packageName);
   2281             }
   2282             PackageInfo packageInfo = ref != null ? ref.get() : null;
   2283             //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
   2284             //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
   2285             //        + ": " + packageInfo.mResources.getAssets().isUpToDate());
   2286             if (packageInfo != null && (packageInfo.mResources == null
   2287                     || packageInfo.mResources.getAssets().isUpToDate())) {
   2288                 if (packageInfo.isSecurityViolation()
   2289                         && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
   2290                     throw new SecurityException(
   2291                             "Requesting code from " + packageName
   2292                             + " to be run in process "
   2293                             + mBoundApplication.processName
   2294                             + "/" + mBoundApplication.appInfo.uid);
   2295                 }
   2296                 return packageInfo;
   2297             }
   2298         }
   2299 
   2300         ApplicationInfo ai = null;
   2301         try {
   2302             ai = getPackageManager().getApplicationInfo(packageName,
   2303                     PackageManager.GET_SHARED_LIBRARY_FILES);
   2304         } catch (RemoteException e) {
   2305         }
   2306 
   2307         if (ai != null) {
   2308             return getPackageInfo(ai, flags);
   2309         }
   2310 
   2311         return null;
   2312     }
   2313 
   2314     public final PackageInfo getPackageInfo(ApplicationInfo ai, int flags) {
   2315         boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
   2316         boolean securityViolation = includeCode && ai.uid != 0
   2317                 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
   2318                         ? ai.uid != mBoundApplication.appInfo.uid : true);
   2319         if ((flags&(Context.CONTEXT_INCLUDE_CODE
   2320                 |Context.CONTEXT_IGNORE_SECURITY))
   2321                 == Context.CONTEXT_INCLUDE_CODE) {
   2322             if (securityViolation) {
   2323                 String msg = "Requesting code from " + ai.packageName
   2324                         + " (with uid " + ai.uid + ")";
   2325                 if (mBoundApplication != null) {
   2326                     msg = msg + " to be run in process "
   2327                         + mBoundApplication.processName + " (with uid "
   2328                         + mBoundApplication.appInfo.uid + ")";
   2329                 }
   2330                 throw new SecurityException(msg);
   2331             }
   2332         }
   2333         return getPackageInfo(ai, null, securityViolation, includeCode);
   2334     }
   2335 
   2336     public final PackageInfo getPackageInfoNoCheck(ApplicationInfo ai) {
   2337         return getPackageInfo(ai, null, false, true);
   2338     }
   2339 
   2340     private final PackageInfo getPackageInfo(ApplicationInfo aInfo,
   2341             ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
   2342         synchronized (mPackages) {
   2343             WeakReference<PackageInfo> ref;
   2344             if (includeCode) {
   2345                 ref = mPackages.get(aInfo.packageName);
   2346             } else {
   2347                 ref = mResourcePackages.get(aInfo.packageName);
   2348             }
   2349             PackageInfo packageInfo = ref != null ? ref.get() : null;
   2350             if (packageInfo == null || (packageInfo.mResources != null
   2351                     && !packageInfo.mResources.getAssets().isUpToDate())) {
   2352                 if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
   2353                         : "Loading resource-only package ") + aInfo.packageName
   2354                         + " (in " + (mBoundApplication != null
   2355                                 ? mBoundApplication.processName : null)
   2356                         + ")");
   2357                 packageInfo =
   2358                     new PackageInfo(this, aInfo, this, baseLoader,
   2359                             securityViolation, includeCode &&
   2360                             (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
   2361                 if (includeCode) {
   2362                     mPackages.put(aInfo.packageName,
   2363                             new WeakReference<PackageInfo>(packageInfo));
   2364                 } else {
   2365                     mResourcePackages.put(aInfo.packageName,
   2366                             new WeakReference<PackageInfo>(packageInfo));
   2367                 }
   2368             }
   2369             return packageInfo;
   2370         }
   2371     }
   2372 
   2373     ActivityThread() {
   2374     }
   2375 
   2376     public ApplicationThread getApplicationThread()
   2377     {
   2378         return mAppThread;
   2379     }
   2380 
   2381     public Instrumentation getInstrumentation()
   2382     {
   2383         return mInstrumentation;
   2384     }
   2385 
   2386     public Configuration getConfiguration() {
   2387         return mConfiguration;
   2388     }
   2389 
   2390     public boolean isProfiling() {
   2391         return mBoundApplication != null && mBoundApplication.profileFile != null;
   2392     }
   2393 
   2394     public String getProfileFilePath() {
   2395         return mBoundApplication.profileFile;
   2396     }
   2397 
   2398     public Looper getLooper() {
   2399         return mLooper;
   2400     }
   2401 
   2402     public Application getApplication() {
   2403         return mInitialApplication;
   2404     }
   2405 
   2406     public String getProcessName() {
   2407         return mBoundApplication.processName;
   2408     }
   2409 
   2410     public ContextImpl getSystemContext() {
   2411         synchronized (this) {
   2412             if (mSystemContext == null) {
   2413                 ContextImpl context =
   2414                     ContextImpl.createSystemContext(this);
   2415                 PackageInfo info = new PackageInfo(this, "android", context, null);
   2416                 context.init(info, null, this);
   2417                 context.getResources().updateConfiguration(
   2418                         getConfiguration(), getDisplayMetricsLocked(false));
   2419                 mSystemContext = context;
   2420                 //Slog.i(TAG, "Created system resources " + context.getResources()
   2421                 //        + ": " + context.getResources().getConfiguration());
   2422             }
   2423         }
   2424         return mSystemContext;
   2425     }
   2426 
   2427     public void installSystemApplicationInfo(ApplicationInfo info) {
   2428         synchronized (this) {
   2429             ContextImpl context = getSystemContext();
   2430             context.init(new PackageInfo(this, "android", context, info), null, this);
   2431         }
   2432     }
   2433 
   2434     void ensureJitEnabled() {
   2435         if (!mJitEnabled) {
   2436             mJitEnabled = true;
   2437             dalvik.system.VMRuntime.getRuntime().startJitCompilation();
   2438         }
   2439     }
   2440 
   2441     void scheduleGcIdler() {
   2442         if (!mGcIdlerScheduled) {
   2443             mGcIdlerScheduled = true;
   2444             Looper.myQueue().addIdleHandler(mGcIdler);
   2445         }
   2446         mH.removeMessages(H.GC_WHEN_IDLE);
   2447     }
   2448 
   2449     void unscheduleGcIdler() {
   2450         if (mGcIdlerScheduled) {
   2451             mGcIdlerScheduled = false;
   2452             Looper.myQueue().removeIdleHandler(mGcIdler);
   2453         }
   2454         mH.removeMessages(H.GC_WHEN_IDLE);
   2455     }
   2456 
   2457     void doGcIfNeeded() {
   2458         mGcIdlerScheduled = false;
   2459         final long now = SystemClock.uptimeMillis();
   2460         //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
   2461         //        + "m now=" + now);
   2462         if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
   2463             //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!");
   2464             BinderInternal.forceGc("bg");
   2465         }
   2466     }
   2467 
   2468     public final ActivityInfo resolveActivityInfo(Intent intent) {
   2469         ActivityInfo aInfo = intent.resolveActivityInfo(
   2470                 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
   2471         if (aInfo == null) {
   2472             // Throw an exception.
   2473             Instrumentation.checkStartActivityResult(
   2474                     IActivityManager.START_CLASS_NOT_FOUND, intent);
   2475         }
   2476         return aInfo;
   2477     }
   2478 
   2479     public final Activity startActivityNow(Activity parent, String id,
   2480         Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
   2481         Object lastNonConfigurationInstance) {
   2482         ActivityRecord r = new ActivityRecord();
   2483             r.token = token;
   2484             r.ident = 0;
   2485             r.intent = intent;
   2486             r.state = state;
   2487             r.parent = parent;
   2488             r.embeddedID = id;
   2489             r.activityInfo = activityInfo;
   2490             r.lastNonConfigurationInstance = lastNonConfigurationInstance;
   2491         if (localLOGV) {
   2492             ComponentName compname = intent.getComponent();
   2493             String name;
   2494             if (compname != null) {
   2495                 name = compname.toShortString();
   2496             } else {
   2497                 name = "(Intent " + intent + ").getComponent() returned null";
   2498             }
   2499             Slog.v(TAG, "Performing launch: action=" + intent.getAction()
   2500                     + ", comp=" + name
   2501                     + ", token=" + token);
   2502         }
   2503         return performLaunchActivity(r, null);
   2504     }
   2505 
   2506     public final Activity getActivity(IBinder token) {
   2507         return mActivities.get(token).activity;
   2508     }
   2509 
   2510     public final void sendActivityResult(
   2511             IBinder token, String id, int requestCode,
   2512             int resultCode, Intent data) {
   2513         if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id
   2514                 + " req=" + requestCode + " res=" + resultCode + " data=" + data);
   2515         ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
   2516         list.add(new ResultInfo(id, requestCode, resultCode, data));
   2517         mAppThread.scheduleSendResult(token, list);
   2518     }
   2519 
   2520     // if the thread hasn't started yet, we don't have the handler, so just
   2521     // save the messages until we're ready.
   2522     private final void queueOrSendMessage(int what, Object obj) {
   2523         queueOrSendMessage(what, obj, 0, 0);
   2524     }
   2525 
   2526     private final void queueOrSendMessage(int what, Object obj, int arg1) {
   2527         queueOrSendMessage(what, obj, arg1, 0);
   2528     }
   2529 
   2530     private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
   2531         synchronized (this) {
   2532             if (localLOGV) Slog.v(
   2533                 TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
   2534                 + ": " + arg1 + " / " + obj);
   2535             Message msg = Message.obtain();
   2536             msg.what = what;
   2537             msg.obj = obj;
   2538             msg.arg1 = arg1;
   2539             msg.arg2 = arg2;
   2540             mH.sendMessage(msg);
   2541         }
   2542     }
   2543 
   2544     final void scheduleContextCleanup(ContextImpl context, String who,
   2545             String what) {
   2546         ContextCleanupInfo cci = new ContextCleanupInfo();
   2547         cci.context = context;
   2548         cci.who = who;
   2549         cci.what = what;
   2550         queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
   2551     }
   2552 
   2553     private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {
   2554         // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
   2555 
   2556         ActivityInfo aInfo = r.activityInfo;
   2557         if (r.packageInfo == null) {
   2558             r.packageInfo = getPackageInfo(aInfo.applicationInfo,
   2559                     Context.CONTEXT_INCLUDE_CODE);
   2560         }
   2561 
   2562         ComponentName component = r.intent.getComponent();
   2563         if (component == null) {
   2564             component = r.intent.resolveActivity(
   2565                 mInitialApplication.getPackageManager());
   2566             r.intent.setComponent(component);
   2567         }
   2568 
   2569         if (r.activityInfo.targetActivity != null) {
   2570             component = new ComponentName(r.activityInfo.packageName,
   2571                     r.activityInfo.targetActivity);
   2572         }
   2573 
   2574         Activity activity = null;
   2575         try {
   2576             java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
   2577             activity = mInstrumentation.newActivity(
   2578                     cl, component.getClassName(), r.intent);
   2579             r.intent.setExtrasClassLoader(cl);
   2580             if (r.state != null) {
   2581                 r.state.setClassLoader(cl);
   2582             }
   2583         } catch (Exception e) {
   2584             if (!mInstrumentation.onException(activity, e)) {
   2585                 throw new RuntimeException(
   2586                     "Unable to instantiate activity " + component
   2587                     + ": " + e.toString(), e);
   2588             }
   2589         }
   2590 
   2591         try {
   2592             Application app = r.packageInfo.makeApplication(false, mInstrumentation);
   2593 
   2594             if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
   2595             if (localLOGV) Slog.v(
   2596                     TAG, r + ": app=" + app
   2597                     + ", appName=" + app.getPackageName()
   2598                     + ", pkg=" + r.packageInfo.getPackageName()
   2599                     + ", comp=" + r.intent.getComponent().toShortString()
   2600                     + ", dir=" + r.packageInfo.getAppDir());
   2601 
   2602             if (activity != null) {
   2603                 ContextImpl appContext = new ContextImpl();
   2604                 appContext.init(r.packageInfo, r.token, this);
   2605                 appContext.setOuterContext(activity);
   2606                 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
   2607                 Configuration config = new Configuration(mConfiguration);
   2608                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
   2609                         + r.activityInfo.name + " with config " + config);
   2610                 activity.attach(appContext, this, getInstrumentation(), r.token,
   2611                         r.ident, app, r.intent, r.activityInfo, title, r.parent,
   2612                         r.embeddedID, r.lastNonConfigurationInstance,
   2613                         r.lastNonConfigurationChildInstances, config);
   2614 
   2615                 if (customIntent != null) {
   2616                     activity.mIntent = customIntent;
   2617                 }
   2618                 r.lastNonConfigurationInstance = null;
   2619                 r.lastNonConfigurationChildInstances = null;
   2620                 activity.mStartedActivity = false;
   2621                 int theme = r.activityInfo.getThemeResource();
   2622                 if (theme != 0) {
   2623                     activity.setTheme(theme);
   2624                 }
   2625 
   2626                 activity.mCalled = false;
   2627                 mInstrumentation.callActivityOnCreate(activity, r.state);
   2628                 if (!activity.mCalled) {
   2629                     throw new SuperNotCalledException(
   2630                         "Activity " + r.intent.getComponent().toShortString() +
   2631                         " did not call through to super.onCreate()");
   2632                 }
   2633                 r.activity = activity;
   2634                 r.stopped = true;
   2635                 if (!r.activity.mFinished) {
   2636                     activity.performStart();
   2637                     r.stopped = false;
   2638                 }
   2639                 if (!r.activity.mFinished) {
   2640                     if (r.state != null) {
   2641                         mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
   2642                     }
   2643                 }
   2644                 if (!r.activity.mFinished) {
   2645                     activity.mCalled = false;
   2646                     mInstrumentation.callActivityOnPostCreate(activity, r.state);
   2647                     if (!activity.mCalled) {
   2648                         throw new SuperNotCalledException(
   2649                             "Activity " + r.intent.getComponent().toShortString() +
   2650                             " did not call through to super.onPostCreate()");
   2651                     }
   2652                 }
   2653             }
   2654             r.paused = true;
   2655 
   2656             mActivities.put(r.token, r);
   2657 
   2658         } catch (SuperNotCalledException e) {
   2659             throw e;
   2660 
   2661         } catch (Exception e) {
   2662             if (!mInstrumentation.onException(activity, e)) {
   2663                 throw new RuntimeException(
   2664                     "Unable to start activity " + component
   2665                     + ": " + e.toString(), e);
   2666             }
   2667         }
   2668 
   2669         return activity;
   2670     }
   2671 
   2672     private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
   2673         // If we are getting ready to gc after going to the background, well
   2674         // we are back active so skip it.
   2675         unscheduleGcIdler();
   2676 
   2677         if (localLOGV) Slog.v(
   2678             TAG, "Handling launch of " + r);
   2679         Activity a = performLaunchActivity(r, customIntent);
   2680 
   2681         if (a != null) {
   2682             r.createdConfig = new Configuration(mConfiguration);
   2683             Bundle oldState = r.state;
   2684             handleResumeActivity(r.token, false, r.isForward);
   2685 
   2686             if (!r.activity.mFinished && r.startsNotResumed) {
   2687                 // The activity manager actually wants this one to start out
   2688                 // paused, because it needs to be visible but isn't in the
   2689                 // foreground.  We accomplish this by going through the
   2690                 // normal startup (because activities expect to go through
   2691                 // onResume() the first time they run, before their window
   2692                 // is displayed), and then pausing it.  However, in this case
   2693                 // we do -not- need to do the full pause cycle (of freezing
   2694                 // and such) because the activity manager assumes it can just
   2695                 // retain the current state it has.
   2696                 try {
   2697                     r.activity.mCalled = false;
   2698                     mInstrumentation.callActivityOnPause(r.activity);
   2699                     // We need to keep around the original state, in case
   2700                     // we need to be created again.
   2701                     r.state = oldState;
   2702                     if (!r.activity.mCalled) {
   2703                         throw new SuperNotCalledException(
   2704                             "Activity " + r.intent.getComponent().toShortString() +
   2705                             " did not call through to super.onPause()");
   2706                     }
   2707 
   2708                 } catch (SuperNotCalledException e) {
   2709                     throw e;
   2710 
   2711                 } catch (Exception e) {
   2712                     if (!mInstrumentation.onException(r.activity, e)) {
   2713                         throw new RuntimeException(
   2714                                 "Unable to pause activity "
   2715                                 + r.intent.getComponent().toShortString()
   2716                                 + ": " + e.toString(), e);
   2717                     }
   2718                 }
   2719                 r.paused = true;
   2720             }
   2721         } else {
   2722             // If there was an error, for any reason, tell the activity
   2723             // manager to stop us.
   2724             try {
   2725                 ActivityManagerNative.getDefault()
   2726                     .finishActivity(r.token, Activity.RESULT_CANCELED, null);
   2727             } catch (RemoteException ex) {
   2728             }
   2729         }
   2730     }
   2731 
   2732     private final void deliverNewIntents(ActivityRecord r,
   2733             List<Intent> intents) {
   2734         final int N = intents.size();
   2735         for (int i=0; i<N; i++) {
   2736             Intent intent = intents.get(i);
   2737             intent.setExtrasClassLoader(r.activity.getClassLoader());
   2738             mInstrumentation.callActivityOnNewIntent(r.activity, intent);
   2739         }
   2740     }
   2741 
   2742     public final void performNewIntents(IBinder token,
   2743             List<Intent> intents) {
   2744         ActivityRecord r = mActivities.get(token);
   2745         if (r != null) {
   2746             final boolean resumed = !r.paused;
   2747             if (resumed) {
   2748                 mInstrumentation.callActivityOnPause(r.activity);
   2749             }
   2750             deliverNewIntents(r, intents);
   2751             if (resumed) {
   2752                 mInstrumentation.callActivityOnResume(r.activity);
   2753             }
   2754         }
   2755     }
   2756 
   2757     private final void handleNewIntent(NewIntentData data) {
   2758         performNewIntents(data.token, data.intents);
   2759     }
   2760 
   2761     private final void handleReceiver(ReceiverData data) {
   2762         // If we are getting ready to gc after going to the background, well
   2763         // we are back active so skip it.
   2764         unscheduleGcIdler();
   2765 
   2766         String component = data.intent.getComponent().getClassName();
   2767 
   2768         PackageInfo packageInfo = getPackageInfoNoCheck(
   2769                 data.info.applicationInfo);
   2770 
   2771         IActivityManager mgr = ActivityManagerNative.getDefault();
   2772 
   2773         BroadcastReceiver receiver = null;
   2774         try {
   2775             java.lang.ClassLoader cl = packageInfo.getClassLoader();
   2776             data.intent.setExtrasClassLoader(cl);
   2777             if (data.resultExtras != null) {
   2778                 data.resultExtras.setClassLoader(cl);
   2779             }
   2780             receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
   2781         } catch (Exception e) {
   2782             try {
   2783                 if (DEBUG_BROADCAST) Slog.i(TAG,
   2784                         "Finishing failed broadcast to " + data.intent.getComponent());
   2785                 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
   2786                                    data.resultData, data.resultExtras, data.resultAbort);
   2787             } catch (RemoteException ex) {
   2788             }
   2789             throw new RuntimeException(
   2790                 "Unable to instantiate receiver " + component
   2791                 + ": " + e.toString(), e);
   2792         }
   2793 
   2794         try {
   2795             Application app = packageInfo.makeApplication(false, mInstrumentation);
   2796 
   2797             if (localLOGV) Slog.v(
   2798                 TAG, "Performing receive of " + data.intent
   2799                 + ": app=" + app
   2800                 + ", appName=" + app.getPackageName()
   2801                 + ", pkg=" + packageInfo.getPackageName()
   2802                 + ", comp=" + data.intent.getComponent().toShortString()
   2803                 + ", dir=" + packageInfo.getAppDir());
   2804 
   2805             ContextImpl context = (ContextImpl)app.getBaseContext();
   2806             receiver.setOrderedHint(true);
   2807             receiver.setResult(data.resultCode, data.resultData,
   2808                 data.resultExtras);
   2809             receiver.setOrderedHint(data.sync);
   2810             receiver.onReceive(context.getReceiverRestrictedContext(),
   2811                     data.intent);
   2812         } catch (Exception e) {
   2813             try {
   2814                 if (DEBUG_BROADCAST) Slog.i(TAG,
   2815                         "Finishing failed broadcast to " + data.intent.getComponent());
   2816                 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
   2817                     data.resultData, data.resultExtras, data.resultAbort);
   2818             } catch (RemoteException ex) {
   2819             }
   2820             if (!mInstrumentation.onException(receiver, e)) {
   2821                 throw new RuntimeException(
   2822                     "Unable to start receiver " + component
   2823                     + ": " + e.toString(), e);
   2824             }
   2825         }
   2826 
   2827         try {
   2828             if (data.sync) {
   2829                 if (DEBUG_BROADCAST) Slog.i(TAG,
   2830                         "Finishing ordered broadcast to " + data.intent.getComponent());
   2831                 mgr.finishReceiver(
   2832                     mAppThread.asBinder(), receiver.getResultCode(),
   2833                     receiver.getResultData(), receiver.getResultExtras(false),
   2834                         receiver.getAbortBroadcast());
   2835             } else {
   2836                 if (DEBUG_BROADCAST) Slog.i(TAG,
   2837                         "Finishing broadcast to " + data.intent.getComponent());
   2838                 mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false);
   2839             }
   2840         } catch (RemoteException ex) {
   2841         }
   2842     }
   2843 
   2844     // Instantiate a BackupAgent and tell it that it's alive
   2845     private final void handleCreateBackupAgent(CreateBackupAgentData data) {
   2846         if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
   2847 
   2848         // no longer idle; we have backup work to do
   2849         unscheduleGcIdler();
   2850 
   2851         // instantiate the BackupAgent class named in the manifest
   2852         PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
   2853         String packageName = packageInfo.mPackageName;
   2854         if (mBackupAgents.get(packageName) != null) {
   2855             Slog.d(TAG, "BackupAgent " + "  for " + packageName
   2856                     + " already exists");
   2857             return;
   2858         }
   2859 
   2860         BackupAgent agent = null;
   2861         String classname = data.appInfo.backupAgentName;
   2862         if (classname == null) {
   2863             if (data.backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL) {
   2864                 Slog.e(TAG, "Attempted incremental backup but no defined agent for "
   2865                         + packageName);
   2866                 return;
   2867             }
   2868             classname = "android.app.FullBackupAgent";
   2869         }
   2870         try {
   2871             IBinder binder = null;
   2872             try {
   2873                 java.lang.ClassLoader cl = packageInfo.getClassLoader();
   2874                 agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance();
   2875 
   2876                 // set up the agent's context
   2877                 if (DEBUG_BACKUP) Slog.v(TAG, "Initializing BackupAgent "
   2878                         + data.appInfo.backupAgentName);
   2879 
   2880                 ContextImpl context = new ContextImpl();
   2881                 context.init(packageInfo, null, this);
   2882                 context.setOuterContext(agent);
   2883                 agent.attach(context);
   2884 
   2885                 agent.onCreate();
   2886                 binder = agent.onBind();
   2887                 mBackupAgents.put(packageName, agent);
   2888             } catch (Exception e) {
   2889                 // If this is during restore, fail silently; otherwise go
   2890                 // ahead and let the user see the crash.
   2891                 Slog.e(TAG, "Agent threw during creation: " + e);
   2892                 if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE) {
   2893                     throw e;
   2894                 }
   2895                 // falling through with 'binder' still null
   2896             }
   2897 
   2898             // tell the OS that we're live now
   2899             try {
   2900                 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
   2901             } catch (RemoteException e) {
   2902                 // nothing to do.
   2903             }
   2904         } catch (Exception e) {
   2905             throw new RuntimeException("Unable to create BackupAgent "
   2906                     + data.appInfo.backupAgentName + ": " + e.toString(), e);
   2907         }
   2908     }
   2909 
   2910     // Tear down a BackupAgent
   2911     private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
   2912         if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
   2913 
   2914         PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
   2915         String packageName = packageInfo.mPackageName;
   2916         BackupAgent agent = mBackupAgents.get(packageName);
   2917         if (agent != null) {
   2918             try {
   2919                 agent.onDestroy();
   2920             } catch (Exception e) {
   2921                 Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
   2922                 e.printStackTrace();
   2923             }
   2924             mBackupAgents.remove(packageName);
   2925         } else {
   2926             Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
   2927         }
   2928     }
   2929 
   2930     private final void handleCreateService(CreateServiceData data) {
   2931         // If we are getting ready to gc after going to the background, well
   2932         // we are back active so skip it.
   2933         unscheduleGcIdler();
   2934 
   2935         PackageInfo packageInfo = getPackageInfoNoCheck(
   2936                 data.info.applicationInfo);
   2937         Service service = null;
   2938         try {
   2939             java.lang.ClassLoader cl = packageInfo.getClassLoader();
   2940             service = (Service) cl.loadClass(data.info.name).newInstance();
   2941         } catch (Exception e) {
   2942             if (!mInstrumentation.onException(service, e)) {
   2943                 throw new RuntimeException(
   2944                     "Unable to instantiate service " + data.info.name
   2945                     + ": " + e.toString(), e);
   2946             }
   2947         }
   2948 
   2949         try {
   2950             if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
   2951 
   2952             ContextImpl context = new ContextImpl();
   2953             context.init(packageInfo, null, this);
   2954 
   2955             Application app = packageInfo.makeApplication(false, mInstrumentation);
   2956             context.setOuterContext(service);
   2957             service.attach(context, this, data.info.name, data.token, app,
   2958                     ActivityManagerNative.getDefault());
   2959             service.onCreate();
   2960             mServices.put(data.token, service);
   2961             try {
   2962                 ActivityManagerNative.getDefault().serviceDoneExecuting(
   2963                         data.token, 0, 0, 0);
   2964             } catch (RemoteException e) {
   2965                 // nothing to do.
   2966             }
   2967         } catch (Exception e) {
   2968             if (!mInstrumentation.onException(service, e)) {
   2969                 throw new RuntimeException(
   2970                     "Unable to create service " + data.info.name
   2971                     + ": " + e.toString(), e);
   2972             }
   2973         }
   2974     }
   2975 
   2976     private final void handleBindService(BindServiceData data) {
   2977         Service s = mServices.get(data.token);
   2978         if (s != null) {
   2979             try {
   2980                 data.intent.setExtrasClassLoader(s.getClassLoader());
   2981                 try {
   2982                     if (!data.rebind) {
   2983                         IBinder binder = s.onBind(data.intent);
   2984                         ActivityManagerNative.getDefault().publishService(
   2985                                 data.token, data.intent, binder);
   2986                     } else {
   2987                         s.onRebind(data.intent);
   2988                         ActivityManagerNative.getDefault().serviceDoneExecuting(
   2989                                 data.token, 0, 0, 0);
   2990                     }
   2991                     ensureJitEnabled();
   2992                 } catch (RemoteException ex) {
   2993                 }
   2994             } catch (Exception e) {
   2995                 if (!mInstrumentation.onException(s, e)) {
   2996                     throw new RuntimeException(
   2997                             "Unable to bind to service " + s
   2998                             + " with " + data.intent + ": " + e.toString(), e);
   2999                 }
   3000             }
   3001         }
   3002     }
   3003 
   3004     private final void handleUnbindService(BindServiceData data) {
   3005         Service s = mServices.get(data.token);
   3006         if (s != null) {
   3007             try {
   3008                 data.intent.setExtrasClassLoader(s.getClassLoader());
   3009                 boolean doRebind = s.onUnbind(data.intent);
   3010                 try {
   3011                     if (doRebind) {
   3012                         ActivityManagerNative.getDefault().unbindFinished(
   3013                                 data.token, data.intent, doRebind);
   3014                     } else {
   3015                         ActivityManagerNative.getDefault().serviceDoneExecuting(
   3016                                 data.token, 0, 0, 0);
   3017                     }
   3018                 } catch (RemoteException ex) {
   3019                 }
   3020             } catch (Exception e) {
   3021                 if (!mInstrumentation.onException(s, e)) {
   3022                     throw new RuntimeException(
   3023                             "Unable to unbind to service " + s
   3024                             + " with " + data.intent + ": " + e.toString(), e);
   3025                 }
   3026             }
   3027         }
   3028     }
   3029 
   3030     private void handleDumpService(DumpServiceInfo info) {
   3031         try {
   3032             Service s = mServices.get(info.service);
   3033             if (s != null) {
   3034                 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
   3035                 s.dump(info.fd, pw, info.args);
   3036                 pw.close();
   3037             }
   3038         } finally {
   3039             synchronized (info) {
   3040                 info.dumped = true;
   3041                 info.notifyAll();
   3042             }
   3043         }
   3044     }
   3045 
   3046     private final void handleServiceArgs(ServiceArgsData data) {
   3047         Service s = mServices.get(data.token);
   3048         if (s != null) {
   3049             try {
   3050                 if (data.args != null) {
   3051                     data.args.setExtrasClassLoader(s.getClassLoader());
   3052                 }
   3053                 int res = s.onStartCommand(data.args, data.flags, data.startId);
   3054                 try {
   3055                     ActivityManagerNative.getDefault().serviceDoneExecuting(
   3056                             data.token, 1, data.startId, res);
   3057                 } catch (RemoteException e) {
   3058                     // nothing to do.
   3059                 }
   3060                 ensureJitEnabled();
   3061             } catch (Exception e) {
   3062                 if (!mInstrumentation.onException(s, e)) {
   3063                     throw new RuntimeException(
   3064                             "Unable to start service " + s
   3065                             + " with " + data.args + ": " + e.toString(), e);
   3066                 }
   3067             }
   3068         }
   3069     }
   3070 
   3071     private final void handleStopService(IBinder token) {
   3072         Service s = mServices.remove(token);
   3073         if (s != null) {
   3074             try {
   3075                 if (localLOGV) Slog.v(TAG, "Destroying service " + s);
   3076                 s.onDestroy();
   3077                 Context context = s.getBaseContext();
   3078                 if (context instanceof ContextImpl) {
   3079                     final String who = s.getClassName();
   3080                     ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
   3081                 }
   3082                 try {
   3083                     ActivityManagerNative.getDefault().serviceDoneExecuting(
   3084                             token, 0, 0, 0);
   3085                 } catch (RemoteException e) {
   3086                     // nothing to do.
   3087                 }
   3088             } catch (Exception e) {
   3089                 if (!mInstrumentation.onException(s, e)) {
   3090                     throw new RuntimeException(
   3091                             "Unable to stop service " + s
   3092                             + ": " + e.toString(), e);
   3093                 }
   3094             }
   3095         }
   3096         //Slog.i(TAG, "Running services: " + mServices);
   3097     }
   3098 
   3099     public final ActivityRecord performResumeActivity(IBinder token,
   3100             boolean clearHide) {
   3101         ActivityRecord r = mActivities.get(token);
   3102         if (localLOGV) Slog.v(TAG, "Performing resume of " + r
   3103                 + " finished=" + r.activity.mFinished);
   3104         if (r != null && !r.activity.mFinished) {
   3105             if (clearHide) {
   3106                 r.hideForNow = false;
   3107                 r.activity.mStartedActivity = false;
   3108             }
   3109             try {
   3110                 if (r.pendingIntents != null) {
   3111                     deliverNewIntents(r, r.pendingIntents);
   3112                     r.pendingIntents = null;
   3113                 }
   3114                 if (r.pendingResults != null) {
   3115                     deliverResults(r, r.pendingResults);
   3116                     r.pendingResults = null;
   3117                 }
   3118                 r.activity.performResume();
   3119 
   3120                 EventLog.writeEvent(LOG_ON_RESUME_CALLED,
   3121                         r.activity.getComponentName().getClassName());
   3122 
   3123                 r.paused = false;
   3124                 r.stopped = false;
   3125                 r.state = null;
   3126             } catch (Exception e) {
   3127                 if (!mInstrumentation.onException(r.activity, e)) {
   3128                     throw new RuntimeException(
   3129                         "Unable to resume activity "
   3130                         + r.intent.getComponent().toShortString()
   3131                         + ": " + e.toString(), e);
   3132                 }
   3133             }
   3134         }
   3135         return r;
   3136     }
   3137 
   3138     final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
   3139         // If we are getting ready to gc after going to the background, well
   3140         // we are back active so skip it.
   3141         unscheduleGcIdler();
   3142 
   3143         ActivityRecord r = performResumeActivity(token, clearHide);
   3144 
   3145         if (r != null) {
   3146             final Activity a = r.activity;
   3147 
   3148             if (localLOGV) Slog.v(
   3149                 TAG, "Resume " + r + " started activity: " +
   3150                 a.mStartedActivity + ", hideForNow: " + r.hideForNow
   3151                 + ", finished: " + a.mFinished);
   3152 
   3153             final int forwardBit = isForward ?
   3154                     WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
   3155 
   3156             // If the window hasn't yet been added to the window manager,
   3157             // and this guy didn't finish itself or start another activity,
   3158             // then go ahead and add the window.
   3159             boolean willBeVisible = !a.mStartedActivity;
   3160             if (!willBeVisible) {
   3161                 try {
   3162                     willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
   3163                             a.getActivityToken());
   3164                 } catch (RemoteException e) {
   3165                 }
   3166             }
   3167             if (r.window == null && !a.mFinished && willBeVisible) {
   3168                 r.window = r.activity.getWindow();
   3169                 View decor = r.window.getDecorView();
   3170                 decor.setVisibility(View.INVISIBLE);
   3171                 ViewManager wm = a.getWindowManager();
   3172                 WindowManager.LayoutParams l = r.window.getAttributes();
   3173                 a.mDecor = decor;
   3174                 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
   3175                 l.softInputMode |= forwardBit;
   3176                 if (a.mVisibleFromClient) {
   3177                     a.mWindowAdded = true;
   3178                     wm.addView(decor, l);
   3179                 }
   3180 
   3181             // If the window has already been added, but during resume
   3182             // we started another activity, then don't yet make the
   3183             // window visible.
   3184             } else if (!willBeVisible) {
   3185                 if (localLOGV) Slog.v(
   3186                     TAG, "Launch " + r + " mStartedActivity set");
   3187                 r.hideForNow = true;
   3188             }
   3189 
   3190             // The window is now visible if it has been added, we are not
   3191             // simply finishing, and we are not starting another activity.
   3192             if (!r.activity.mFinished && willBeVisible
   3193                     && r.activity.mDecor != null && !r.hideForNow) {
   3194                 if (r.newConfig != null) {
   3195                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
   3196                             + r.activityInfo.name + " with newConfig " + r.newConfig);
   3197                     performConfigurationChanged(r.activity, r.newConfig);
   3198                     r.newConfig = null;
   3199                 }
   3200                 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
   3201                         + isForward);
   3202                 WindowManager.LayoutParams l = r.window.getAttributes();
   3203                 if ((l.softInputMode
   3204                         & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
   3205                         != forwardBit) {
   3206                     l.softInputMode = (l.softInputMode
   3207                             & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
   3208                             | forwardBit;
   3209                     if (r.activity.mVisibleFromClient) {
   3210                         ViewManager wm = a.getWindowManager();
   3211                         View decor = r.window.getDecorView();
   3212                         wm.updateViewLayout(decor, l);
   3213                     }
   3214                 }
   3215                 r.activity.mVisibleFromServer = true;
   3216                 mNumVisibleActivities++;
   3217                 if (r.activity.mVisibleFromClient) {
   3218                     r.activity.makeVisible();
   3219                 }
   3220             }
   3221 
   3222             r.nextIdle = mNewActivities;
   3223             mNewActivities = r;
   3224             if (localLOGV) Slog.v(
   3225                 TAG, "Scheduling idle handler for " + r);
   3226             Looper.myQueue().addIdleHandler(new Idler());
   3227 
   3228         } else {
   3229             // If an exception was thrown when trying to resume, then
   3230             // just end this activity.
   3231             try {
   3232                 ActivityManagerNative.getDefault()
   3233                     .finishActivity(token, Activity.RESULT_CANCELED, null);
   3234             } catch (RemoteException ex) {
   3235             }
   3236         }
   3237     }
   3238 
   3239     private int mThumbnailWidth = -1;
   3240     private int mThumbnailHeight = -1;
   3241 
   3242     private final Bitmap createThumbnailBitmap(ActivityRecord r) {
   3243         Bitmap thumbnail = null;
   3244         try {
   3245             int w = mThumbnailWidth;
   3246             int h;
   3247             if (w < 0) {
   3248                 Resources res = r.activity.getResources();
   3249                 mThumbnailHeight = h =
   3250                     res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
   3251 
   3252                 mThumbnailWidth = w =
   3253                     res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
   3254             } else {
   3255                 h = mThumbnailHeight;
   3256             }
   3257 
   3258             // XXX Only set hasAlpha if needed?
   3259             thumbnail = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
   3260             thumbnail.eraseColor(0);
   3261             Canvas cv = new Canvas(thumbnail);
   3262             if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
   3263                 thumbnail = null;
   3264             }
   3265         } catch (Exception e) {
   3266             if (!mInstrumentation.onException(r.activity, e)) {
   3267                 throw new RuntimeException(
   3268                         "Unable to create thumbnail of "
   3269                         + r.intent.getComponent().toShortString()
   3270                         + ": " + e.toString(), e);
   3271             }
   3272             thumbnail = null;
   3273         }
   3274 
   3275         return thumbnail;
   3276     }
   3277 
   3278     private final void handlePauseActivity(IBinder token, boolean finished,
   3279             boolean userLeaving, int configChanges) {
   3280         ActivityRecord r = mActivities.get(token);
   3281         if (r != null) {
   3282             //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
   3283             if (userLeaving) {
   3284                 performUserLeavingActivity(r);
   3285             }
   3286 
   3287             r.activity.mConfigChangeFlags |= configChanges;
   3288             Bundle state = performPauseActivity(token, finished, true);
   3289 
   3290             // Tell the activity manager we have paused.
   3291             try {
   3292                 ActivityManagerNative.getDefault().activityPaused(token, state);
   3293             } catch (RemoteException ex) {
   3294             }
   3295         }
   3296     }
   3297 
   3298     final void performUserLeavingActivity(ActivityRecord r) {
   3299         mInstrumentation.callActivityOnUserLeaving(r.activity);
   3300     }
   3301 
   3302     final Bundle performPauseActivity(IBinder token, boolean finished,
   3303             boolean saveState) {
   3304         ActivityRecord r = mActivities.get(token);
   3305         return r != null ? performPauseActivity(r, finished, saveState) : null;
   3306     }
   3307 
   3308     final Bundle performPauseActivity(ActivityRecord r, boolean finished,
   3309             boolean saveState) {
   3310         if (r.paused) {
   3311             if (r.activity.mFinished) {
   3312                 // If we are finishing, we won't call onResume() in certain cases.
   3313                 // So here we likewise don't want to call onPause() if the activity
   3314                 // isn't resumed.
   3315                 return null;
   3316             }
   3317             RuntimeException e = new RuntimeException(
   3318                     "Performing pause of activity that is not resumed: "
   3319                     + r.intent.getComponent().toShortString());
   3320             Slog.e(TAG, e.getMessage(), e);
   3321         }
   3322         Bundle state = null;
   3323         if (finished) {
   3324             r.activity.mFinished = true;
   3325         }
   3326         try {
   3327             // Next have the activity save its current state and managed dialogs...
   3328             if (!r.activity.mFinished && saveState) {
   3329                 state = new Bundle();
   3330                 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
   3331                 r.state = state;
   3332             }
   3333             // Now we are idle.
   3334             r.activity.mCalled = false;
   3335             mInstrumentation.callActivityOnPause(r.activity);
   3336             EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
   3337             if (!r.activity.mCalled) {
   3338                 throw new SuperNotCalledException(
   3339                     "Activity " + r.intent.getComponent().toShortString() +
   3340                     " did not call through to super.onPause()");
   3341             }
   3342 
   3343         } catch (SuperNotCalledException e) {
   3344             throw e;
   3345 
   3346         } catch (Exception e) {
   3347             if (!mInstrumentation.onException(r.activity, e)) {
   3348                 throw new RuntimeException(
   3349                         "Unable to pause activity "
   3350                         + r.intent.getComponent().toShortString()
   3351                         + ": " + e.toString(), e);
   3352             }
   3353         }
   3354         r.paused = true;
   3355         return state;
   3356     }
   3357 
   3358     final void performStopActivity(IBinder token) {
   3359         ActivityRecord r = mActivities.get(token);
   3360         performStopActivityInner(r, null, false);
   3361     }
   3362 
   3363     private static class StopInfo {
   3364         Bitmap thumbnail;
   3365         CharSequence description;
   3366     }
   3367 
   3368     private final class ProviderRefCount {
   3369         public int count;
   3370         ProviderRefCount(int pCount) {
   3371             count = pCount;
   3372         }
   3373     }
   3374 
   3375     private final void performStopActivityInner(ActivityRecord r,
   3376             StopInfo info, boolean keepShown) {
   3377         if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
   3378         if (r != null) {
   3379             if (!keepShown && r.stopped) {
   3380                 if (r.activity.mFinished) {
   3381                     // If we are finishing, we won't call onResume() in certain
   3382                     // cases.  So here we likewise don't want to call onStop()
   3383                     // if the activity isn't resumed.
   3384                     return;
   3385                 }
   3386                 RuntimeException e = new RuntimeException(
   3387                         "Performing stop of activity that is not resumed: "
   3388                         + r.intent.getComponent().toShortString());
   3389                 Slog.e(TAG, e.getMessage(), e);
   3390             }
   3391 
   3392             if (info != null) {
   3393                 try {
   3394                     // First create a thumbnail for the activity...
   3395                     //info.thumbnail = createThumbnailBitmap(r);
   3396                     info.description = r.activity.onCreateDescription();
   3397                 } catch (Exception e) {
   3398                     if (!mInstrumentation.onException(r.activity, e)) {
   3399                         throw new RuntimeException(
   3400                                 "Unable to save state of activity "
   3401                                 + r.intent.getComponent().toShortString()
   3402                                 + ": " + e.toString(), e);
   3403                     }
   3404                 }
   3405             }
   3406 
   3407             if (!keepShown) {
   3408                 try {
   3409                     // Now we are idle.
   3410                     r.activity.performStop();
   3411                 } catch (Exception e) {
   3412                     if (!mInstrumentation.onException(r.activity, e)) {
   3413                         throw new RuntimeException(
   3414                                 "Unable to stop activity "
   3415                                 + r.intent.getComponent().toShortString()
   3416                                 + ": " + e.toString(), e);
   3417                     }
   3418                 }
   3419                 r.stopped = true;
   3420             }
   3421 
   3422             r.paused = true;
   3423         }
   3424     }
   3425 
   3426     private final void updateVisibility(ActivityRecord r, boolean show) {
   3427         View v = r.activity.mDecor;
   3428         if (v != null) {
   3429             if (show) {
   3430                 if (!r.activity.mVisibleFromServer) {
   3431                     r.activity.mVisibleFromServer = true;
   3432                     mNumVisibleActivities++;
   3433                     if (r.activity.mVisibleFromClient) {
   3434                         r.activity.makeVisible();
   3435                     }
   3436                 }
   3437                 if (r.newConfig != null) {
   3438                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
   3439                             + r.activityInfo.name + " with new config " + r.newConfig);
   3440                     performConfigurationChanged(r.activity, r.newConfig);
   3441                     r.newConfig = null;
   3442                 }
   3443             } else {
   3444                 if (r.activity.mVisibleFromServer) {
   3445                     r.activity.mVisibleFromServer = false;
   3446                     mNumVisibleActivities--;
   3447                     v.setVisibility(View.INVISIBLE);
   3448                 }
   3449             }
   3450         }
   3451     }
   3452 
   3453     private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
   3454         ActivityRecord r = mActivities.get(token);
   3455         r.activity.mConfigChangeFlags |= configChanges;
   3456 
   3457         StopInfo info = new StopInfo();
   3458         performStopActivityInner(r, info, show);
   3459 
   3460         if (localLOGV) Slog.v(
   3461             TAG, "Finishing stop of " + r + ": show=" + show
   3462             + " win=" + r.window);
   3463 
   3464         updateVisibility(r, show);
   3465 
   3466         // Tell activity manager we have been stopped.
   3467         try {
   3468             ActivityManagerNative.getDefault().activityStopped(
   3469                 r.token, info.thumbnail, info.description);
   3470         } catch (RemoteException ex) {
   3471         }
   3472     }
   3473 
   3474     final void performRestartActivity(IBinder token) {
   3475         ActivityRecord r = mActivities.get(token);
   3476         if (r.stopped) {
   3477             r.activity.performRestart();
   3478             r.stopped = false;
   3479         }
   3480     }
   3481 
   3482     private final void handleWindowVisibility(IBinder token, boolean show) {
   3483         ActivityRecord r = mActivities.get(token);
   3484         if (!show && !r.stopped) {
   3485             performStopActivityInner(r, null, show);
   3486         } else if (show && r.stopped) {
   3487             // If we are getting ready to gc after going to the background, well
   3488             // we are back active so skip it.
   3489             unscheduleGcIdler();
   3490 
   3491             r.activity.performRestart();
   3492             r.stopped = false;
   3493         }
   3494         if (r.activity.mDecor != null) {
   3495             if (Config.LOGV) Slog.v(
   3496                 TAG, "Handle window " + r + " visibility: " + show);
   3497             updateVisibility(r, show);
   3498         }
   3499     }
   3500 
   3501     private final void deliverResults(ActivityRecord r, List<ResultInfo> results) {
   3502         final int N = results.size();
   3503         for (int i=0; i<N; i++) {
   3504             ResultInfo ri = results.get(i);
   3505             try {
   3506                 if (ri.mData != null) {
   3507                     ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
   3508                 }
   3509                 if (DEBUG_RESULTS) Slog.v(TAG,
   3510                         "Delivering result to activity " + r + " : " + ri);
   3511                 r.activity.dispatchActivityResult(ri.mResultWho,
   3512                         ri.mRequestCode, ri.mResultCode, ri.mData);
   3513             } catch (Exception e) {
   3514                 if (!mInstrumentation.onException(r.activity, e)) {
   3515                     throw new RuntimeException(
   3516                             "Failure delivering result " + ri + " to activity "
   3517                             + r.intent.getComponent().toShortString()
   3518                             + ": " + e.toString(), e);
   3519                 }
   3520             }
   3521         }
   3522     }
   3523 
   3524     private final void handleSendResult(ResultData res) {
   3525         ActivityRecord r = mActivities.get(res.token);
   3526         if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
   3527         if (r != null) {
   3528             final boolean resumed = !r.paused;
   3529             if (!r.activity.mFinished && r.activity.mDecor != null
   3530                     && r.hideForNow && resumed) {
   3531                 // We had hidden the activity because it started another
   3532                 // one...  we have gotten a result back and we are not
   3533                 // paused, so make sure our window is visible.
   3534                 updateVisibility(r, true);
   3535             }
   3536             if (resumed) {
   3537                 try {
   3538                     // Now we are idle.
   3539                     r.activity.mCalled = false;
   3540                     mInstrumentation.callActivityOnPause(r.activity);
   3541                     if (!r.activity.mCalled) {
   3542                         throw new SuperNotCalledException(
   3543                             "Activity " + r.intent.getComponent().toShortString()
   3544                             + " did not call through to super.onPause()");
   3545                     }
   3546                 } catch (SuperNotCalledException e) {
   3547                     throw e;
   3548                 } catch (Exception e) {
   3549                     if (!mInstrumentation.onException(r.activity, e)) {
   3550                         throw new RuntimeException(
   3551                                 "Unable to pause activity "
   3552                                 + r.intent.getComponent().toShortString()
   3553                                 + ": " + e.toString(), e);
   3554                     }
   3555                 }
   3556             }
   3557             deliverResults(r, res.results);
   3558             if (resumed) {
   3559                 mInstrumentation.callActivityOnResume(r.activity);
   3560             }
   3561         }
   3562     }
   3563 
   3564     public final ActivityRecord performDestroyActivity(IBinder token, boolean finishing) {
   3565         return performDestroyActivity(token, finishing, 0, false);
   3566     }
   3567 
   3568     private final ActivityRecord performDestroyActivity(IBinder token, boolean finishing,
   3569             int configChanges, boolean getNonConfigInstance) {
   3570         ActivityRecord r = mActivities.get(token);
   3571         if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
   3572         if (r != null) {
   3573             r.activity.mConfigChangeFlags |= configChanges;
   3574             if (finishing) {
   3575                 r.activity.mFinished = true;
   3576             }
   3577             if (!r.paused) {
   3578                 try {
   3579                     r.activity.mCalled = false;
   3580                     mInstrumentation.callActivityOnPause(r.activity);
   3581                     EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
   3582                             r.activity.getComponentName().getClassName());
   3583                     if (!r.activity.mCalled) {
   3584                         throw new SuperNotCalledException(
   3585                             "Activity " + safeToComponentShortString(r.intent)
   3586                             + " did not call through to super.onPause()");
   3587                     }
   3588                 } catch (SuperNotCalledException e) {
   3589                     throw e;
   3590                 } catch (Exception e) {
   3591                     if (!mInstrumentation.onException(r.activity, e)) {
   3592                         throw new RuntimeException(
   3593                                 "Unable to pause activity "
   3594                                 + safeToComponentShortString(r.intent)
   3595                                 + ": " + e.toString(), e);
   3596                     }
   3597                 }
   3598                 r.paused = true;
   3599             }
   3600             if (!r.stopped) {
   3601                 try {
   3602                     r.activity.performStop();
   3603                 } catch (SuperNotCalledException e) {
   3604                     throw e;
   3605                 } catch (Exception e) {
   3606                     if (!mInstrumentation.onException(r.activity, e)) {
   3607                         throw new RuntimeException(
   3608                                 "Unable to stop activity "
   3609                                 + safeToComponentShortString(r.intent)
   3610                                 + ": " + e.toString(), e);
   3611                     }
   3612                 }
   3613                 r.stopped = true;
   3614             }
   3615             if (getNonConfigInstance) {
   3616                 try {
   3617                     r.lastNonConfigurationInstance
   3618                             = r.activity.onRetainNonConfigurationInstance();
   3619                 } catch (Exception e) {
   3620                     if (!mInstrumentation.onException(r.activity, e)) {
   3621                         throw new RuntimeException(
   3622                                 "Unable to retain activity "
   3623                                 + r.intent.getComponent().toShortString()
   3624                                 + ": " + e.toString(), e);
   3625                     }
   3626                 }
   3627                 try {
   3628                     r.lastNonConfigurationChildInstances
   3629                             = r.activity.onRetainNonConfigurationChildInstances();
   3630                 } catch (Exception e) {
   3631                     if (!mInstrumentation.onException(r.activity, e)) {
   3632                         throw new RuntimeException(
   3633                                 "Unable to retain child activities "
   3634                                 + safeToComponentShortString(r.intent)
   3635                                 + ": " + e.toString(), e);
   3636                     }
   3637                 }
   3638 
   3639             }
   3640             try {
   3641                 r.activity.mCalled = false;
   3642                 r.activity.onDestroy();
   3643                 if (!r.activity.mCalled) {
   3644                     throw new SuperNotCalledException(
   3645                         "Activity " + safeToComponentShortString(r.intent) +
   3646                         " did not call through to super.onDestroy()");
   3647                 }
   3648                 if (r.window != null) {
   3649                     r.window.closeAllPanels();
   3650                 }
   3651             } catch (SuperNotCalledException e) {
   3652                 throw e;
   3653             } catch (Exception e) {
   3654                 if (!mInstrumentation.onException(r.activity, e)) {
   3655                     throw new RuntimeException(
   3656                             "Unable to destroy activity " + safeToComponentShortString(r.intent)
   3657                             + ": " + e.toString(), e);
   3658                 }
   3659             }
   3660         }
   3661         mActivities.remove(token);
   3662 
   3663         return r;
   3664     }
   3665 
   3666     private static String safeToComponentShortString(Intent intent) {
   3667         ComponentName component = intent.getComponent();
   3668         return component == null ? "[Unknown]" : component.toShortString();
   3669     }
   3670 
   3671     private final void handleDestroyActivity(IBinder token, boolean finishing,
   3672             int configChanges, boolean getNonConfigInstance) {
   3673         ActivityRecord r = performDestroyActivity(token, finishing,
   3674                 configChanges, getNonConfigInstance);
   3675         if (r != null) {
   3676             WindowManager wm = r.activity.getWindowManager();
   3677             View v = r.activity.mDecor;
   3678             if (v != null) {
   3679                 if (r.activity.mVisibleFromServer) {
   3680                     mNumVisibleActivities--;
   3681                 }
   3682                 IBinder wtoken = v.getWindowToken();
   3683                 if (r.activity.mWindowAdded) {
   3684                     wm.removeViewImmediate(v);
   3685                 }
   3686                 if (wtoken != null) {
   3687                     WindowManagerImpl.getDefault().closeAll(wtoken,
   3688                             r.activity.getClass().getName(), "Activity");
   3689                 }
   3690                 r.activity.mDecor = null;
   3691             }
   3692             WindowManagerImpl.getDefault().closeAll(token,
   3693                     r.activity.getClass().getName(), "Activity");
   3694 
   3695             // Mocked out contexts won't be participating in the normal
   3696             // process lifecycle, but if we're running with a proper
   3697             // ApplicationContext we need to have it tear down things
   3698             // cleanly.
   3699             Context c = r.activity.getBaseContext();
   3700             if (c instanceof ContextImpl) {
   3701                 ((ContextImpl) c).scheduleFinalCleanup(
   3702                         r.activity.getClass().getName(), "Activity");
   3703             }
   3704         }
   3705         if (finishing) {
   3706             try {
   3707                 ActivityManagerNative.getDefault().activityDestroyed(token);
   3708             } catch (RemoteException ex) {
   3709                 // If the system process has died, it's game over for everyone.
   3710             }
   3711         }
   3712     }
   3713 
   3714     private final void handleRelaunchActivity(ActivityRecord tmp, int configChanges) {
   3715         // If we are getting ready to gc after going to the background, well
   3716         // we are back active so skip it.
   3717         unscheduleGcIdler();
   3718 
   3719         Configuration changedConfig = null;
   3720 
   3721         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
   3722                 + tmp.token + " with configChanges=0x"
   3723                 + Integer.toHexString(configChanges));
   3724 
   3725         // First: make sure we have the most recent configuration and most
   3726         // recent version of the activity, or skip it if some previous call
   3727         // had taken a more recent version.
   3728         synchronized (mPackages) {
   3729             int N = mRelaunchingActivities.size();
   3730             IBinder token = tmp.token;
   3731             tmp = null;
   3732             for (int i=0; i<N; i++) {
   3733                 ActivityRecord r = mRelaunchingActivities.get(i);
   3734                 if (r.token == token) {
   3735                     tmp = r;
   3736                     mRelaunchingActivities.remove(i);
   3737                     i--;
   3738                     N--;
   3739                 }
   3740             }
   3741 
   3742             if (tmp == null) {
   3743                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
   3744                 return;
   3745             }
   3746 
   3747             if (mPendingConfiguration != null) {
   3748                 changedConfig = mPendingConfiguration;
   3749                 mPendingConfiguration = null;
   3750             }
   3751         }
   3752 
   3753         if (tmp.createdConfig != null) {
   3754             // If the activity manager is passing us its current config,
   3755             // assume that is really what we want regardless of what we
   3756             // may have pending.
   3757             if (mConfiguration == null
   3758                     || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
   3759                             && mConfiguration.diff(tmp.createdConfig) != 0)) {
   3760                 if (changedConfig == null
   3761                         || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
   3762                     changedConfig = tmp.createdConfig;
   3763                 }
   3764             }
   3765         }
   3766 
   3767         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
   3768                 + tmp.token + ": changedConfig=" + changedConfig);
   3769 
   3770         // If there was a pending configuration change, execute it first.
   3771         if (changedConfig != null) {
   3772             handleConfigurationChanged(changedConfig);
   3773         }
   3774 
   3775         ActivityRecord r = mActivities.get(tmp.token);
   3776         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
   3777         if (r == null) {
   3778             return;
   3779         }
   3780 
   3781         r.activity.mConfigChangeFlags |= configChanges;
   3782         Intent currentIntent = r.activity.mIntent;
   3783 
   3784         Bundle savedState = null;
   3785         if (!r.paused) {
   3786             savedState = performPauseActivity(r.token, false, true);
   3787         }
   3788 
   3789         handleDestroyActivity(r.token, false, configChanges, true);
   3790 
   3791         r.activity = null;
   3792         r.window = null;
   3793         r.hideForNow = false;
   3794         r.nextIdle = null;
   3795         // Merge any pending results and pending intents; don't just replace them
   3796         if (tmp.pendingResults != null) {
   3797             if (r.pendingResults == null) {
   3798                 r.pendingResults = tmp.pendingResults;
   3799             } else {
   3800                 r.pendingResults.addAll(tmp.pendingResults);
   3801             }
   3802         }
   3803         if (tmp.pendingIntents != null) {
   3804             if (r.pendingIntents == null) {
   3805                 r.pendingIntents = tmp.pendingIntents;
   3806             } else {
   3807                 r.pendingIntents.addAll(tmp.pendingIntents);
   3808             }
   3809         }
   3810         r.startsNotResumed = tmp.startsNotResumed;
   3811         if (savedState != null) {
   3812             r.state = savedState;
   3813         }
   3814 
   3815         handleLaunchActivity(r, currentIntent);
   3816     }
   3817 
   3818     private final void handleRequestThumbnail(IBinder token) {
   3819         ActivityRecord r = mActivities.get(token);
   3820         Bitmap thumbnail = createThumbnailBitmap(r);
   3821         CharSequence description = null;
   3822         try {
   3823             description = r.activity.onCreateDescription();
   3824         } catch (Exception e) {
   3825             if (!mInstrumentation.onException(r.activity, e)) {
   3826                 throw new RuntimeException(
   3827                         "Unable to create description of activity "
   3828                         + r.intent.getComponent().toShortString()
   3829                         + ": " + e.toString(), e);
   3830             }
   3831         }
   3832         //System.out.println("Reporting top thumbnail " + thumbnail);
   3833         try {
   3834             ActivityManagerNative.getDefault().reportThumbnail(
   3835                 token, thumbnail, description);
   3836         } catch (RemoteException ex) {
   3837         }
   3838     }
   3839 
   3840     ArrayList<ComponentCallbacks> collectComponentCallbacksLocked(
   3841             boolean allActivities, Configuration newConfig) {
   3842         ArrayList<ComponentCallbacks> callbacks
   3843                 = new ArrayList<ComponentCallbacks>();
   3844 
   3845         if (mActivities.size() > 0) {
   3846             Iterator<ActivityRecord> it = mActivities.values().iterator();
   3847             while (it.hasNext()) {
   3848                 ActivityRecord ar = it.next();
   3849                 Activity a = ar.activity;
   3850                 if (a != null) {
   3851                     if (!ar.activity.mFinished && (allActivities ||
   3852                             (a != null && !ar.paused))) {
   3853                         // If the activity is currently resumed, its configuration
   3854                         // needs to change right now.
   3855                         callbacks.add(a);
   3856                     } else if (newConfig != null) {
   3857                         // Otherwise, we will tell it about the change
   3858                         // the next time it is resumed or shown.  Note that
   3859                         // the activity manager may, before then, decide the
   3860                         // activity needs to be destroyed to handle its new
   3861                         // configuration.
   3862                         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Setting activity "
   3863                                 + ar.activityInfo.name + " newConfig=" + newConfig);
   3864                         ar.newConfig = newConfig;
   3865                     }
   3866                 }
   3867             }
   3868         }
   3869         if (mServices.size() > 0) {
   3870             Iterator<Service> it = mServices.values().iterator();
   3871             while (it.hasNext()) {
   3872                 callbacks.add(it.next());
   3873             }
   3874         }
   3875         synchronized (mProviderMap) {
   3876             if (mLocalProviders.size() > 0) {
   3877                 Iterator<ProviderRecord> it = mLocalProviders.values().iterator();
   3878                 while (it.hasNext()) {
   3879                     callbacks.add(it.next().mLocalProvider);
   3880                 }
   3881             }
   3882         }
   3883         final int N = mAllApplications.size();
   3884         for (int i=0; i<N; i++) {
   3885             callbacks.add(mAllApplications.get(i));
   3886         }
   3887 
   3888         return callbacks;
   3889     }
   3890 
   3891     private final void performConfigurationChanged(
   3892             ComponentCallbacks cb, Configuration config) {
   3893         // Only for Activity objects, check that they actually call up to their
   3894         // superclass implementation.  ComponentCallbacks is an interface, so
   3895         // we check the runtime type and act accordingly.
   3896         Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
   3897         if (activity != null) {
   3898             activity.mCalled = false;
   3899         }
   3900 
   3901         boolean shouldChangeConfig = false;
   3902         if ((activity == null) || (activity.mCurrentConfig == null)) {
   3903             shouldChangeConfig = true;
   3904         } else {
   3905 
   3906             // If the new config is the same as the config this Activity
   3907             // is already running with then don't bother calling
   3908             // onConfigurationChanged
   3909             int diff = activity.mCurrentConfig.diff(config);
   3910             if (diff != 0) {
   3911 
   3912                 // If this activity doesn't handle any of the config changes
   3913                 // then don't bother calling onConfigurationChanged as we're
   3914                 // going to destroy it.
   3915                 if ((~activity.mActivityInfo.configChanges & diff) == 0) {
   3916                     shouldChangeConfig = true;
   3917                 }
   3918             }
   3919         }
   3920 
   3921         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
   3922                 + ": shouldChangeConfig=" + shouldChangeConfig);
   3923         if (shouldChangeConfig) {
   3924             cb.onConfigurationChanged(config);
   3925 
   3926             if (activity != null) {
   3927                 if (!activity.mCalled) {
   3928                     throw new SuperNotCalledException(
   3929                             "Activity " + activity.getLocalClassName() +
   3930                         " did not call through to super.onConfigurationChanged()");
   3931                 }
   3932                 activity.mConfigChangeFlags = 0;
   3933                 activity.mCurrentConfig = new Configuration(config);
   3934             }
   3935         }
   3936     }
   3937 
   3938     final boolean applyConfigurationToResourcesLocked(Configuration config) {
   3939         if (mResConfiguration == null) {
   3940             mResConfiguration = new Configuration();
   3941         }
   3942         if (!mResConfiguration.isOtherSeqNewer(config)) {
   3943             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
   3944                     + mResConfiguration.seq + ", newSeq=" + config.seq);
   3945             return false;
   3946         }
   3947         int changes = mResConfiguration.updateFrom(config);
   3948         DisplayMetrics dm = getDisplayMetricsLocked(true);
   3949 
   3950         // set it for java, this also affects newly created Resources
   3951         if (config.locale != null) {
   3952             Locale.setDefault(config.locale);
   3953         }
   3954 
   3955         Resources.updateSystemConfiguration(config, dm);
   3956 
   3957         ContextImpl.ApplicationPackageManager.configurationChanged();
   3958         //Slog.i(TAG, "Configuration changed in " + currentPackageName());
   3959 
   3960         Iterator<WeakReference<Resources>> it =
   3961             mActiveResources.values().iterator();
   3962         //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
   3963         //    mActiveResources.entrySet().iterator();
   3964         while (it.hasNext()) {
   3965             WeakReference<Resources> v = it.next();
   3966             Resources r = v.get();
   3967             if (r != null) {
   3968                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
   3969                         + r + " config to: " + config);
   3970                 r.updateConfiguration(config, dm);
   3971                 //Slog.i(TAG, "Updated app resources " + v.getKey()
   3972                 //        + " " + r + ": " + r.getConfiguration());
   3973             } else {
   3974                 //Slog.i(TAG, "Removing old resources " + v.getKey());
   3975                 it.remove();
   3976             }
   3977         }
   3978 
   3979         return changes != 0;
   3980     }
   3981 
   3982     final void handleConfigurationChanged(Configuration config) {
   3983 
   3984         ArrayList<ComponentCallbacks> callbacks = null;
   3985 
   3986         synchronized (mPackages) {
   3987             if (mPendingConfiguration != null) {
   3988                 if (!mPendingConfiguration.isOtherSeqNewer(config)) {
   3989                     config = mPendingConfiguration;
   3990                 }
   3991                 mPendingConfiguration = null;
   3992             }
   3993 
   3994             if (config == null) {
   3995                 return;
   3996             }
   3997 
   3998             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
   3999                     + config);
   4000 
   4001             applyConfigurationToResourcesLocked(config);
   4002 
   4003             if (mConfiguration == null) {
   4004                 mConfiguration = new Configuration();
   4005             }
   4006             if (!mConfiguration.isOtherSeqNewer(config)) {
   4007                 return;
   4008             }
   4009             mConfiguration.updateFrom(config);
   4010 
   4011             callbacks = collectComponentCallbacksLocked(false, config);
   4012         }
   4013 
   4014         if (callbacks != null) {
   4015             final int N = callbacks.size();
   4016             for (int i=0; i<N; i++) {
   4017                 performConfigurationChanged(callbacks.get(i), config);
   4018             }
   4019         }
   4020     }
   4021 
   4022     final void handleActivityConfigurationChanged(IBinder token) {
   4023         ActivityRecord r = mActivities.get(token);
   4024         if (r == null || r.activity == null) {
   4025             return;
   4026         }
   4027 
   4028         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
   4029                 + r.activityInfo.name);
   4030 
   4031         performConfigurationChanged(r.activity, mConfiguration);
   4032     }
   4033 
   4034     final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
   4035         if (start) {
   4036             try {
   4037                 Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
   4038                         8 * 1024 * 1024, 0);
   4039             } catch (RuntimeException e) {
   4040                 Slog.w(TAG, "Profiling failed on path " + pcd.path
   4041                         + " -- can the process access this path?");
   4042             } finally {
   4043                 try {
   4044                     pcd.fd.close();
   4045                 } catch (IOException e) {
   4046                     Slog.w(TAG, "Failure closing profile fd", e);
   4047                 }
   4048             }
   4049         } else {
   4050             Debug.stopMethodTracing();
   4051         }
   4052     }
   4053 
   4054     final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
   4055         boolean hasPkgInfo = false;
   4056         if (packages != null) {
   4057             for (int i=packages.length-1; i>=0; i--) {
   4058                 //Slog.i(TAG, "Cleaning old package: " + packages[i]);
   4059                 if (!hasPkgInfo) {
   4060                     WeakReference<PackageInfo> ref;
   4061                     ref = mPackages.get(packages[i]);
   4062                     if (ref != null && ref.get() != null) {
   4063                         hasPkgInfo = true;
   4064                     } else {
   4065                         ref = mResourcePackages.get(packages[i]);
   4066                         if (ref != null && ref.get() != null) {
   4067                             hasPkgInfo = true;
   4068                         }
   4069                     }
   4070                 }
   4071                 mPackages.remove(packages[i]);
   4072                 mResourcePackages.remove(packages[i]);
   4073             }
   4074         }
   4075         ContextImpl.ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
   4076                 hasPkgInfo);
   4077     }
   4078 
   4079     final void handleLowMemory() {
   4080         ArrayList<ComponentCallbacks> callbacks
   4081                 = new ArrayList<ComponentCallbacks>();
   4082 
   4083         synchronized (mPackages) {
   4084             callbacks = collectComponentCallbacksLocked(true, null);
   4085         }
   4086 
   4087         final int N = callbacks.size();
   4088         for (int i=0; i<N; i++) {
   4089             callbacks.get(i).onLowMemory();
   4090         }
   4091 
   4092         // Ask SQLite to free up as much memory as it can, mostly from its page caches.
   4093         if (Process.myUid() != Process.SYSTEM_UID) {
   4094             int sqliteReleased = SQLiteDatabase.releaseMemory();
   4095             EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
   4096         }
   4097 
   4098         // Ask graphics to free up as much as possible (font/image caches)
   4099         Canvas.freeCaches();
   4100 
   4101         BinderInternal.forceGc("mem");
   4102     }
   4103 
   4104     private final void handleBindApplication(AppBindData data) {
   4105         mBoundApplication = data;
   4106         mConfiguration = new Configuration(data.config);
   4107 
   4108         // send up app name; do this *before* waiting for debugger
   4109         Process.setArgV0(data.processName);
   4110         android.ddm.DdmHandleAppName.setAppName(data.processName);
   4111 
   4112         /*
   4113          * Before spawning a new process, reset the time zone to be the system time zone.
   4114          * This needs to be done because the system time zone could have changed after the
   4115          * the spawning of this process. Without doing this this process would have the incorrect
   4116          * system time zone.
   4117          */
   4118         TimeZone.setDefault(null);
   4119 
   4120         /*
   4121          * Initialize the default locale in this process for the reasons we set the time zone.
   4122          */
   4123         Locale.setDefault(data.config.locale);
   4124 
   4125         /*
   4126          * Update the system configuration since its preloaded and might not
   4127          * reflect configuration changes. The configuration object passed
   4128          * in AppBindData can be safely assumed to be up to date
   4129          */
   4130         Resources.getSystem().updateConfiguration(mConfiguration, null);
   4131 
   4132         data.info = getPackageInfoNoCheck(data.appInfo);
   4133 
   4134         /**
   4135          * Switch this process to density compatibility mode if needed.
   4136          */
   4137         if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
   4138                 == 0) {
   4139             Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
   4140         }
   4141 
   4142         if (data.debugMode != IApplicationThread.DEBUG_OFF) {
   4143             // XXX should have option to change the port.
   4144             Debug.changeDebugPort(8100);
   4145             if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
   4146                 Slog.w(TAG, "Application " + data.info.getPackageName()
   4147                       + " is waiting for the debugger on port 8100...");
   4148 
   4149                 IActivityManager mgr = ActivityManagerNative.getDefault();
   4150                 try {
   4151                     mgr.showWaitingForDebugger(mAppThread, true);
   4152                 } catch (RemoteException ex) {
   4153                 }
   4154 
   4155                 Debug.waitForDebugger();
   4156 
   4157                 try {
   4158                     mgr.showWaitingForDebugger(mAppThread, false);
   4159                 } catch (RemoteException ex) {
   4160                 }
   4161 
   4162             } else {
   4163                 Slog.w(TAG, "Application " + data.info.getPackageName()
   4164                       + " can be debugged on port 8100...");
   4165             }
   4166         }
   4167 
   4168         if (data.instrumentationName != null) {
   4169             ContextImpl appContext = new ContextImpl();
   4170             appContext.init(data.info, null, this);
   4171             InstrumentationInfo ii = null;
   4172             try {
   4173                 ii = appContext.getPackageManager().
   4174                     getInstrumentationInfo(data.instrumentationName, 0);
   4175             } catch (PackageManager.NameNotFoundException e) {
   4176             }
   4177             if (ii == null) {
   4178                 throw new RuntimeException(
   4179                     "Unable to find instrumentation info for: "
   4180                     + data.instrumentationName);
   4181             }
   4182 
   4183             mInstrumentationAppDir = ii.sourceDir;
   4184             mInstrumentationAppPackage = ii.packageName;
   4185             mInstrumentedAppDir = data.info.getAppDir();
   4186 
   4187             ApplicationInfo instrApp = new ApplicationInfo();
   4188             instrApp.packageName = ii.packageName;
   4189             instrApp.sourceDir = ii.sourceDir;
   4190             instrApp.publicSourceDir = ii.publicSourceDir;
   4191             instrApp.dataDir = ii.dataDir;
   4192             PackageInfo pi = getPackageInfo(instrApp,
   4193                     appContext.getClassLoader(), false, true);
   4194             ContextImpl instrContext = new ContextImpl();
   4195             instrContext.init(pi, null, this);
   4196 
   4197             try {
   4198                 java.lang.ClassLoader cl = instrContext.getClassLoader();
   4199                 mInstrumentation = (Instrumentation)
   4200                     cl.loadClass(data.instrumentationName.getClassName()).newInstance();
   4201             } catch (Exception e) {
   4202                 throw new RuntimeException(
   4203                     "Unable to instantiate instrumentation "
   4204                     + data.instrumentationName + ": " + e.toString(), e);
   4205             }
   4206 
   4207             mInstrumentation.init(this, instrContext, appContext,
   4208                     new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
   4209 
   4210             if (data.profileFile != null && !ii.handleProfiling) {
   4211                 data.handlingProfiling = true;
   4212                 File file = new File(data.profileFile);
   4213                 file.getParentFile().mkdirs();
   4214                 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
   4215             }
   4216 
   4217             try {
   4218                 mInstrumentation.onCreate(data.instrumentationArgs);
   4219             }
   4220             catch (Exception e) {
   4221                 throw new RuntimeException(
   4222                     "Exception thrown in onCreate() of "
   4223                     + data.instrumentationName + ": " + e.toString(), e);
   4224             }
   4225 
   4226         } else {
   4227             mInstrumentation = new Instrumentation();
   4228         }
   4229 
   4230         // If the app is being launched for full backup or restore, bring it up in
   4231         // a restricted environment with the base application class.
   4232         Application app = data.info.makeApplication(data.restrictedBackupMode, null);
   4233         mInitialApplication = app;
   4234 
   4235         List<ProviderInfo> providers = data.providers;
   4236         if (providers != null) {
   4237             installContentProviders(app, providers);
   4238             // For process that contain content providers, we want to
   4239             // ensure that the JIT is enabled "at some point".
   4240             mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
   4241         }
   4242 
   4243         try {
   4244             mInstrumentation.callApplicationOnCreate(app);
   4245         } catch (Exception e) {
   4246             if (!mInstrumentation.onException(app, e)) {
   4247                 throw new RuntimeException(
   4248                     "Unable to create application " + app.getClass().getName()
   4249                     + ": " + e.toString(), e);
   4250             }
   4251         }
   4252     }
   4253 
   4254     /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
   4255         IActivityManager am = ActivityManagerNative.getDefault();
   4256         if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) {
   4257             Debug.stopMethodTracing();
   4258         }
   4259         //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault()
   4260         //      + ", app thr: " + mAppThread);
   4261         try {
   4262             am.finishInstrumentation(mAppThread, resultCode, results);
   4263         } catch (RemoteException ex) {
   4264         }
   4265     }
   4266 
   4267     private final void installContentProviders(
   4268             Context context, List<ProviderInfo> providers) {
   4269         final ArrayList<IActivityManager.ContentProviderHolder> results =
   4270             new ArrayList<IActivityManager.ContentProviderHolder>();
   4271 
   4272         Iterator<ProviderInfo> i = providers.iterator();
   4273         while (i.hasNext()) {
   4274             ProviderInfo cpi = i.next();
   4275             StringBuilder buf = new StringBuilder(128);
   4276             buf.append("Publishing provider ");
   4277             buf.append(cpi.authority);
   4278             buf.append(": ");
   4279             buf.append(cpi.name);
   4280             Log.i(TAG, buf.toString());
   4281             IContentProvider cp = installProvider(context, null, cpi, false);
   4282             if (cp != null) {
   4283                 IActivityManager.ContentProviderHolder cph =
   4284                     new IActivityManager.ContentProviderHolder(cpi);
   4285                 cph.provider = cp;
   4286                 results.add(cph);
   4287                 // Don't ever unload this provider from the process.
   4288                 synchronized(mProviderMap) {
   4289                     mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
   4290                 }
   4291             }
   4292         }
   4293 
   4294         try {
   4295             ActivityManagerNative.getDefault().publishContentProviders(
   4296                 getApplicationThread(), results);
   4297         } catch (RemoteException ex) {
   4298         }
   4299     }
   4300 
   4301     private final IContentProvider getProvider(Context context, String name) {
   4302         synchronized(mProviderMap) {
   4303             final ProviderRecord pr = mProviderMap.get(name);
   4304             if (pr != null) {
   4305                 return pr.mProvider;
   4306             }
   4307         }
   4308 
   4309         IActivityManager.ContentProviderHolder holder = null;
   4310         try {
   4311             holder = ActivityManagerNative.getDefault().getContentProvider(
   4312                 getApplicationThread(), name);
   4313         } catch (RemoteException ex) {
   4314         }
   4315         if (holder == null) {
   4316             Slog.e(TAG, "Failed to find provider info for " + name);
   4317             return null;
   4318         }
   4319         if (holder.permissionFailure != null) {
   4320             throw new SecurityException("Permission " + holder.permissionFailure
   4321                     + " required for provider " + name);
   4322         }
   4323 
   4324         IContentProvider prov = installProvider(context, holder.provider,
   4325                 holder.info, true);
   4326         //Slog.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
   4327         if (holder.noReleaseNeeded || holder.provider == null) {
   4328             // We are not going to release the provider if it is an external
   4329             // provider that doesn't care about being released, or if it is
   4330             // a local provider running in this process.
   4331             //Slog.i(TAG, "*** NO RELEASE NEEDED");
   4332             synchronized(mProviderMap) {
   4333                 mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
   4334             }
   4335         }
   4336         return prov;
   4337     }
   4338 
   4339     public final IContentProvider acquireProvider(Context c, String name) {
   4340         IContentProvider provider = getProvider(c, name);
   4341         if(provider == null)
   4342             return null;
   4343         IBinder jBinder = provider.asBinder();
   4344         synchronized(mProviderMap) {
   4345             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
   4346             if(prc == null) {
   4347                 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
   4348             } else {
   4349                 prc.count++;
   4350             } //end else
   4351         } //end synchronized
   4352         return provider;
   4353     }
   4354 
   4355     public final boolean releaseProvider(IContentProvider provider) {
   4356         if(provider == null) {
   4357             return false;
   4358         }
   4359         IBinder jBinder = provider.asBinder();
   4360         synchronized(mProviderMap) {
   4361             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
   4362             if(prc == null) {
   4363                 if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldnt be here");
   4364                 return false;
   4365             } else {
   4366                 prc.count--;
   4367                 if(prc.count == 0) {
   4368                     // Schedule the actual remove asynchronously, since we
   4369                     // don't know the context this will be called in.
   4370                     // TODO: it would be nice to post a delayed message, so
   4371                     // if we come back and need the same provider quickly
   4372                     // we will still have it available.
   4373                     Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
   4374                     mH.sendMessage(msg);
   4375                 } //end if
   4376             } //end else
   4377         } //end synchronized
   4378         return true;
   4379     }
   4380 
   4381     final void completeRemoveProvider(IContentProvider provider) {
   4382         IBinder jBinder = provider.asBinder();
   4383         String name = null;
   4384         synchronized(mProviderMap) {
   4385             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
   4386             if(prc != null && prc.count == 0) {
   4387                 mProviderRefCountMap.remove(jBinder);
   4388                 //invoke removeProvider to dereference provider
   4389                 name = removeProviderLocked(provider);
   4390             }
   4391         }
   4392 
   4393         if (name != null) {
   4394             try {
   4395                 if(localLOGV) Slog.v(TAG, "removeProvider::Invoking " +
   4396                         "ActivityManagerNative.removeContentProvider(" + name);
   4397                 ActivityManagerNative.getDefault().removeContentProvider(
   4398                         getApplicationThread(), name);
   4399             } catch (RemoteException e) {
   4400                 //do nothing content provider object is dead any way
   4401             } //end catch
   4402         }
   4403     }
   4404 
   4405     public final String removeProviderLocked(IContentProvider provider) {
   4406         if (provider == null) {
   4407             return null;
   4408         }
   4409         IBinder providerBinder = provider.asBinder();
   4410 
   4411         String name = null;
   4412 
   4413         // remove the provider from mProviderMap
   4414         Iterator<ProviderRecord> iter = mProviderMap.values().iterator();
   4415         while (iter.hasNext()) {
   4416             ProviderRecord pr = iter.next();
   4417             IBinder myBinder = pr.mProvider.asBinder();
   4418             if (myBinder == providerBinder) {
   4419                 //find if its published by this process itself
   4420                 if(pr.mLocalProvider != null) {
   4421                     if(localLOGV) Slog.i(TAG, "removeProvider::found local provider returning");
   4422                     return name;
   4423                 }
   4424                 if(localLOGV) Slog.v(TAG, "removeProvider::Not local provider Unlinking " +
   4425                         "death recipient");
   4426                 //content provider is in another process
   4427                 myBinder.unlinkToDeath(pr, 0);
   4428                 iter.remove();
   4429                 //invoke remove only once for the very first name seen
   4430                 if(name == null) {
   4431                     name = pr.mName;
   4432                 }
   4433             } //end if myBinder
   4434         }  //end while iter
   4435 
   4436         return name;
   4437     }
   4438 
   4439     final void removeDeadProvider(String name, IContentProvider provider) {
   4440         synchronized(mProviderMap) {
   4441             ProviderRecord pr = mProviderMap.get(name);
   4442             if (pr.mProvider.asBinder() == provider.asBinder()) {
   4443                 Slog.i(TAG, "Removing dead content provider: " + name);
   4444                 ProviderRecord removed = mProviderMap.remove(name);
   4445                 if (removed != null) {
   4446                     removed.mProvider.asBinder().unlinkToDeath(removed, 0);
   4447                 }
   4448             }
   4449         }
   4450     }
   4451 
   4452     final void removeDeadProviderLocked(String name, IContentProvider provider) {
   4453         ProviderRecord pr = mProviderMap.get(name);
   4454         if (pr.mProvider.asBinder() == provider.asBinder()) {
   4455             Slog.i(TAG, "Removing dead content provider: " + name);
   4456             ProviderRecord removed = mProviderMap.remove(name);
   4457             if (removed != null) {
   4458                 removed.mProvider.asBinder().unlinkToDeath(removed, 0);
   4459             }
   4460         }
   4461     }
   4462 
   4463     private final IContentProvider installProvider(Context context,
   4464             IContentProvider provider, ProviderInfo info, boolean noisy) {
   4465         ContentProvider localProvider = null;
   4466         if (provider == null) {
   4467             if (noisy) {
   4468                 Slog.d(TAG, "Loading provider " + info.authority + ": "
   4469                         + info.name);
   4470             }
   4471             Context c = null;
   4472             ApplicationInfo ai = info.applicationInfo;
   4473             if (context.getPackageName().equals(ai.packageName)) {
   4474                 c = context;
   4475             } else if (mInitialApplication != null &&
   4476                     mInitialApplication.getPackageName().equals(ai.packageName)) {
   4477                 c = mInitialApplication;
   4478             } else {
   4479                 try {
   4480                     c = context.createPackageContext(ai.packageName,
   4481                             Context.CONTEXT_INCLUDE_CODE);
   4482                 } catch (PackageManager.NameNotFoundException e) {
   4483                 }
   4484             }
   4485             if (c == null) {
   4486                 Slog.w(TAG, "Unable to get context for package " +
   4487                       ai.packageName +
   4488                       " while loading content provider " +
   4489                       info.name);
   4490                 return null;
   4491             }
   4492             try {
   4493                 final java.lang.ClassLoader cl = c.getClassLoader();
   4494                 localProvider = (ContentProvider)cl.
   4495                     loadClass(info.name).newInstance();
   4496                 provider = localProvider.getIContentProvider();
   4497                 if (provider == null) {
   4498                     Slog.e(TAG, "Failed to instantiate class " +
   4499                           info.name + " from sourceDir " +
   4500                           info.applicationInfo.sourceDir);
   4501                     return null;
   4502                 }
   4503                 if (Config.LOGV) Slog.v(
   4504                     TAG, "Instantiating local provider " + info.name);
   4505                 // XXX Need to create the correct context for this provider.
   4506                 localProvider.attachInfo(c, info);
   4507             } catch (java.lang.Exception e) {
   4508                 if (!mInstrumentation.onException(null, e)) {
   4509                     throw new RuntimeException(
   4510                             "Unable to get provider " + info.name
   4511                             + ": " + e.toString(), e);
   4512                 }
   4513                 return null;
   4514             }
   4515         } else if (localLOGV) {
   4516             Slog.v(TAG, "Installing external provider " + info.authority + ": "
   4517                     + info.name);
   4518         }
   4519 
   4520         synchronized (mProviderMap) {
   4521             // Cache the pointer for the remote provider.
   4522             String names[] = PATTERN_SEMICOLON.split(info.authority);
   4523             for (int i=0; i<names.length; i++) {
   4524                 ProviderRecord pr = new ProviderRecord(names[i], provider,
   4525                         localProvider);
   4526                 try {
   4527                     provider.asBinder().linkToDeath(pr, 0);
   4528                     mProviderMap.put(names[i], pr);
   4529                 } catch (RemoteException e) {
   4530                     return null;
   4531                 }
   4532             }
   4533             if (localProvider != null) {
   4534                 mLocalProviders.put(provider.asBinder(),
   4535                         new ProviderRecord(null, provider, localProvider));
   4536             }
   4537         }
   4538 
   4539         return provider;
   4540     }
   4541 
   4542     private final void attach(boolean system) {
   4543         sThreadLocal.set(this);
   4544         mSystemThread = system;
   4545         if (!system) {
   4546             ViewRoot.addFirstDrawHandler(new Runnable() {
   4547                 public void run() {
   4548                     ensureJitEnabled();
   4549                 }
   4550             });
   4551             android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
   4552             RuntimeInit.setApplicationObject(mAppThread.asBinder());
   4553             IActivityManager mgr = ActivityManagerNative.getDefault();
   4554             try {
   4555                 mgr.attachApplication(mAppThread);
   4556             } catch (RemoteException ex) {
   4557             }
   4558         } else {
   4559             // Don't set application object here -- if the system crashes,
   4560             // we can't display an alert, we just want to die die die.
   4561             android.ddm.DdmHandleAppName.setAppName("system_process");
   4562             try {
   4563                 mInstrumentation = new Instrumentation();
   4564                 ContextImpl context = new ContextImpl();
   4565                 context.init(getSystemContext().mPackageInfo, null, this);
   4566                 Application app = Instrumentation.newApplication(Application.class, context);
   4567                 mAllApplications.add(app);
   4568                 mInitialApplication = app;
   4569                 app.onCreate();
   4570             } catch (Exception e) {
   4571                 throw new RuntimeException(
   4572                         "Unable to instantiate Application():" + e.toString(), e);
   4573             }
   4574         }
   4575 
   4576         ViewRoot.addConfigCallback(new ComponentCallbacks() {
   4577             public void onConfigurationChanged(Configuration newConfig) {
   4578                 synchronized (mPackages) {
   4579                     // We need to apply this change to the resources
   4580                     // immediately, because upon returning the view
   4581                     // hierarchy will be informed about it.
   4582                     if (applyConfigurationToResourcesLocked(newConfig)) {
   4583                         // This actually changed the resources!  Tell
   4584                         // everyone about it.
   4585                         if (mPendingConfiguration == null ||
   4586                                 mPendingConfiguration.isOtherSeqNewer(newConfig)) {
   4587                             mPendingConfiguration = newConfig;
   4588 
   4589                             queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
   4590                         }
   4591                     }
   4592                 }
   4593             }
   4594             public void onLowMemory() {
   4595             }
   4596         });
   4597     }
   4598 
   4599     private final void detach()
   4600     {
   4601         sThreadLocal.set(null);
   4602     }
   4603 
   4604     public static final ActivityThread systemMain() {
   4605         ActivityThread thread = new ActivityThread();
   4606         thread.attach(true);
   4607         return thread;
   4608     }
   4609 
   4610     public final void installSystemProviders(List providers) {
   4611         if (providers != null) {
   4612             installContentProviders(mInitialApplication,
   4613                                     (List<ProviderInfo>)providers);
   4614         }
   4615     }
   4616 
   4617     public static final void main(String[] args) {
   4618         SamplingProfilerIntegration.start();
   4619 
   4620         Process.setArgV0("<pre-initialized>");
   4621 
   4622         Looper.prepareMainLooper();
   4623 
   4624         ActivityThread thread = new ActivityThread();
   4625         thread.attach(false);
   4626 
   4627         Looper.loop();
   4628 
   4629         if (Process.supportsProcesses()) {
   4630             throw new RuntimeException("Main thread loop unexpectedly exited");
   4631         }
   4632 
   4633         thread.detach();
   4634         String name = (thread.mInitialApplication != null)
   4635             ? thread.mInitialApplication.getPackageName()
   4636             : "<unknown>";
   4637         Slog.i(TAG, "Main thread of " + name + " is now exiting");
   4638     }
   4639 }
   4640