ActivityThread.java revision 3d32f6e5228e5dfbfe88b24f6df64406628a3e0c
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
17package android.app;
18
19import android.app.backup.BackupAgent;
20import android.content.BroadcastReceiver;
21import android.content.ComponentCallbacks;
22import android.content.ComponentName;
23import android.content.ContentProvider;
24import android.content.Context;
25import android.content.IContentProvider;
26import android.content.Intent;
27import android.content.IIntentReceiver;
28import android.content.ServiceConnection;
29import android.content.pm.ActivityInfo;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.IPackageManager;
32import android.content.pm.InstrumentationInfo;
33import android.content.pm.PackageManager;
34import android.content.pm.ProviderInfo;
35import android.content.pm.ServiceInfo;
36import android.content.res.AssetManager;
37import android.content.res.CompatibilityInfo;
38import android.content.res.Configuration;
39import android.content.res.Resources;
40import android.database.sqlite.SQLiteDatabase;
41import android.database.sqlite.SQLiteDebug;
42import android.database.sqlite.SQLiteDebug.DbStats;
43import android.graphics.Bitmap;
44import android.graphics.Canvas;
45import android.os.Bundle;
46import android.os.Debug;
47import android.os.Handler;
48import android.os.IBinder;
49import android.os.Looper;
50import android.os.Message;
51import android.os.MessageQueue;
52import android.os.ParcelFileDescriptor;
53import android.os.Process;
54import android.os.RemoteException;
55import android.os.ServiceManager;
56import android.os.SystemClock;
57import android.util.AndroidRuntimeException;
58import android.util.Config;
59import android.util.DisplayMetrics;
60import android.util.EventLog;
61import android.util.Log;
62import android.util.Slog;
63import android.view.Display;
64import android.view.View;
65import android.view.ViewDebug;
66import android.view.ViewManager;
67import android.view.ViewRoot;
68import android.view.Window;
69import android.view.WindowManager;
70import android.view.WindowManagerImpl;
71
72import com.android.internal.os.BinderInternal;
73import com.android.internal.os.RuntimeInit;
74import com.android.internal.os.SamplingProfilerIntegration;
75import com.android.internal.util.ArrayUtils;
76
77import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
78
79import java.io.File;
80import java.io.FileDescriptor;
81import java.io.FileOutputStream;
82import java.io.IOException;
83import java.io.InputStream;
84import java.io.PrintWriter;
85import java.lang.ref.WeakReference;
86import java.net.URL;
87import java.util.ArrayList;
88import java.util.Enumeration;
89import java.util.HashMap;
90import java.util.Iterator;
91import java.util.List;
92import java.util.Locale;
93import java.util.Map;
94import java.util.TimeZone;
95import java.util.regex.Pattern;
96
97import dalvik.system.SamplingProfiler;
98
99final class IntentReceiverLeaked extends AndroidRuntimeException {
100    public IntentReceiverLeaked(String msg) {
101        super(msg);
102    }
103}
104
105final class ServiceConnectionLeaked extends AndroidRuntimeException {
106    public ServiceConnectionLeaked(String msg) {
107        super(msg);
108    }
109}
110
111final 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 */
125public 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 = "  %4d %6d %8d %14s  %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.cache, 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, "  %4s %6s %8s %14s  %s", "pgsz", "dbsz", "lkaside", "cache",
1925                    "Dbname");
1926                for (int i = 0; i < N; i++) {
1927                    DbStats dbStats = stats.dbStats.get(i);
1928                    printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
1929                            dbStats.lookaside, dbStats.cache, dbStats.dbName);
1930                }
1931            }
1932
1933            // Asset details.
1934            String assetAlloc = AssetManager.getAssetAllocations();
1935            if (assetAlloc != null) {
1936                pw.println(" ");
1937                pw.println(" Asset Allocations");
1938                pw.print(assetAlloc);
1939            }
1940        }
1941
1942        private void printRow(PrintWriter pw, String format, Object...objs) {
1943            pw.println(String.format(format, objs));
1944        }
1945    }
1946
1947    private final class H extends Handler {
1948        private H() {
1949            SamplingProfiler.getInstance().setEventThread(mLooper.getThread());
1950        }
1951
1952        public static final int LAUNCH_ACTIVITY         = 100;
1953        public static final int PAUSE_ACTIVITY          = 101;
1954        public static final int PAUSE_ACTIVITY_FINISHING= 102;
1955        public static final int STOP_ACTIVITY_SHOW      = 103;
1956        public static final int STOP_ACTIVITY_HIDE      = 104;
1957        public static final int SHOW_WINDOW             = 105;
1958        public static final int HIDE_WINDOW             = 106;
1959        public static final int RESUME_ACTIVITY         = 107;
1960        public static final int SEND_RESULT             = 108;
1961        public static final int DESTROY_ACTIVITY         = 109;
1962        public static final int BIND_APPLICATION        = 110;
1963        public static final int EXIT_APPLICATION        = 111;
1964        public static final int NEW_INTENT              = 112;
1965        public static final int RECEIVER                = 113;
1966        public static final int CREATE_SERVICE          = 114;
1967        public static final int SERVICE_ARGS            = 115;
1968        public static final int STOP_SERVICE            = 116;
1969        public static final int REQUEST_THUMBNAIL       = 117;
1970        public static final int CONFIGURATION_CHANGED   = 118;
1971        public static final int CLEAN_UP_CONTEXT        = 119;
1972        public static final int GC_WHEN_IDLE            = 120;
1973        public static final int BIND_SERVICE            = 121;
1974        public static final int UNBIND_SERVICE          = 122;
1975        public static final int DUMP_SERVICE            = 123;
1976        public static final int LOW_MEMORY              = 124;
1977        public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
1978        public static final int RELAUNCH_ACTIVITY       = 126;
1979        public static final int PROFILER_CONTROL        = 127;
1980        public static final int CREATE_BACKUP_AGENT     = 128;
1981        public static final int DESTROY_BACKUP_AGENT    = 129;
1982        public static final int SUICIDE                 = 130;
1983        public static final int REMOVE_PROVIDER         = 131;
1984        public static final int ENABLE_JIT              = 132;
1985        public static final int DISPATCH_PACKAGE_BROADCAST = 133;
1986        String codeToString(int code) {
1987            if (localLOGV) {
1988                switch (code) {
1989                    case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
1990                    case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
1991                    case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
1992                    case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
1993                    case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
1994                    case SHOW_WINDOW: return "SHOW_WINDOW";
1995                    case HIDE_WINDOW: return "HIDE_WINDOW";
1996                    case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
1997                    case SEND_RESULT: return "SEND_RESULT";
1998                    case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
1999                    case BIND_APPLICATION: return "BIND_APPLICATION";
2000                    case EXIT_APPLICATION: return "EXIT_APPLICATION";
2001                    case NEW_INTENT: return "NEW_INTENT";
2002                    case RECEIVER: return "RECEIVER";
2003                    case CREATE_SERVICE: return "CREATE_SERVICE";
2004                    case SERVICE_ARGS: return "SERVICE_ARGS";
2005                    case STOP_SERVICE: return "STOP_SERVICE";
2006                    case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
2007                    case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
2008                    case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
2009                    case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
2010                    case BIND_SERVICE: return "BIND_SERVICE";
2011                    case UNBIND_SERVICE: return "UNBIND_SERVICE";
2012                    case DUMP_SERVICE: return "DUMP_SERVICE";
2013                    case LOW_MEMORY: return "LOW_MEMORY";
2014                    case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
2015                    case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
2016                    case PROFILER_CONTROL: return "PROFILER_CONTROL";
2017                    case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
2018                    case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
2019                    case SUICIDE: return "SUICIDE";
2020                    case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
2021                    case ENABLE_JIT: return "ENABLE_JIT";
2022                    case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
2023                }
2024            }
2025            return "(unknown)";
2026        }
2027        public void handleMessage(Message msg) {
2028            switch (msg.what) {
2029                case LAUNCH_ACTIVITY: {
2030                    ActivityRecord r = (ActivityRecord)msg.obj;
2031
2032                    r.packageInfo = getPackageInfoNoCheck(
2033                            r.activityInfo.applicationInfo);
2034                    handleLaunchActivity(r, null);
2035                } break;
2036                case RELAUNCH_ACTIVITY: {
2037                    ActivityRecord r = (ActivityRecord)msg.obj;
2038                    handleRelaunchActivity(r, msg.arg1);
2039                } break;
2040                case PAUSE_ACTIVITY:
2041                    handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
2042                    maybeSnapshot();
2043                    break;
2044                case PAUSE_ACTIVITY_FINISHING:
2045                    handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
2046                    break;
2047                case STOP_ACTIVITY_SHOW:
2048                    handleStopActivity((IBinder)msg.obj, true, msg.arg2);
2049                    break;
2050                case STOP_ACTIVITY_HIDE:
2051                    handleStopActivity((IBinder)msg.obj, false, msg.arg2);
2052                    break;
2053                case SHOW_WINDOW:
2054                    handleWindowVisibility((IBinder)msg.obj, true);
2055                    break;
2056                case HIDE_WINDOW:
2057                    handleWindowVisibility((IBinder)msg.obj, false);
2058                    break;
2059                case RESUME_ACTIVITY:
2060                    handleResumeActivity((IBinder)msg.obj, true,
2061                            msg.arg1 != 0);
2062                    break;
2063                case SEND_RESULT:
2064                    handleSendResult((ResultData)msg.obj);
2065                    break;
2066                case DESTROY_ACTIVITY:
2067                    handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
2068                            msg.arg2, false);
2069                    break;
2070                case BIND_APPLICATION:
2071                    AppBindData data = (AppBindData)msg.obj;
2072                    handleBindApplication(data);
2073                    break;
2074                case EXIT_APPLICATION:
2075                    if (mInitialApplication != null) {
2076                        mInitialApplication.onTerminate();
2077                    }
2078                    Looper.myLooper().quit();
2079                    break;
2080                case NEW_INTENT:
2081                    handleNewIntent((NewIntentData)msg.obj);
2082                    break;
2083                case RECEIVER:
2084                    handleReceiver((ReceiverData)msg.obj);
2085                    maybeSnapshot();
2086                    break;
2087                case CREATE_SERVICE:
2088                    handleCreateService((CreateServiceData)msg.obj);
2089                    break;
2090                case BIND_SERVICE:
2091                    handleBindService((BindServiceData)msg.obj);
2092                    break;
2093                case UNBIND_SERVICE:
2094                    handleUnbindService((BindServiceData)msg.obj);
2095                    break;
2096                case SERVICE_ARGS:
2097                    handleServiceArgs((ServiceArgsData)msg.obj);
2098                    break;
2099                case STOP_SERVICE:
2100                    handleStopService((IBinder)msg.obj);
2101                    maybeSnapshot();
2102                    break;
2103                case REQUEST_THUMBNAIL:
2104                    handleRequestThumbnail((IBinder)msg.obj);
2105                    break;
2106                case CONFIGURATION_CHANGED:
2107                    handleConfigurationChanged((Configuration)msg.obj);
2108                    break;
2109                case CLEAN_UP_CONTEXT:
2110                    ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
2111                    cci.context.performFinalCleanup(cci.who, cci.what);
2112                    break;
2113                case GC_WHEN_IDLE:
2114                    scheduleGcIdler();
2115                    break;
2116                case DUMP_SERVICE:
2117                    handleDumpService((DumpServiceInfo)msg.obj);
2118                    break;
2119                case LOW_MEMORY:
2120                    handleLowMemory();
2121                    break;
2122                case ACTIVITY_CONFIGURATION_CHANGED:
2123                    handleActivityConfigurationChanged((IBinder)msg.obj);
2124                    break;
2125                case PROFILER_CONTROL:
2126                    handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
2127                    break;
2128                case CREATE_BACKUP_AGENT:
2129                    handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
2130                    break;
2131                case DESTROY_BACKUP_AGENT:
2132                    handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
2133                    break;
2134                case SUICIDE:
2135                    Process.killProcess(Process.myPid());
2136                    break;
2137                case REMOVE_PROVIDER:
2138                    completeRemoveProvider((IContentProvider)msg.obj);
2139                    break;
2140                case ENABLE_JIT:
2141                    ensureJitEnabled();
2142                    break;
2143                case DISPATCH_PACKAGE_BROADCAST:
2144                    handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
2145                    break;
2146            }
2147        }
2148
2149        void maybeSnapshot() {
2150            if (mBoundApplication != null) {
2151                SamplingProfilerIntegration.writeSnapshot(
2152                        mBoundApplication.processName);
2153            }
2154        }
2155    }
2156
2157    private final class Idler implements MessageQueue.IdleHandler {
2158        public final boolean queueIdle() {
2159            ActivityRecord a = mNewActivities;
2160            if (a != null) {
2161                mNewActivities = null;
2162                IActivityManager am = ActivityManagerNative.getDefault();
2163                ActivityRecord prev;
2164                do {
2165                    if (localLOGV) Slog.v(
2166                        TAG, "Reporting idle of " + a +
2167                        " finished=" +
2168                        (a.activity != null ? a.activity.mFinished : false));
2169                    if (a.activity != null && !a.activity.mFinished) {
2170                        try {
2171                            am.activityIdle(a.token, a.createdConfig);
2172                            a.createdConfig = null;
2173                        } catch (RemoteException ex) {
2174                        }
2175                    }
2176                    prev = a;
2177                    a = a.nextIdle;
2178                    prev.nextIdle = null;
2179                } while (a != null);
2180            }
2181            ensureJitEnabled();
2182            return false;
2183        }
2184    }
2185
2186    final class GcIdler implements MessageQueue.IdleHandler {
2187        public final boolean queueIdle() {
2188            doGcIfNeeded();
2189            return false;
2190        }
2191    }
2192
2193    private final static class ResourcesKey {
2194        final private String mResDir;
2195        final private float mScale;
2196        final private int mHash;
2197
2198        ResourcesKey(String resDir, float scale) {
2199            mResDir = resDir;
2200            mScale = scale;
2201            mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
2202        }
2203
2204        @Override
2205        public int hashCode() {
2206            return mHash;
2207        }
2208
2209        @Override
2210        public boolean equals(Object obj) {
2211            if (!(obj instanceof ResourcesKey)) {
2212                return false;
2213            }
2214            ResourcesKey peer = (ResourcesKey) obj;
2215            return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
2216        }
2217    }
2218
2219    static IPackageManager sPackageManager;
2220
2221    final ApplicationThread mAppThread = new ApplicationThread();
2222    final Looper mLooper = Looper.myLooper();
2223    final H mH = new H();
2224    final HashMap<IBinder, ActivityRecord> mActivities
2225            = new HashMap<IBinder, ActivityRecord>();
2226    // List of new activities (via ActivityRecord.nextIdle) that should
2227    // be reported when next we idle.
2228    ActivityRecord mNewActivities = null;
2229    // Number of activities that are currently visible on-screen.
2230    int mNumVisibleActivities = 0;
2231    final HashMap<IBinder, Service> mServices
2232            = new HashMap<IBinder, Service>();
2233    AppBindData mBoundApplication;
2234    Configuration mConfiguration;
2235    Configuration mResConfiguration;
2236    Application mInitialApplication;
2237    final ArrayList<Application> mAllApplications
2238            = new ArrayList<Application>();
2239    // set of instantiated backup agents, keyed by package name
2240    final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
2241    static final ThreadLocal sThreadLocal = new ThreadLocal();
2242    Instrumentation mInstrumentation;
2243    String mInstrumentationAppDir = null;
2244    String mInstrumentationAppPackage = null;
2245    String mInstrumentedAppDir = null;
2246    boolean mSystemThread = false;
2247    boolean mJitEnabled = false;
2248
2249    // These can be accessed by multiple threads; mPackages is the lock.
2250    // XXX For now we keep around information about all packages we have
2251    // seen, not removing entries from this map.
2252    final HashMap<String, WeakReference<PackageInfo>> mPackages
2253            = new HashMap<String, WeakReference<PackageInfo>>();
2254    final HashMap<String, WeakReference<PackageInfo>> mResourcePackages
2255            = new HashMap<String, WeakReference<PackageInfo>>();
2256    Display mDisplay = null;
2257    DisplayMetrics mDisplayMetrics = null;
2258    final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
2259            = new HashMap<ResourcesKey, WeakReference<Resources> >();
2260    final ArrayList<ActivityRecord> mRelaunchingActivities
2261            = new ArrayList<ActivityRecord>();
2262    Configuration mPendingConfiguration = null;
2263
2264    // The lock of mProviderMap protects the following variables.
2265    final HashMap<String, ProviderRecord> mProviderMap
2266        = new HashMap<String, ProviderRecord>();
2267    final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
2268        = new HashMap<IBinder, ProviderRefCount>();
2269    final HashMap<IBinder, ProviderRecord> mLocalProviders
2270        = new HashMap<IBinder, ProviderRecord>();
2271
2272    final GcIdler mGcIdler = new GcIdler();
2273    boolean mGcIdlerScheduled = false;
2274
2275    public final PackageInfo getPackageInfo(String packageName, int flags) {
2276        synchronized (mPackages) {
2277            WeakReference<PackageInfo> ref;
2278            if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
2279                ref = mPackages.get(packageName);
2280            } else {
2281                ref = mResourcePackages.get(packageName);
2282            }
2283            PackageInfo packageInfo = ref != null ? ref.get() : null;
2284            //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
2285            //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
2286            //        + ": " + packageInfo.mResources.getAssets().isUpToDate());
2287            if (packageInfo != null && (packageInfo.mResources == null
2288                    || packageInfo.mResources.getAssets().isUpToDate())) {
2289                if (packageInfo.isSecurityViolation()
2290                        && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
2291                    throw new SecurityException(
2292                            "Requesting code from " + packageName
2293                            + " to be run in process "
2294                            + mBoundApplication.processName
2295                            + "/" + mBoundApplication.appInfo.uid);
2296                }
2297                return packageInfo;
2298            }
2299        }
2300
2301        ApplicationInfo ai = null;
2302        try {
2303            ai = getPackageManager().getApplicationInfo(packageName,
2304                    PackageManager.GET_SHARED_LIBRARY_FILES);
2305        } catch (RemoteException e) {
2306        }
2307
2308        if (ai != null) {
2309            return getPackageInfo(ai, flags);
2310        }
2311
2312        return null;
2313    }
2314
2315    public final PackageInfo getPackageInfo(ApplicationInfo ai, int flags) {
2316        boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
2317        boolean securityViolation = includeCode && ai.uid != 0
2318                && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
2319                        ? ai.uid != mBoundApplication.appInfo.uid : true);
2320        if ((flags&(Context.CONTEXT_INCLUDE_CODE
2321                |Context.CONTEXT_IGNORE_SECURITY))
2322                == Context.CONTEXT_INCLUDE_CODE) {
2323            if (securityViolation) {
2324                String msg = "Requesting code from " + ai.packageName
2325                        + " (with uid " + ai.uid + ")";
2326                if (mBoundApplication != null) {
2327                    msg = msg + " to be run in process "
2328                        + mBoundApplication.processName + " (with uid "
2329                        + mBoundApplication.appInfo.uid + ")";
2330                }
2331                throw new SecurityException(msg);
2332            }
2333        }
2334        return getPackageInfo(ai, null, securityViolation, includeCode);
2335    }
2336
2337    public final PackageInfo getPackageInfoNoCheck(ApplicationInfo ai) {
2338        return getPackageInfo(ai, null, false, true);
2339    }
2340
2341    private final PackageInfo getPackageInfo(ApplicationInfo aInfo,
2342            ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
2343        synchronized (mPackages) {
2344            WeakReference<PackageInfo> ref;
2345            if (includeCode) {
2346                ref = mPackages.get(aInfo.packageName);
2347            } else {
2348                ref = mResourcePackages.get(aInfo.packageName);
2349            }
2350            PackageInfo packageInfo = ref != null ? ref.get() : null;
2351            if (packageInfo == null || (packageInfo.mResources != null
2352                    && !packageInfo.mResources.getAssets().isUpToDate())) {
2353                if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
2354                        : "Loading resource-only package ") + aInfo.packageName
2355                        + " (in " + (mBoundApplication != null
2356                                ? mBoundApplication.processName : null)
2357                        + ")");
2358                packageInfo =
2359                    new PackageInfo(this, aInfo, this, baseLoader,
2360                            securityViolation, includeCode &&
2361                            (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
2362                if (includeCode) {
2363                    mPackages.put(aInfo.packageName,
2364                            new WeakReference<PackageInfo>(packageInfo));
2365                } else {
2366                    mResourcePackages.put(aInfo.packageName,
2367                            new WeakReference<PackageInfo>(packageInfo));
2368                }
2369            }
2370            return packageInfo;
2371        }
2372    }
2373
2374    ActivityThread() {
2375    }
2376
2377    public ApplicationThread getApplicationThread()
2378    {
2379        return mAppThread;
2380    }
2381
2382    public Instrumentation getInstrumentation()
2383    {
2384        return mInstrumentation;
2385    }
2386
2387    public Configuration getConfiguration() {
2388        return mConfiguration;
2389    }
2390
2391    public boolean isProfiling() {
2392        return mBoundApplication != null && mBoundApplication.profileFile != null;
2393    }
2394
2395    public String getProfileFilePath() {
2396        return mBoundApplication.profileFile;
2397    }
2398
2399    public Looper getLooper() {
2400        return mLooper;
2401    }
2402
2403    public Application getApplication() {
2404        return mInitialApplication;
2405    }
2406
2407    public String getProcessName() {
2408        return mBoundApplication.processName;
2409    }
2410
2411    public ContextImpl getSystemContext() {
2412        synchronized (this) {
2413            if (mSystemContext == null) {
2414                ContextImpl context =
2415                    ContextImpl.createSystemContext(this);
2416                PackageInfo info = new PackageInfo(this, "android", context, null);
2417                context.init(info, null, this);
2418                context.getResources().updateConfiguration(
2419                        getConfiguration(), getDisplayMetricsLocked(false));
2420                mSystemContext = context;
2421                //Slog.i(TAG, "Created system resources " + context.getResources()
2422                //        + ": " + context.getResources().getConfiguration());
2423            }
2424        }
2425        return mSystemContext;
2426    }
2427
2428    public void installSystemApplicationInfo(ApplicationInfo info) {
2429        synchronized (this) {
2430            ContextImpl context = getSystemContext();
2431            context.init(new PackageInfo(this, "android", context, info), null, this);
2432        }
2433    }
2434
2435    void ensureJitEnabled() {
2436        if (!mJitEnabled) {
2437            mJitEnabled = true;
2438            dalvik.system.VMRuntime.getRuntime().startJitCompilation();
2439        }
2440    }
2441
2442    void scheduleGcIdler() {
2443        if (!mGcIdlerScheduled) {
2444            mGcIdlerScheduled = true;
2445            Looper.myQueue().addIdleHandler(mGcIdler);
2446        }
2447        mH.removeMessages(H.GC_WHEN_IDLE);
2448    }
2449
2450    void unscheduleGcIdler() {
2451        if (mGcIdlerScheduled) {
2452            mGcIdlerScheduled = false;
2453            Looper.myQueue().removeIdleHandler(mGcIdler);
2454        }
2455        mH.removeMessages(H.GC_WHEN_IDLE);
2456    }
2457
2458    void doGcIfNeeded() {
2459        mGcIdlerScheduled = false;
2460        final long now = SystemClock.uptimeMillis();
2461        //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
2462        //        + "m now=" + now);
2463        if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
2464            //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!");
2465            BinderInternal.forceGc("bg");
2466        }
2467    }
2468
2469    public final ActivityInfo resolveActivityInfo(Intent intent) {
2470        ActivityInfo aInfo = intent.resolveActivityInfo(
2471                mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
2472        if (aInfo == null) {
2473            // Throw an exception.
2474            Instrumentation.checkStartActivityResult(
2475                    IActivityManager.START_CLASS_NOT_FOUND, intent);
2476        }
2477        return aInfo;
2478    }
2479
2480    public final Activity startActivityNow(Activity parent, String id,
2481        Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
2482        Object lastNonConfigurationInstance) {
2483        ActivityRecord r = new ActivityRecord();
2484            r.token = token;
2485            r.ident = 0;
2486            r.intent = intent;
2487            r.state = state;
2488            r.parent = parent;
2489            r.embeddedID = id;
2490            r.activityInfo = activityInfo;
2491            r.lastNonConfigurationInstance = lastNonConfigurationInstance;
2492        if (localLOGV) {
2493            ComponentName compname = intent.getComponent();
2494            String name;
2495            if (compname != null) {
2496                name = compname.toShortString();
2497            } else {
2498                name = "(Intent " + intent + ").getComponent() returned null";
2499            }
2500            Slog.v(TAG, "Performing launch: action=" + intent.getAction()
2501                    + ", comp=" + name
2502                    + ", token=" + token);
2503        }
2504        return performLaunchActivity(r, null);
2505    }
2506
2507    public final Activity getActivity(IBinder token) {
2508        return mActivities.get(token).activity;
2509    }
2510
2511    public final void sendActivityResult(
2512            IBinder token, String id, int requestCode,
2513            int resultCode, Intent data) {
2514        if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id
2515                + " req=" + requestCode + " res=" + resultCode + " data=" + data);
2516        ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
2517        list.add(new ResultInfo(id, requestCode, resultCode, data));
2518        mAppThread.scheduleSendResult(token, list);
2519    }
2520
2521    // if the thread hasn't started yet, we don't have the handler, so just
2522    // save the messages until we're ready.
2523    private final void queueOrSendMessage(int what, Object obj) {
2524        queueOrSendMessage(what, obj, 0, 0);
2525    }
2526
2527    private final void queueOrSendMessage(int what, Object obj, int arg1) {
2528        queueOrSendMessage(what, obj, arg1, 0);
2529    }
2530
2531    private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
2532        synchronized (this) {
2533            if (localLOGV) Slog.v(
2534                TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
2535                + ": " + arg1 + " / " + obj);
2536            Message msg = Message.obtain();
2537            msg.what = what;
2538            msg.obj = obj;
2539            msg.arg1 = arg1;
2540            msg.arg2 = arg2;
2541            mH.sendMessage(msg);
2542        }
2543    }
2544
2545    final void scheduleContextCleanup(ContextImpl context, String who,
2546            String what) {
2547        ContextCleanupInfo cci = new ContextCleanupInfo();
2548        cci.context = context;
2549        cci.who = who;
2550        cci.what = what;
2551        queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
2552    }
2553
2554    private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {
2555        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
2556
2557        ActivityInfo aInfo = r.activityInfo;
2558        if (r.packageInfo == null) {
2559            r.packageInfo = getPackageInfo(aInfo.applicationInfo,
2560                    Context.CONTEXT_INCLUDE_CODE);
2561        }
2562
2563        ComponentName component = r.intent.getComponent();
2564        if (component == null) {
2565            component = r.intent.resolveActivity(
2566                mInitialApplication.getPackageManager());
2567            r.intent.setComponent(component);
2568        }
2569
2570        if (r.activityInfo.targetActivity != null) {
2571            component = new ComponentName(r.activityInfo.packageName,
2572                    r.activityInfo.targetActivity);
2573        }
2574
2575        Activity activity = null;
2576        try {
2577            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
2578            activity = mInstrumentation.newActivity(
2579                    cl, component.getClassName(), r.intent);
2580            r.intent.setExtrasClassLoader(cl);
2581            if (r.state != null) {
2582                r.state.setClassLoader(cl);
2583            }
2584        } catch (Exception e) {
2585            if (!mInstrumentation.onException(activity, e)) {
2586                throw new RuntimeException(
2587                    "Unable to instantiate activity " + component
2588                    + ": " + e.toString(), e);
2589            }
2590        }
2591
2592        try {
2593            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
2594
2595            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
2596            if (localLOGV) Slog.v(
2597                    TAG, r + ": app=" + app
2598                    + ", appName=" + app.getPackageName()
2599                    + ", pkg=" + r.packageInfo.getPackageName()
2600                    + ", comp=" + r.intent.getComponent().toShortString()
2601                    + ", dir=" + r.packageInfo.getAppDir());
2602
2603            if (activity != null) {
2604                ContextImpl appContext = new ContextImpl();
2605                appContext.init(r.packageInfo, r.token, this);
2606                appContext.setOuterContext(activity);
2607                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
2608                Configuration config = new Configuration(mConfiguration);
2609                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
2610                        + r.activityInfo.name + " with config " + config);
2611                activity.attach(appContext, this, getInstrumentation(), r.token,
2612                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
2613                        r.embeddedID, r.lastNonConfigurationInstance,
2614                        r.lastNonConfigurationChildInstances, config);
2615
2616                if (customIntent != null) {
2617                    activity.mIntent = customIntent;
2618                }
2619                r.lastNonConfigurationInstance = null;
2620                r.lastNonConfigurationChildInstances = null;
2621                activity.mStartedActivity = false;
2622                int theme = r.activityInfo.getThemeResource();
2623                if (theme != 0) {
2624                    activity.setTheme(theme);
2625                }
2626
2627                activity.mCalled = false;
2628                mInstrumentation.callActivityOnCreate(activity, r.state);
2629                if (!activity.mCalled) {
2630                    throw new SuperNotCalledException(
2631                        "Activity " + r.intent.getComponent().toShortString() +
2632                        " did not call through to super.onCreate()");
2633                }
2634                r.activity = activity;
2635                r.stopped = true;
2636                if (!r.activity.mFinished) {
2637                    activity.performStart();
2638                    r.stopped = false;
2639                }
2640                if (!r.activity.mFinished) {
2641                    if (r.state != null) {
2642                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
2643                    }
2644                }
2645                if (!r.activity.mFinished) {
2646                    activity.mCalled = false;
2647                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
2648                    if (!activity.mCalled) {
2649                        throw new SuperNotCalledException(
2650                            "Activity " + r.intent.getComponent().toShortString() +
2651                            " did not call through to super.onPostCreate()");
2652                    }
2653                }
2654            }
2655            r.paused = true;
2656
2657            mActivities.put(r.token, r);
2658
2659        } catch (SuperNotCalledException e) {
2660            throw e;
2661
2662        } catch (Exception e) {
2663            if (!mInstrumentation.onException(activity, e)) {
2664                throw new RuntimeException(
2665                    "Unable to start activity " + component
2666                    + ": " + e.toString(), e);
2667            }
2668        }
2669
2670        return activity;
2671    }
2672
2673    private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
2674        // If we are getting ready to gc after going to the background, well
2675        // we are back active so skip it.
2676        unscheduleGcIdler();
2677
2678        if (localLOGV) Slog.v(
2679            TAG, "Handling launch of " + r);
2680        Activity a = performLaunchActivity(r, customIntent);
2681
2682        if (a != null) {
2683            r.createdConfig = new Configuration(mConfiguration);
2684            Bundle oldState = r.state;
2685            handleResumeActivity(r.token, false, r.isForward);
2686
2687            if (!r.activity.mFinished && r.startsNotResumed) {
2688                // The activity manager actually wants this one to start out
2689                // paused, because it needs to be visible but isn't in the
2690                // foreground.  We accomplish this by going through the
2691                // normal startup (because activities expect to go through
2692                // onResume() the first time they run, before their window
2693                // is displayed), and then pausing it.  However, in this case
2694                // we do -not- need to do the full pause cycle (of freezing
2695                // and such) because the activity manager assumes it can just
2696                // retain the current state it has.
2697                try {
2698                    r.activity.mCalled = false;
2699                    mInstrumentation.callActivityOnPause(r.activity);
2700                    // We need to keep around the original state, in case
2701                    // we need to be created again.
2702                    r.state = oldState;
2703                    if (!r.activity.mCalled) {
2704                        throw new SuperNotCalledException(
2705                            "Activity " + r.intent.getComponent().toShortString() +
2706                            " did not call through to super.onPause()");
2707                    }
2708
2709                } catch (SuperNotCalledException e) {
2710                    throw e;
2711
2712                } catch (Exception e) {
2713                    if (!mInstrumentation.onException(r.activity, e)) {
2714                        throw new RuntimeException(
2715                                "Unable to pause activity "
2716                                + r.intent.getComponent().toShortString()
2717                                + ": " + e.toString(), e);
2718                    }
2719                }
2720                r.paused = true;
2721            }
2722        } else {
2723            // If there was an error, for any reason, tell the activity
2724            // manager to stop us.
2725            try {
2726                ActivityManagerNative.getDefault()
2727                    .finishActivity(r.token, Activity.RESULT_CANCELED, null);
2728            } catch (RemoteException ex) {
2729            }
2730        }
2731    }
2732
2733    private final void deliverNewIntents(ActivityRecord r,
2734            List<Intent> intents) {
2735        final int N = intents.size();
2736        for (int i=0; i<N; i++) {
2737            Intent intent = intents.get(i);
2738            intent.setExtrasClassLoader(r.activity.getClassLoader());
2739            mInstrumentation.callActivityOnNewIntent(r.activity, intent);
2740        }
2741    }
2742
2743    public final void performNewIntents(IBinder token,
2744            List<Intent> intents) {
2745        ActivityRecord r = mActivities.get(token);
2746        if (r != null) {
2747            final boolean resumed = !r.paused;
2748            if (resumed) {
2749                mInstrumentation.callActivityOnPause(r.activity);
2750            }
2751            deliverNewIntents(r, intents);
2752            if (resumed) {
2753                mInstrumentation.callActivityOnResume(r.activity);
2754            }
2755        }
2756    }
2757
2758    private final void handleNewIntent(NewIntentData data) {
2759        performNewIntents(data.token, data.intents);
2760    }
2761
2762    private final void handleReceiver(ReceiverData data) {
2763        // If we are getting ready to gc after going to the background, well
2764        // we are back active so skip it.
2765        unscheduleGcIdler();
2766
2767        String component = data.intent.getComponent().getClassName();
2768
2769        PackageInfo packageInfo = getPackageInfoNoCheck(
2770                data.info.applicationInfo);
2771
2772        IActivityManager mgr = ActivityManagerNative.getDefault();
2773
2774        BroadcastReceiver receiver = null;
2775        try {
2776            java.lang.ClassLoader cl = packageInfo.getClassLoader();
2777            data.intent.setExtrasClassLoader(cl);
2778            if (data.resultExtras != null) {
2779                data.resultExtras.setClassLoader(cl);
2780            }
2781            receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
2782        } catch (Exception e) {
2783            try {
2784                if (DEBUG_BROADCAST) Slog.i(TAG,
2785                        "Finishing failed broadcast to " + data.intent.getComponent());
2786                mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
2787                                   data.resultData, data.resultExtras, data.resultAbort);
2788            } catch (RemoteException ex) {
2789            }
2790            throw new RuntimeException(
2791                "Unable to instantiate receiver " + component
2792                + ": " + e.toString(), e);
2793        }
2794
2795        try {
2796            Application app = packageInfo.makeApplication(false, mInstrumentation);
2797
2798            if (localLOGV) Slog.v(
2799                TAG, "Performing receive of " + data.intent
2800                + ": app=" + app
2801                + ", appName=" + app.getPackageName()
2802                + ", pkg=" + packageInfo.getPackageName()
2803                + ", comp=" + data.intent.getComponent().toShortString()
2804                + ", dir=" + packageInfo.getAppDir());
2805
2806            ContextImpl context = (ContextImpl)app.getBaseContext();
2807            receiver.setOrderedHint(true);
2808            receiver.setResult(data.resultCode, data.resultData,
2809                data.resultExtras);
2810            receiver.setOrderedHint(data.sync);
2811            receiver.onReceive(context.getReceiverRestrictedContext(),
2812                    data.intent);
2813        } catch (Exception e) {
2814            try {
2815                if (DEBUG_BROADCAST) Slog.i(TAG,
2816                        "Finishing failed broadcast to " + data.intent.getComponent());
2817                mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
2818                    data.resultData, data.resultExtras, data.resultAbort);
2819            } catch (RemoteException ex) {
2820            }
2821            if (!mInstrumentation.onException(receiver, e)) {
2822                throw new RuntimeException(
2823                    "Unable to start receiver " + component
2824                    + ": " + e.toString(), e);
2825            }
2826        }
2827
2828        try {
2829            if (data.sync) {
2830                if (DEBUG_BROADCAST) Slog.i(TAG,
2831                        "Finishing ordered broadcast to " + data.intent.getComponent());
2832                mgr.finishReceiver(
2833                    mAppThread.asBinder(), receiver.getResultCode(),
2834                    receiver.getResultData(), receiver.getResultExtras(false),
2835                        receiver.getAbortBroadcast());
2836            } else {
2837                if (DEBUG_BROADCAST) Slog.i(TAG,
2838                        "Finishing broadcast to " + data.intent.getComponent());
2839                mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false);
2840            }
2841        } catch (RemoteException ex) {
2842        }
2843    }
2844
2845    // Instantiate a BackupAgent and tell it that it's alive
2846    private final void handleCreateBackupAgent(CreateBackupAgentData data) {
2847        if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
2848
2849        // no longer idle; we have backup work to do
2850        unscheduleGcIdler();
2851
2852        // instantiate the BackupAgent class named in the manifest
2853        PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
2854        String packageName = packageInfo.mPackageName;
2855        if (mBackupAgents.get(packageName) != null) {
2856            Slog.d(TAG, "BackupAgent " + "  for " + packageName
2857                    + " already exists");
2858            return;
2859        }
2860
2861        BackupAgent agent = null;
2862        String classname = data.appInfo.backupAgentName;
2863        if (classname == null) {
2864            if (data.backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL) {
2865                Slog.e(TAG, "Attempted incremental backup but no defined agent for "
2866                        + packageName);
2867                return;
2868            }
2869            classname = "android.app.FullBackupAgent";
2870        }
2871        try {
2872            IBinder binder = null;
2873            try {
2874                java.lang.ClassLoader cl = packageInfo.getClassLoader();
2875                agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance();
2876
2877                // set up the agent's context
2878                if (DEBUG_BACKUP) Slog.v(TAG, "Initializing BackupAgent "
2879                        + data.appInfo.backupAgentName);
2880
2881                ContextImpl context = new ContextImpl();
2882                context.init(packageInfo, null, this);
2883                context.setOuterContext(agent);
2884                agent.attach(context);
2885
2886                agent.onCreate();
2887                binder = agent.onBind();
2888                mBackupAgents.put(packageName, agent);
2889            } catch (Exception e) {
2890                // If this is during restore, fail silently; otherwise go
2891                // ahead and let the user see the crash.
2892                Slog.e(TAG, "Agent threw during creation: " + e);
2893                if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE) {
2894                    throw e;
2895                }
2896                // falling through with 'binder' still null
2897            }
2898
2899            // tell the OS that we're live now
2900            try {
2901                ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
2902            } catch (RemoteException e) {
2903                // nothing to do.
2904            }
2905        } catch (Exception e) {
2906            throw new RuntimeException("Unable to create BackupAgent "
2907                    + data.appInfo.backupAgentName + ": " + e.toString(), e);
2908        }
2909    }
2910
2911    // Tear down a BackupAgent
2912    private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
2913        if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
2914
2915        PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
2916        String packageName = packageInfo.mPackageName;
2917        BackupAgent agent = mBackupAgents.get(packageName);
2918        if (agent != null) {
2919            try {
2920                agent.onDestroy();
2921            } catch (Exception e) {
2922                Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
2923                e.printStackTrace();
2924            }
2925            mBackupAgents.remove(packageName);
2926        } else {
2927            Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
2928        }
2929    }
2930
2931    private final void handleCreateService(CreateServiceData data) {
2932        // If we are getting ready to gc after going to the background, well
2933        // we are back active so skip it.
2934        unscheduleGcIdler();
2935
2936        PackageInfo packageInfo = getPackageInfoNoCheck(
2937                data.info.applicationInfo);
2938        Service service = null;
2939        try {
2940            java.lang.ClassLoader cl = packageInfo.getClassLoader();
2941            service = (Service) cl.loadClass(data.info.name).newInstance();
2942        } catch (Exception e) {
2943            if (!mInstrumentation.onException(service, e)) {
2944                throw new RuntimeException(
2945                    "Unable to instantiate service " + data.info.name
2946                    + ": " + e.toString(), e);
2947            }
2948        }
2949
2950        try {
2951            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
2952
2953            ContextImpl context = new ContextImpl();
2954            context.init(packageInfo, null, this);
2955
2956            Application app = packageInfo.makeApplication(false, mInstrumentation);
2957            context.setOuterContext(service);
2958            service.attach(context, this, data.info.name, data.token, app,
2959                    ActivityManagerNative.getDefault());
2960            service.onCreate();
2961            mServices.put(data.token, service);
2962            try {
2963                ActivityManagerNative.getDefault().serviceDoneExecuting(
2964                        data.token, 0, 0, 0);
2965            } catch (RemoteException e) {
2966                // nothing to do.
2967            }
2968        } catch (Exception e) {
2969            if (!mInstrumentation.onException(service, e)) {
2970                throw new RuntimeException(
2971                    "Unable to create service " + data.info.name
2972                    + ": " + e.toString(), e);
2973            }
2974        }
2975    }
2976
2977    private final void handleBindService(BindServiceData data) {
2978        Service s = mServices.get(data.token);
2979        if (s != null) {
2980            try {
2981                data.intent.setExtrasClassLoader(s.getClassLoader());
2982                try {
2983                    if (!data.rebind) {
2984                        IBinder binder = s.onBind(data.intent);
2985                        ActivityManagerNative.getDefault().publishService(
2986                                data.token, data.intent, binder);
2987                    } else {
2988                        s.onRebind(data.intent);
2989                        ActivityManagerNative.getDefault().serviceDoneExecuting(
2990                                data.token, 0, 0, 0);
2991                    }
2992                    ensureJitEnabled();
2993                } catch (RemoteException ex) {
2994                }
2995            } catch (Exception e) {
2996                if (!mInstrumentation.onException(s, e)) {
2997                    throw new RuntimeException(
2998                            "Unable to bind to service " + s
2999                            + " with " + data.intent + ": " + e.toString(), e);
3000                }
3001            }
3002        }
3003    }
3004
3005    private final void handleUnbindService(BindServiceData data) {
3006        Service s = mServices.get(data.token);
3007        if (s != null) {
3008            try {
3009                data.intent.setExtrasClassLoader(s.getClassLoader());
3010                boolean doRebind = s.onUnbind(data.intent);
3011                try {
3012                    if (doRebind) {
3013                        ActivityManagerNative.getDefault().unbindFinished(
3014                                data.token, data.intent, doRebind);
3015                    } else {
3016                        ActivityManagerNative.getDefault().serviceDoneExecuting(
3017                                data.token, 0, 0, 0);
3018                    }
3019                } catch (RemoteException ex) {
3020                }
3021            } catch (Exception e) {
3022                if (!mInstrumentation.onException(s, e)) {
3023                    throw new RuntimeException(
3024                            "Unable to unbind to service " + s
3025                            + " with " + data.intent + ": " + e.toString(), e);
3026                }
3027            }
3028        }
3029    }
3030
3031    private void handleDumpService(DumpServiceInfo info) {
3032        try {
3033            Service s = mServices.get(info.service);
3034            if (s != null) {
3035                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
3036                s.dump(info.fd, pw, info.args);
3037                pw.close();
3038            }
3039        } finally {
3040            synchronized (info) {
3041                info.dumped = true;
3042                info.notifyAll();
3043            }
3044        }
3045    }
3046
3047    private final void handleServiceArgs(ServiceArgsData data) {
3048        Service s = mServices.get(data.token);
3049        if (s != null) {
3050            try {
3051                if (data.args != null) {
3052                    data.args.setExtrasClassLoader(s.getClassLoader());
3053                }
3054                int res = s.onStartCommand(data.args, data.flags, data.startId);
3055                try {
3056                    ActivityManagerNative.getDefault().serviceDoneExecuting(
3057                            data.token, 1, data.startId, res);
3058                } catch (RemoteException e) {
3059                    // nothing to do.
3060                }
3061                ensureJitEnabled();
3062            } catch (Exception e) {
3063                if (!mInstrumentation.onException(s, e)) {
3064                    throw new RuntimeException(
3065                            "Unable to start service " + s
3066                            + " with " + data.args + ": " + e.toString(), e);
3067                }
3068            }
3069        }
3070    }
3071
3072    private final void handleStopService(IBinder token) {
3073        Service s = mServices.remove(token);
3074        if (s != null) {
3075            try {
3076                if (localLOGV) Slog.v(TAG, "Destroying service " + s);
3077                s.onDestroy();
3078                Context context = s.getBaseContext();
3079                if (context instanceof ContextImpl) {
3080                    final String who = s.getClassName();
3081                    ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
3082                }
3083                try {
3084                    ActivityManagerNative.getDefault().serviceDoneExecuting(
3085                            token, 0, 0, 0);
3086                } catch (RemoteException e) {
3087                    // nothing to do.
3088                }
3089            } catch (Exception e) {
3090                if (!mInstrumentation.onException(s, e)) {
3091                    throw new RuntimeException(
3092                            "Unable to stop service " + s
3093                            + ": " + e.toString(), e);
3094                }
3095            }
3096        }
3097        //Slog.i(TAG, "Running services: " + mServices);
3098    }
3099
3100    public final ActivityRecord performResumeActivity(IBinder token,
3101            boolean clearHide) {
3102        ActivityRecord r = mActivities.get(token);
3103        if (localLOGV) Slog.v(TAG, "Performing resume of " + r
3104                + " finished=" + r.activity.mFinished);
3105        if (r != null && !r.activity.mFinished) {
3106            if (clearHide) {
3107                r.hideForNow = false;
3108                r.activity.mStartedActivity = false;
3109            }
3110            try {
3111                if (r.pendingIntents != null) {
3112                    deliverNewIntents(r, r.pendingIntents);
3113                    r.pendingIntents = null;
3114                }
3115                if (r.pendingResults != null) {
3116                    deliverResults(r, r.pendingResults);
3117                    r.pendingResults = null;
3118                }
3119                r.activity.performResume();
3120
3121                EventLog.writeEvent(LOG_ON_RESUME_CALLED,
3122                        r.activity.getComponentName().getClassName());
3123
3124                r.paused = false;
3125                r.stopped = false;
3126                r.state = null;
3127            } catch (Exception e) {
3128                if (!mInstrumentation.onException(r.activity, e)) {
3129                    throw new RuntimeException(
3130                        "Unable to resume activity "
3131                        + r.intent.getComponent().toShortString()
3132                        + ": " + e.toString(), e);
3133                }
3134            }
3135        }
3136        return r;
3137    }
3138
3139    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
3140        // If we are getting ready to gc after going to the background, well
3141        // we are back active so skip it.
3142        unscheduleGcIdler();
3143
3144        ActivityRecord r = performResumeActivity(token, clearHide);
3145
3146        if (r != null) {
3147            final Activity a = r.activity;
3148
3149            if (localLOGV) Slog.v(
3150                TAG, "Resume " + r + " started activity: " +
3151                a.mStartedActivity + ", hideForNow: " + r.hideForNow
3152                + ", finished: " + a.mFinished);
3153
3154            final int forwardBit = isForward ?
3155                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
3156
3157            // If the window hasn't yet been added to the window manager,
3158            // and this guy didn't finish itself or start another activity,
3159            // then go ahead and add the window.
3160            boolean willBeVisible = !a.mStartedActivity;
3161            if (!willBeVisible) {
3162                try {
3163                    willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
3164                            a.getActivityToken());
3165                } catch (RemoteException e) {
3166                }
3167            }
3168            if (r.window == null && !a.mFinished && willBeVisible) {
3169                r.window = r.activity.getWindow();
3170                View decor = r.window.getDecorView();
3171                decor.setVisibility(View.INVISIBLE);
3172                ViewManager wm = a.getWindowManager();
3173                WindowManager.LayoutParams l = r.window.getAttributes();
3174                a.mDecor = decor;
3175                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
3176                l.softInputMode |= forwardBit;
3177                if (a.mVisibleFromClient) {
3178                    a.mWindowAdded = true;
3179                    wm.addView(decor, l);
3180                }
3181
3182            // If the window has already been added, but during resume
3183            // we started another activity, then don't yet make the
3184            // window visible.
3185            } else if (!willBeVisible) {
3186                if (localLOGV) Slog.v(
3187                    TAG, "Launch " + r + " mStartedActivity set");
3188                r.hideForNow = true;
3189            }
3190
3191            // The window is now visible if it has been added, we are not
3192            // simply finishing, and we are not starting another activity.
3193            if (!r.activity.mFinished && willBeVisible
3194                    && r.activity.mDecor != null && !r.hideForNow) {
3195                if (r.newConfig != null) {
3196                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
3197                            + r.activityInfo.name + " with newConfig " + r.newConfig);
3198                    performConfigurationChanged(r.activity, r.newConfig);
3199                    r.newConfig = null;
3200                }
3201                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
3202                        + isForward);
3203                WindowManager.LayoutParams l = r.window.getAttributes();
3204                if ((l.softInputMode
3205                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
3206                        != forwardBit) {
3207                    l.softInputMode = (l.softInputMode
3208                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
3209                            | forwardBit;
3210                    if (r.activity.mVisibleFromClient) {
3211                        ViewManager wm = a.getWindowManager();
3212                        View decor = r.window.getDecorView();
3213                        wm.updateViewLayout(decor, l);
3214                    }
3215                }
3216                r.activity.mVisibleFromServer = true;
3217                mNumVisibleActivities++;
3218                if (r.activity.mVisibleFromClient) {
3219                    r.activity.makeVisible();
3220                }
3221            }
3222
3223            r.nextIdle = mNewActivities;
3224            mNewActivities = r;
3225            if (localLOGV) Slog.v(
3226                TAG, "Scheduling idle handler for " + r);
3227            Looper.myQueue().addIdleHandler(new Idler());
3228
3229        } else {
3230            // If an exception was thrown when trying to resume, then
3231            // just end this activity.
3232            try {
3233                ActivityManagerNative.getDefault()
3234                    .finishActivity(token, Activity.RESULT_CANCELED, null);
3235            } catch (RemoteException ex) {
3236            }
3237        }
3238    }
3239
3240    private int mThumbnailWidth = -1;
3241    private int mThumbnailHeight = -1;
3242
3243    private final Bitmap createThumbnailBitmap(ActivityRecord r) {
3244        Bitmap thumbnail = null;
3245        try {
3246            int w = mThumbnailWidth;
3247            int h;
3248            if (w < 0) {
3249                Resources res = r.activity.getResources();
3250                mThumbnailHeight = h =
3251                    res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
3252
3253                mThumbnailWidth = w =
3254                    res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
3255            } else {
3256                h = mThumbnailHeight;
3257            }
3258
3259            // XXX Only set hasAlpha if needed?
3260            thumbnail = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
3261            thumbnail.eraseColor(0);
3262            Canvas cv = new Canvas(thumbnail);
3263            if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
3264                thumbnail = null;
3265            }
3266        } catch (Exception e) {
3267            if (!mInstrumentation.onException(r.activity, e)) {
3268                throw new RuntimeException(
3269                        "Unable to create thumbnail of "
3270                        + r.intent.getComponent().toShortString()
3271                        + ": " + e.toString(), e);
3272            }
3273            thumbnail = null;
3274        }
3275
3276        return thumbnail;
3277    }
3278
3279    private final void handlePauseActivity(IBinder token, boolean finished,
3280            boolean userLeaving, int configChanges) {
3281        ActivityRecord r = mActivities.get(token);
3282        if (r != null) {
3283            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
3284            if (userLeaving) {
3285                performUserLeavingActivity(r);
3286            }
3287
3288            r.activity.mConfigChangeFlags |= configChanges;
3289            Bundle state = performPauseActivity(token, finished, true);
3290
3291            // Tell the activity manager we have paused.
3292            try {
3293                ActivityManagerNative.getDefault().activityPaused(token, state);
3294            } catch (RemoteException ex) {
3295            }
3296        }
3297    }
3298
3299    final void performUserLeavingActivity(ActivityRecord r) {
3300        mInstrumentation.callActivityOnUserLeaving(r.activity);
3301    }
3302
3303    final Bundle performPauseActivity(IBinder token, boolean finished,
3304            boolean saveState) {
3305        ActivityRecord r = mActivities.get(token);
3306        return r != null ? performPauseActivity(r, finished, saveState) : null;
3307    }
3308
3309    final Bundle performPauseActivity(ActivityRecord r, boolean finished,
3310            boolean saveState) {
3311        if (r.paused) {
3312            if (r.activity.mFinished) {
3313                // If we are finishing, we won't call onResume() in certain cases.
3314                // So here we likewise don't want to call onPause() if the activity
3315                // isn't resumed.
3316                return null;
3317            }
3318            RuntimeException e = new RuntimeException(
3319                    "Performing pause of activity that is not resumed: "
3320                    + r.intent.getComponent().toShortString());
3321            Slog.e(TAG, e.getMessage(), e);
3322        }
3323        Bundle state = null;
3324        if (finished) {
3325            r.activity.mFinished = true;
3326        }
3327        try {
3328            // Next have the activity save its current state and managed dialogs...
3329            if (!r.activity.mFinished && saveState) {
3330                state = new Bundle();
3331                mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
3332                r.state = state;
3333            }
3334            // Now we are idle.
3335            r.activity.mCalled = false;
3336            mInstrumentation.callActivityOnPause(r.activity);
3337            EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
3338            if (!r.activity.mCalled) {
3339                throw new SuperNotCalledException(
3340                    "Activity " + r.intent.getComponent().toShortString() +
3341                    " did not call through to super.onPause()");
3342            }
3343
3344        } catch (SuperNotCalledException e) {
3345            throw e;
3346
3347        } catch (Exception e) {
3348            if (!mInstrumentation.onException(r.activity, e)) {
3349                throw new RuntimeException(
3350                        "Unable to pause activity "
3351                        + r.intent.getComponent().toShortString()
3352                        + ": " + e.toString(), e);
3353            }
3354        }
3355        r.paused = true;
3356        return state;
3357    }
3358
3359    final void performStopActivity(IBinder token) {
3360        ActivityRecord r = mActivities.get(token);
3361        performStopActivityInner(r, null, false);
3362    }
3363
3364    private static class StopInfo {
3365        Bitmap thumbnail;
3366        CharSequence description;
3367    }
3368
3369    private final class ProviderRefCount {
3370        public int count;
3371        ProviderRefCount(int pCount) {
3372            count = pCount;
3373        }
3374    }
3375
3376    private final void performStopActivityInner(ActivityRecord r,
3377            StopInfo info, boolean keepShown) {
3378        if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
3379        if (r != null) {
3380            if (!keepShown && r.stopped) {
3381                if (r.activity.mFinished) {
3382                    // If we are finishing, we won't call onResume() in certain
3383                    // cases.  So here we likewise don't want to call onStop()
3384                    // if the activity isn't resumed.
3385                    return;
3386                }
3387                RuntimeException e = new RuntimeException(
3388                        "Performing stop of activity that is not resumed: "
3389                        + r.intent.getComponent().toShortString());
3390                Slog.e(TAG, e.getMessage(), e);
3391            }
3392
3393            if (info != null) {
3394                try {
3395                    // First create a thumbnail for the activity...
3396                    //info.thumbnail = createThumbnailBitmap(r);
3397                    info.description = r.activity.onCreateDescription();
3398                } catch (Exception e) {
3399                    if (!mInstrumentation.onException(r.activity, e)) {
3400                        throw new RuntimeException(
3401                                "Unable to save state of activity "
3402                                + r.intent.getComponent().toShortString()
3403                                + ": " + e.toString(), e);
3404                    }
3405                }
3406            }
3407
3408            if (!keepShown) {
3409                try {
3410                    // Now we are idle.
3411                    r.activity.performStop();
3412                } catch (Exception e) {
3413                    if (!mInstrumentation.onException(r.activity, e)) {
3414                        throw new RuntimeException(
3415                                "Unable to stop activity "
3416                                + r.intent.getComponent().toShortString()
3417                                + ": " + e.toString(), e);
3418                    }
3419                }
3420                r.stopped = true;
3421            }
3422
3423            r.paused = true;
3424        }
3425    }
3426
3427    private final void updateVisibility(ActivityRecord r, boolean show) {
3428        View v = r.activity.mDecor;
3429        if (v != null) {
3430            if (show) {
3431                if (!r.activity.mVisibleFromServer) {
3432                    r.activity.mVisibleFromServer = true;
3433                    mNumVisibleActivities++;
3434                    if (r.activity.mVisibleFromClient) {
3435                        r.activity.makeVisible();
3436                    }
3437                }
3438                if (r.newConfig != null) {
3439                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
3440                            + r.activityInfo.name + " with new config " + r.newConfig);
3441                    performConfigurationChanged(r.activity, r.newConfig);
3442                    r.newConfig = null;
3443                }
3444            } else {
3445                if (r.activity.mVisibleFromServer) {
3446                    r.activity.mVisibleFromServer = false;
3447                    mNumVisibleActivities--;
3448                    v.setVisibility(View.INVISIBLE);
3449                }
3450            }
3451        }
3452    }
3453
3454    private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
3455        ActivityRecord r = mActivities.get(token);
3456        r.activity.mConfigChangeFlags |= configChanges;
3457
3458        StopInfo info = new StopInfo();
3459        performStopActivityInner(r, info, show);
3460
3461        if (localLOGV) Slog.v(
3462            TAG, "Finishing stop of " + r + ": show=" + show
3463            + " win=" + r.window);
3464
3465        updateVisibility(r, show);
3466
3467        // Tell activity manager we have been stopped.
3468        try {
3469            ActivityManagerNative.getDefault().activityStopped(
3470                r.token, info.thumbnail, info.description);
3471        } catch (RemoteException ex) {
3472        }
3473    }
3474
3475    final void performRestartActivity(IBinder token) {
3476        ActivityRecord r = mActivities.get(token);
3477        if (r.stopped) {
3478            r.activity.performRestart();
3479            r.stopped = false;
3480        }
3481    }
3482
3483    private final void handleWindowVisibility(IBinder token, boolean show) {
3484        ActivityRecord r = mActivities.get(token);
3485        if (!show && !r.stopped) {
3486            performStopActivityInner(r, null, show);
3487        } else if (show && r.stopped) {
3488            // If we are getting ready to gc after going to the background, well
3489            // we are back active so skip it.
3490            unscheduleGcIdler();
3491
3492            r.activity.performRestart();
3493            r.stopped = false;
3494        }
3495        if (r.activity.mDecor != null) {
3496            if (Config.LOGV) Slog.v(
3497                TAG, "Handle window " + r + " visibility: " + show);
3498            updateVisibility(r, show);
3499        }
3500    }
3501
3502    private final void deliverResults(ActivityRecord r, List<ResultInfo> results) {
3503        final int N = results.size();
3504        for (int i=0; i<N; i++) {
3505            ResultInfo ri = results.get(i);
3506            try {
3507                if (ri.mData != null) {
3508                    ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
3509                }
3510                if (DEBUG_RESULTS) Slog.v(TAG,
3511                        "Delivering result to activity " + r + " : " + ri);
3512                r.activity.dispatchActivityResult(ri.mResultWho,
3513                        ri.mRequestCode, ri.mResultCode, ri.mData);
3514            } catch (Exception e) {
3515                if (!mInstrumentation.onException(r.activity, e)) {
3516                    throw new RuntimeException(
3517                            "Failure delivering result " + ri + " to activity "
3518                            + r.intent.getComponent().toShortString()
3519                            + ": " + e.toString(), e);
3520                }
3521            }
3522        }
3523    }
3524
3525    private final void handleSendResult(ResultData res) {
3526        ActivityRecord r = mActivities.get(res.token);
3527        if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
3528        if (r != null) {
3529            final boolean resumed = !r.paused;
3530            if (!r.activity.mFinished && r.activity.mDecor != null
3531                    && r.hideForNow && resumed) {
3532                // We had hidden the activity because it started another
3533                // one...  we have gotten a result back and we are not
3534                // paused, so make sure our window is visible.
3535                updateVisibility(r, true);
3536            }
3537            if (resumed) {
3538                try {
3539                    // Now we are idle.
3540                    r.activity.mCalled = false;
3541                    mInstrumentation.callActivityOnPause(r.activity);
3542                    if (!r.activity.mCalled) {
3543                        throw new SuperNotCalledException(
3544                            "Activity " + r.intent.getComponent().toShortString()
3545                            + " did not call through to super.onPause()");
3546                    }
3547                } catch (SuperNotCalledException e) {
3548                    throw e;
3549                } catch (Exception e) {
3550                    if (!mInstrumentation.onException(r.activity, e)) {
3551                        throw new RuntimeException(
3552                                "Unable to pause activity "
3553                                + r.intent.getComponent().toShortString()
3554                                + ": " + e.toString(), e);
3555                    }
3556                }
3557            }
3558            deliverResults(r, res.results);
3559            if (resumed) {
3560                mInstrumentation.callActivityOnResume(r.activity);
3561            }
3562        }
3563    }
3564
3565    public final ActivityRecord performDestroyActivity(IBinder token, boolean finishing) {
3566        return performDestroyActivity(token, finishing, 0, false);
3567    }
3568
3569    private final ActivityRecord performDestroyActivity(IBinder token, boolean finishing,
3570            int configChanges, boolean getNonConfigInstance) {
3571        ActivityRecord r = mActivities.get(token);
3572        if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
3573        if (r != null) {
3574            r.activity.mConfigChangeFlags |= configChanges;
3575            if (finishing) {
3576                r.activity.mFinished = true;
3577            }
3578            if (getNonConfigInstance) {
3579                r.activity.mChangingConfigurations = true;
3580            }
3581            if (!r.paused) {
3582                try {
3583                    r.activity.mCalled = false;
3584                    mInstrumentation.callActivityOnPause(r.activity);
3585                    EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
3586                            r.activity.getComponentName().getClassName());
3587                    if (!r.activity.mCalled) {
3588                        throw new SuperNotCalledException(
3589                            "Activity " + safeToComponentShortString(r.intent)
3590                            + " did not call through to super.onPause()");
3591                    }
3592                } catch (SuperNotCalledException e) {
3593                    throw e;
3594                } catch (Exception e) {
3595                    if (!mInstrumentation.onException(r.activity, e)) {
3596                        throw new RuntimeException(
3597                                "Unable to pause activity "
3598                                + safeToComponentShortString(r.intent)
3599                                + ": " + e.toString(), e);
3600                    }
3601                }
3602                r.paused = true;
3603            }
3604            if (!r.stopped) {
3605                try {
3606                    r.activity.performStop();
3607                } catch (SuperNotCalledException e) {
3608                    throw e;
3609                } catch (Exception e) {
3610                    if (!mInstrumentation.onException(r.activity, e)) {
3611                        throw new RuntimeException(
3612                                "Unable to stop activity "
3613                                + safeToComponentShortString(r.intent)
3614                                + ": " + e.toString(), e);
3615                    }
3616                }
3617                r.stopped = true;
3618            }
3619            if (getNonConfigInstance) {
3620                try {
3621                    r.lastNonConfigurationInstance
3622                            = r.activity.onRetainNonConfigurationInstance();
3623                } catch (Exception e) {
3624                    if (!mInstrumentation.onException(r.activity, e)) {
3625                        throw new RuntimeException(
3626                                "Unable to retain activity "
3627                                + r.intent.getComponent().toShortString()
3628                                + ": " + e.toString(), e);
3629                    }
3630                }
3631                try {
3632                    r.lastNonConfigurationChildInstances
3633                            = r.activity.onRetainNonConfigurationChildInstances();
3634                } catch (Exception e) {
3635                    if (!mInstrumentation.onException(r.activity, e)) {
3636                        throw new RuntimeException(
3637                                "Unable to retain child activities "
3638                                + safeToComponentShortString(r.intent)
3639                                + ": " + e.toString(), e);
3640                    }
3641                }
3642
3643            }
3644            try {
3645                r.activity.mCalled = false;
3646                mInstrumentation.callActivityOnDestroy(r.activity);
3647                if (!r.activity.mCalled) {
3648                    throw new SuperNotCalledException(
3649                        "Activity " + safeToComponentShortString(r.intent) +
3650                        " did not call through to super.onDestroy()");
3651                }
3652                if (r.window != null) {
3653                    r.window.closeAllPanels();
3654                }
3655            } catch (SuperNotCalledException e) {
3656                throw e;
3657            } catch (Exception e) {
3658                if (!mInstrumentation.onException(r.activity, e)) {
3659                    throw new RuntimeException(
3660                            "Unable to destroy activity " + safeToComponentShortString(r.intent)
3661                            + ": " + e.toString(), e);
3662                }
3663            }
3664        }
3665        mActivities.remove(token);
3666
3667        return r;
3668    }
3669
3670    private static String safeToComponentShortString(Intent intent) {
3671        ComponentName component = intent.getComponent();
3672        return component == null ? "[Unknown]" : component.toShortString();
3673    }
3674
3675    private final void handleDestroyActivity(IBinder token, boolean finishing,
3676            int configChanges, boolean getNonConfigInstance) {
3677        ActivityRecord r = performDestroyActivity(token, finishing,
3678                configChanges, getNonConfigInstance);
3679        if (r != null) {
3680            WindowManager wm = r.activity.getWindowManager();
3681            View v = r.activity.mDecor;
3682            if (v != null) {
3683                if (r.activity.mVisibleFromServer) {
3684                    mNumVisibleActivities--;
3685                }
3686                IBinder wtoken = v.getWindowToken();
3687                if (r.activity.mWindowAdded) {
3688                    wm.removeViewImmediate(v);
3689                }
3690                if (wtoken != null) {
3691                    WindowManagerImpl.getDefault().closeAll(wtoken,
3692                            r.activity.getClass().getName(), "Activity");
3693                }
3694                r.activity.mDecor = null;
3695            }
3696            WindowManagerImpl.getDefault().closeAll(token,
3697                    r.activity.getClass().getName(), "Activity");
3698
3699            // Mocked out contexts won't be participating in the normal
3700            // process lifecycle, but if we're running with a proper
3701            // ApplicationContext we need to have it tear down things
3702            // cleanly.
3703            Context c = r.activity.getBaseContext();
3704            if (c instanceof ContextImpl) {
3705                ((ContextImpl) c).scheduleFinalCleanup(
3706                        r.activity.getClass().getName(), "Activity");
3707            }
3708        }
3709        if (finishing) {
3710            try {
3711                ActivityManagerNative.getDefault().activityDestroyed(token);
3712            } catch (RemoteException ex) {
3713                // If the system process has died, it's game over for everyone.
3714            }
3715        }
3716    }
3717
3718    private final void handleRelaunchActivity(ActivityRecord tmp, int configChanges) {
3719        // If we are getting ready to gc after going to the background, well
3720        // we are back active so skip it.
3721        unscheduleGcIdler();
3722
3723        Configuration changedConfig = null;
3724
3725        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
3726                + tmp.token + " with configChanges=0x"
3727                + Integer.toHexString(configChanges));
3728
3729        // First: make sure we have the most recent configuration and most
3730        // recent version of the activity, or skip it if some previous call
3731        // had taken a more recent version.
3732        synchronized (mPackages) {
3733            int N = mRelaunchingActivities.size();
3734            IBinder token = tmp.token;
3735            tmp = null;
3736            for (int i=0; i<N; i++) {
3737                ActivityRecord r = mRelaunchingActivities.get(i);
3738                if (r.token == token) {
3739                    tmp = r;
3740                    mRelaunchingActivities.remove(i);
3741                    i--;
3742                    N--;
3743                }
3744            }
3745
3746            if (tmp == null) {
3747                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
3748                return;
3749            }
3750
3751            if (mPendingConfiguration != null) {
3752                changedConfig = mPendingConfiguration;
3753                mPendingConfiguration = null;
3754            }
3755        }
3756
3757        if (tmp.createdConfig != null) {
3758            // If the activity manager is passing us its current config,
3759            // assume that is really what we want regardless of what we
3760            // may have pending.
3761            if (mConfiguration == null
3762                    || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
3763                            && mConfiguration.diff(tmp.createdConfig) != 0)) {
3764                if (changedConfig == null
3765                        || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
3766                    changedConfig = tmp.createdConfig;
3767                }
3768            }
3769        }
3770
3771        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
3772                + tmp.token + ": changedConfig=" + changedConfig);
3773
3774        // If there was a pending configuration change, execute it first.
3775        if (changedConfig != null) {
3776            handleConfigurationChanged(changedConfig);
3777        }
3778
3779        ActivityRecord r = mActivities.get(tmp.token);
3780        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
3781        if (r == null) {
3782            return;
3783        }
3784
3785        r.activity.mConfigChangeFlags |= configChanges;
3786        Intent currentIntent = r.activity.mIntent;
3787
3788        Bundle savedState = null;
3789        if (!r.paused) {
3790            savedState = performPauseActivity(r.token, false, true);
3791        }
3792
3793        handleDestroyActivity(r.token, false, configChanges, true);
3794
3795        r.activity = null;
3796        r.window = null;
3797        r.hideForNow = false;
3798        r.nextIdle = null;
3799        // Merge any pending results and pending intents; don't just replace them
3800        if (tmp.pendingResults != null) {
3801            if (r.pendingResults == null) {
3802                r.pendingResults = tmp.pendingResults;
3803            } else {
3804                r.pendingResults.addAll(tmp.pendingResults);
3805            }
3806        }
3807        if (tmp.pendingIntents != null) {
3808            if (r.pendingIntents == null) {
3809                r.pendingIntents = tmp.pendingIntents;
3810            } else {
3811                r.pendingIntents.addAll(tmp.pendingIntents);
3812            }
3813        }
3814        r.startsNotResumed = tmp.startsNotResumed;
3815        if (savedState != null) {
3816            r.state = savedState;
3817        }
3818
3819        handleLaunchActivity(r, currentIntent);
3820    }
3821
3822    private final void handleRequestThumbnail(IBinder token) {
3823        ActivityRecord r = mActivities.get(token);
3824        Bitmap thumbnail = createThumbnailBitmap(r);
3825        CharSequence description = null;
3826        try {
3827            description = r.activity.onCreateDescription();
3828        } catch (Exception e) {
3829            if (!mInstrumentation.onException(r.activity, e)) {
3830                throw new RuntimeException(
3831                        "Unable to create description of activity "
3832                        + r.intent.getComponent().toShortString()
3833                        + ": " + e.toString(), e);
3834            }
3835        }
3836        //System.out.println("Reporting top thumbnail " + thumbnail);
3837        try {
3838            ActivityManagerNative.getDefault().reportThumbnail(
3839                token, thumbnail, description);
3840        } catch (RemoteException ex) {
3841        }
3842    }
3843
3844    ArrayList<ComponentCallbacks> collectComponentCallbacksLocked(
3845            boolean allActivities, Configuration newConfig) {
3846        ArrayList<ComponentCallbacks> callbacks
3847                = new ArrayList<ComponentCallbacks>();
3848
3849        if (mActivities.size() > 0) {
3850            Iterator<ActivityRecord> it = mActivities.values().iterator();
3851            while (it.hasNext()) {
3852                ActivityRecord ar = it.next();
3853                Activity a = ar.activity;
3854                if (a != null) {
3855                    if (!ar.activity.mFinished && (allActivities ||
3856                            (a != null && !ar.paused))) {
3857                        // If the activity is currently resumed, its configuration
3858                        // needs to change right now.
3859                        callbacks.add(a);
3860                    } else if (newConfig != null) {
3861                        // Otherwise, we will tell it about the change
3862                        // the next time it is resumed or shown.  Note that
3863                        // the activity manager may, before then, decide the
3864                        // activity needs to be destroyed to handle its new
3865                        // configuration.
3866                        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Setting activity "
3867                                + ar.activityInfo.name + " newConfig=" + newConfig);
3868                        ar.newConfig = newConfig;
3869                    }
3870                }
3871            }
3872        }
3873        if (mServices.size() > 0) {
3874            Iterator<Service> it = mServices.values().iterator();
3875            while (it.hasNext()) {
3876                callbacks.add(it.next());
3877            }
3878        }
3879        synchronized (mProviderMap) {
3880            if (mLocalProviders.size() > 0) {
3881                Iterator<ProviderRecord> it = mLocalProviders.values().iterator();
3882                while (it.hasNext()) {
3883                    callbacks.add(it.next().mLocalProvider);
3884                }
3885            }
3886        }
3887        final int N = mAllApplications.size();
3888        for (int i=0; i<N; i++) {
3889            callbacks.add(mAllApplications.get(i));
3890        }
3891
3892        return callbacks;
3893    }
3894
3895    private final void performConfigurationChanged(
3896            ComponentCallbacks cb, Configuration config) {
3897        // Only for Activity objects, check that they actually call up to their
3898        // superclass implementation.  ComponentCallbacks is an interface, so
3899        // we check the runtime type and act accordingly.
3900        Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
3901        if (activity != null) {
3902            activity.mCalled = false;
3903        }
3904
3905        boolean shouldChangeConfig = false;
3906        if ((activity == null) || (activity.mCurrentConfig == null)) {
3907            shouldChangeConfig = true;
3908        } else {
3909
3910            // If the new config is the same as the config this Activity
3911            // is already running with then don't bother calling
3912            // onConfigurationChanged
3913            int diff = activity.mCurrentConfig.diff(config);
3914            if (diff != 0) {
3915
3916                // If this activity doesn't handle any of the config changes
3917                // then don't bother calling onConfigurationChanged as we're
3918                // going to destroy it.
3919                if ((~activity.mActivityInfo.configChanges & diff) == 0) {
3920                    shouldChangeConfig = true;
3921                }
3922            }
3923        }
3924
3925        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
3926                + ": shouldChangeConfig=" + shouldChangeConfig);
3927        if (shouldChangeConfig) {
3928            cb.onConfigurationChanged(config);
3929
3930            if (activity != null) {
3931                if (!activity.mCalled) {
3932                    throw new SuperNotCalledException(
3933                            "Activity " + activity.getLocalClassName() +
3934                        " did not call through to super.onConfigurationChanged()");
3935                }
3936                activity.mConfigChangeFlags = 0;
3937                activity.mCurrentConfig = new Configuration(config);
3938            }
3939        }
3940    }
3941
3942    final boolean applyConfigurationToResourcesLocked(Configuration config) {
3943        if (mResConfiguration == null) {
3944            mResConfiguration = new Configuration();
3945        }
3946        if (!mResConfiguration.isOtherSeqNewer(config)) {
3947            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
3948                    + mResConfiguration.seq + ", newSeq=" + config.seq);
3949            return false;
3950        }
3951        int changes = mResConfiguration.updateFrom(config);
3952        DisplayMetrics dm = getDisplayMetricsLocked(true);
3953
3954        // set it for java, this also affects newly created Resources
3955        if (config.locale != null) {
3956            Locale.setDefault(config.locale);
3957        }
3958
3959        Resources.updateSystemConfiguration(config, dm);
3960
3961        ContextImpl.ApplicationPackageManager.configurationChanged();
3962        //Slog.i(TAG, "Configuration changed in " + currentPackageName());
3963
3964        Iterator<WeakReference<Resources>> it =
3965            mActiveResources.values().iterator();
3966        //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
3967        //    mActiveResources.entrySet().iterator();
3968        while (it.hasNext()) {
3969            WeakReference<Resources> v = it.next();
3970            Resources r = v.get();
3971            if (r != null) {
3972                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
3973                        + r + " config to: " + config);
3974                r.updateConfiguration(config, dm);
3975                //Slog.i(TAG, "Updated app resources " + v.getKey()
3976                //        + " " + r + ": " + r.getConfiguration());
3977            } else {
3978                //Slog.i(TAG, "Removing old resources " + v.getKey());
3979                it.remove();
3980            }
3981        }
3982
3983        return changes != 0;
3984    }
3985
3986    final void handleConfigurationChanged(Configuration config) {
3987
3988        ArrayList<ComponentCallbacks> callbacks = null;
3989
3990        synchronized (mPackages) {
3991            if (mPendingConfiguration != null) {
3992                if (!mPendingConfiguration.isOtherSeqNewer(config)) {
3993                    config = mPendingConfiguration;
3994                }
3995                mPendingConfiguration = null;
3996            }
3997
3998            if (config == null) {
3999                return;
4000            }
4001
4002            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
4003                    + config);
4004
4005            applyConfigurationToResourcesLocked(config);
4006
4007            if (mConfiguration == null) {
4008                mConfiguration = new Configuration();
4009            }
4010            if (!mConfiguration.isOtherSeqNewer(config)) {
4011                return;
4012            }
4013            mConfiguration.updateFrom(config);
4014
4015            callbacks = collectComponentCallbacksLocked(false, config);
4016        }
4017
4018        if (callbacks != null) {
4019            final int N = callbacks.size();
4020            for (int i=0; i<N; i++) {
4021                performConfigurationChanged(callbacks.get(i), config);
4022            }
4023        }
4024    }
4025
4026    final void handleActivityConfigurationChanged(IBinder token) {
4027        ActivityRecord r = mActivities.get(token);
4028        if (r == null || r.activity == null) {
4029            return;
4030        }
4031
4032        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
4033                + r.activityInfo.name);
4034
4035        performConfigurationChanged(r.activity, mConfiguration);
4036    }
4037
4038    final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
4039        if (start) {
4040            try {
4041                Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
4042                        8 * 1024 * 1024, 0);
4043            } catch (RuntimeException e) {
4044                Slog.w(TAG, "Profiling failed on path " + pcd.path
4045                        + " -- can the process access this path?");
4046            } finally {
4047                try {
4048                    pcd.fd.close();
4049                } catch (IOException e) {
4050                    Slog.w(TAG, "Failure closing profile fd", e);
4051                }
4052            }
4053        } else {
4054            Debug.stopMethodTracing();
4055        }
4056    }
4057
4058    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
4059        boolean hasPkgInfo = false;
4060        if (packages != null) {
4061            for (int i=packages.length-1; i>=0; i--) {
4062                //Slog.i(TAG, "Cleaning old package: " + packages[i]);
4063                if (!hasPkgInfo) {
4064                    WeakReference<PackageInfo> ref;
4065                    ref = mPackages.get(packages[i]);
4066                    if (ref != null && ref.get() != null) {
4067                        hasPkgInfo = true;
4068                    } else {
4069                        ref = mResourcePackages.get(packages[i]);
4070                        if (ref != null && ref.get() != null) {
4071                            hasPkgInfo = true;
4072                        }
4073                    }
4074                }
4075                mPackages.remove(packages[i]);
4076                mResourcePackages.remove(packages[i]);
4077            }
4078        }
4079        ContextImpl.ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
4080                hasPkgInfo);
4081    }
4082
4083    final void handleLowMemory() {
4084        ArrayList<ComponentCallbacks> callbacks
4085                = new ArrayList<ComponentCallbacks>();
4086
4087        synchronized (mPackages) {
4088            callbacks = collectComponentCallbacksLocked(true, null);
4089        }
4090
4091        final int N = callbacks.size();
4092        for (int i=0; i<N; i++) {
4093            callbacks.get(i).onLowMemory();
4094        }
4095
4096        // Ask SQLite to free up as much memory as it can, mostly from its page caches.
4097        if (Process.myUid() != Process.SYSTEM_UID) {
4098            int sqliteReleased = SQLiteDatabase.releaseMemory();
4099            EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
4100        }
4101
4102        // Ask graphics to free up as much as possible (font/image caches)
4103        Canvas.freeCaches();
4104
4105        BinderInternal.forceGc("mem");
4106    }
4107
4108    private final void handleBindApplication(AppBindData data) {
4109        mBoundApplication = data;
4110        mConfiguration = new Configuration(data.config);
4111
4112        // send up app name; do this *before* waiting for debugger
4113        Process.setArgV0(data.processName);
4114        android.ddm.DdmHandleAppName.setAppName(data.processName);
4115
4116        /*
4117         * Before spawning a new process, reset the time zone to be the system time zone.
4118         * This needs to be done because the system time zone could have changed after the
4119         * the spawning of this process. Without doing this this process would have the incorrect
4120         * system time zone.
4121         */
4122        TimeZone.setDefault(null);
4123
4124        /*
4125         * Initialize the default locale in this process for the reasons we set the time zone.
4126         */
4127        Locale.setDefault(data.config.locale);
4128
4129        /*
4130         * Update the system configuration since its preloaded and might not
4131         * reflect configuration changes. The configuration object passed
4132         * in AppBindData can be safely assumed to be up to date
4133         */
4134        Resources.getSystem().updateConfiguration(mConfiguration, null);
4135
4136        data.info = getPackageInfoNoCheck(data.appInfo);
4137
4138        /**
4139         * Switch this process to density compatibility mode if needed.
4140         */
4141        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
4142                == 0) {
4143            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
4144        }
4145
4146        if (data.debugMode != IApplicationThread.DEBUG_OFF) {
4147            // XXX should have option to change the port.
4148            Debug.changeDebugPort(8100);
4149            if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
4150                Slog.w(TAG, "Application " + data.info.getPackageName()
4151                      + " is waiting for the debugger on port 8100...");
4152
4153                IActivityManager mgr = ActivityManagerNative.getDefault();
4154                try {
4155                    mgr.showWaitingForDebugger(mAppThread, true);
4156                } catch (RemoteException ex) {
4157                }
4158
4159                Debug.waitForDebugger();
4160
4161                try {
4162                    mgr.showWaitingForDebugger(mAppThread, false);
4163                } catch (RemoteException ex) {
4164                }
4165
4166            } else {
4167                Slog.w(TAG, "Application " + data.info.getPackageName()
4168                      + " can be debugged on port 8100...");
4169            }
4170        }
4171
4172        if (data.instrumentationName != null) {
4173            ContextImpl appContext = new ContextImpl();
4174            appContext.init(data.info, null, this);
4175            InstrumentationInfo ii = null;
4176            try {
4177                ii = appContext.getPackageManager().
4178                    getInstrumentationInfo(data.instrumentationName, 0);
4179            } catch (PackageManager.NameNotFoundException e) {
4180            }
4181            if (ii == null) {
4182                throw new RuntimeException(
4183                    "Unable to find instrumentation info for: "
4184                    + data.instrumentationName);
4185            }
4186
4187            mInstrumentationAppDir = ii.sourceDir;
4188            mInstrumentationAppPackage = ii.packageName;
4189            mInstrumentedAppDir = data.info.getAppDir();
4190
4191            ApplicationInfo instrApp = new ApplicationInfo();
4192            instrApp.packageName = ii.packageName;
4193            instrApp.sourceDir = ii.sourceDir;
4194            instrApp.publicSourceDir = ii.publicSourceDir;
4195            instrApp.dataDir = ii.dataDir;
4196            PackageInfo pi = getPackageInfo(instrApp,
4197                    appContext.getClassLoader(), false, true);
4198            ContextImpl instrContext = new ContextImpl();
4199            instrContext.init(pi, null, this);
4200
4201            try {
4202                java.lang.ClassLoader cl = instrContext.getClassLoader();
4203                mInstrumentation = (Instrumentation)
4204                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
4205            } catch (Exception e) {
4206                throw new RuntimeException(
4207                    "Unable to instantiate instrumentation "
4208                    + data.instrumentationName + ": " + e.toString(), e);
4209            }
4210
4211            mInstrumentation.init(this, instrContext, appContext,
4212                    new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
4213
4214            if (data.profileFile != null && !ii.handleProfiling) {
4215                data.handlingProfiling = true;
4216                File file = new File(data.profileFile);
4217                file.getParentFile().mkdirs();
4218                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
4219            }
4220
4221            try {
4222                mInstrumentation.onCreate(data.instrumentationArgs);
4223            }
4224            catch (Exception e) {
4225                throw new RuntimeException(
4226                    "Exception thrown in onCreate() of "
4227                    + data.instrumentationName + ": " + e.toString(), e);
4228            }
4229
4230        } else {
4231            mInstrumentation = new Instrumentation();
4232        }
4233
4234        // If the app is being launched for full backup or restore, bring it up in
4235        // a restricted environment with the base application class.
4236        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
4237        mInitialApplication = app;
4238
4239        List<ProviderInfo> providers = data.providers;
4240        if (providers != null) {
4241            installContentProviders(app, providers);
4242            // For process that contain content providers, we want to
4243            // ensure that the JIT is enabled "at some point".
4244            mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
4245        }
4246
4247        try {
4248            mInstrumentation.callApplicationOnCreate(app);
4249        } catch (Exception e) {
4250            if (!mInstrumentation.onException(app, e)) {
4251                throw new RuntimeException(
4252                    "Unable to create application " + app.getClass().getName()
4253                    + ": " + e.toString(), e);
4254            }
4255        }
4256    }
4257
4258    /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
4259        IActivityManager am = ActivityManagerNative.getDefault();
4260        if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) {
4261            Debug.stopMethodTracing();
4262        }
4263        //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault()
4264        //      + ", app thr: " + mAppThread);
4265        try {
4266            am.finishInstrumentation(mAppThread, resultCode, results);
4267        } catch (RemoteException ex) {
4268        }
4269    }
4270
4271    private final void installContentProviders(
4272            Context context, List<ProviderInfo> providers) {
4273        final ArrayList<IActivityManager.ContentProviderHolder> results =
4274            new ArrayList<IActivityManager.ContentProviderHolder>();
4275
4276        Iterator<ProviderInfo> i = providers.iterator();
4277        while (i.hasNext()) {
4278            ProviderInfo cpi = i.next();
4279            StringBuilder buf = new StringBuilder(128);
4280            buf.append("Publishing provider ");
4281            buf.append(cpi.authority);
4282            buf.append(": ");
4283            buf.append(cpi.name);
4284            Log.i(TAG, buf.toString());
4285            IContentProvider cp = installProvider(context, null, cpi, false);
4286            if (cp != null) {
4287                IActivityManager.ContentProviderHolder cph =
4288                    new IActivityManager.ContentProviderHolder(cpi);
4289                cph.provider = cp;
4290                results.add(cph);
4291                // Don't ever unload this provider from the process.
4292                synchronized(mProviderMap) {
4293                    mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
4294                }
4295            }
4296        }
4297
4298        try {
4299            ActivityManagerNative.getDefault().publishContentProviders(
4300                getApplicationThread(), results);
4301        } catch (RemoteException ex) {
4302        }
4303    }
4304
4305    private final IContentProvider getProvider(Context context, String name) {
4306        synchronized(mProviderMap) {
4307            final ProviderRecord pr = mProviderMap.get(name);
4308            if (pr != null) {
4309                return pr.mProvider;
4310            }
4311        }
4312
4313        IActivityManager.ContentProviderHolder holder = null;
4314        try {
4315            holder = ActivityManagerNative.getDefault().getContentProvider(
4316                getApplicationThread(), name);
4317        } catch (RemoteException ex) {
4318        }
4319        if (holder == null) {
4320            Slog.e(TAG, "Failed to find provider info for " + name);
4321            return null;
4322        }
4323        if (holder.permissionFailure != null) {
4324            throw new SecurityException("Permission " + holder.permissionFailure
4325                    + " required for provider " + name);
4326        }
4327
4328        IContentProvider prov = installProvider(context, holder.provider,
4329                holder.info, true);
4330        //Slog.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
4331        if (holder.noReleaseNeeded || holder.provider == null) {
4332            // We are not going to release the provider if it is an external
4333            // provider that doesn't care about being released, or if it is
4334            // a local provider running in this process.
4335            //Slog.i(TAG, "*** NO RELEASE NEEDED");
4336            synchronized(mProviderMap) {
4337                mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
4338            }
4339        }
4340        return prov;
4341    }
4342
4343    public final IContentProvider acquireProvider(Context c, String name) {
4344        IContentProvider provider = getProvider(c, name);
4345        if(provider == null)
4346            return null;
4347        IBinder jBinder = provider.asBinder();
4348        synchronized(mProviderMap) {
4349            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4350            if(prc == null) {
4351                mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
4352            } else {
4353                prc.count++;
4354            } //end else
4355        } //end synchronized
4356        return provider;
4357    }
4358
4359    public final boolean releaseProvider(IContentProvider provider) {
4360        if(provider == null) {
4361            return false;
4362        }
4363        IBinder jBinder = provider.asBinder();
4364        synchronized(mProviderMap) {
4365            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4366            if(prc == null) {
4367                if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldnt be here");
4368                return false;
4369            } else {
4370                prc.count--;
4371                if(prc.count == 0) {
4372                    // Schedule the actual remove asynchronously, since we
4373                    // don't know the context this will be called in.
4374                    // TODO: it would be nice to post a delayed message, so
4375                    // if we come back and need the same provider quickly
4376                    // we will still have it available.
4377                    Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
4378                    mH.sendMessage(msg);
4379                } //end if
4380            } //end else
4381        } //end synchronized
4382        return true;
4383    }
4384
4385    final void completeRemoveProvider(IContentProvider provider) {
4386        IBinder jBinder = provider.asBinder();
4387        String name = null;
4388        synchronized(mProviderMap) {
4389            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4390            if(prc != null && prc.count == 0) {
4391                mProviderRefCountMap.remove(jBinder);
4392                //invoke removeProvider to dereference provider
4393                name = removeProviderLocked(provider);
4394            }
4395        }
4396
4397        if (name != null) {
4398            try {
4399                if(localLOGV) Slog.v(TAG, "removeProvider::Invoking " +
4400                        "ActivityManagerNative.removeContentProvider(" + name);
4401                ActivityManagerNative.getDefault().removeContentProvider(
4402                        getApplicationThread(), name);
4403            } catch (RemoteException e) {
4404                //do nothing content provider object is dead any way
4405            } //end catch
4406        }
4407    }
4408
4409    public final String removeProviderLocked(IContentProvider provider) {
4410        if (provider == null) {
4411            return null;
4412        }
4413        IBinder providerBinder = provider.asBinder();
4414
4415        String name = null;
4416
4417        // remove the provider from mProviderMap
4418        Iterator<ProviderRecord> iter = mProviderMap.values().iterator();
4419        while (iter.hasNext()) {
4420            ProviderRecord pr = iter.next();
4421            IBinder myBinder = pr.mProvider.asBinder();
4422            if (myBinder == providerBinder) {
4423                //find if its published by this process itself
4424                if(pr.mLocalProvider != null) {
4425                    if(localLOGV) Slog.i(TAG, "removeProvider::found local provider returning");
4426                    return name;
4427                }
4428                if(localLOGV) Slog.v(TAG, "removeProvider::Not local provider Unlinking " +
4429                        "death recipient");
4430                //content provider is in another process
4431                myBinder.unlinkToDeath(pr, 0);
4432                iter.remove();
4433                //invoke remove only once for the very first name seen
4434                if(name == null) {
4435                    name = pr.mName;
4436                }
4437            } //end if myBinder
4438        }  //end while iter
4439
4440        return name;
4441    }
4442
4443    final void removeDeadProvider(String name, IContentProvider provider) {
4444        synchronized(mProviderMap) {
4445            ProviderRecord pr = mProviderMap.get(name);
4446            if (pr.mProvider.asBinder() == provider.asBinder()) {
4447                Slog.i(TAG, "Removing dead content provider: " + name);
4448                ProviderRecord removed = mProviderMap.remove(name);
4449                if (removed != null) {
4450                    removed.mProvider.asBinder().unlinkToDeath(removed, 0);
4451                }
4452            }
4453        }
4454    }
4455
4456    final void removeDeadProviderLocked(String name, IContentProvider provider) {
4457        ProviderRecord pr = mProviderMap.get(name);
4458        if (pr.mProvider.asBinder() == provider.asBinder()) {
4459            Slog.i(TAG, "Removing dead content provider: " + name);
4460            ProviderRecord removed = mProviderMap.remove(name);
4461            if (removed != null) {
4462                removed.mProvider.asBinder().unlinkToDeath(removed, 0);
4463            }
4464        }
4465    }
4466
4467    private final IContentProvider installProvider(Context context,
4468            IContentProvider provider, ProviderInfo info, boolean noisy) {
4469        ContentProvider localProvider = null;
4470        if (provider == null) {
4471            if (noisy) {
4472                Slog.d(TAG, "Loading provider " + info.authority + ": "
4473                        + info.name);
4474            }
4475            Context c = null;
4476            ApplicationInfo ai = info.applicationInfo;
4477            if (context.getPackageName().equals(ai.packageName)) {
4478                c = context;
4479            } else if (mInitialApplication != null &&
4480                    mInitialApplication.getPackageName().equals(ai.packageName)) {
4481                c = mInitialApplication;
4482            } else {
4483                try {
4484                    c = context.createPackageContext(ai.packageName,
4485                            Context.CONTEXT_INCLUDE_CODE);
4486                } catch (PackageManager.NameNotFoundException e) {
4487                }
4488            }
4489            if (c == null) {
4490                Slog.w(TAG, "Unable to get context for package " +
4491                      ai.packageName +
4492                      " while loading content provider " +
4493                      info.name);
4494                return null;
4495            }
4496            try {
4497                final java.lang.ClassLoader cl = c.getClassLoader();
4498                localProvider = (ContentProvider)cl.
4499                    loadClass(info.name).newInstance();
4500                provider = localProvider.getIContentProvider();
4501                if (provider == null) {
4502                    Slog.e(TAG, "Failed to instantiate class " +
4503                          info.name + " from sourceDir " +
4504                          info.applicationInfo.sourceDir);
4505                    return null;
4506                }
4507                if (Config.LOGV) Slog.v(
4508                    TAG, "Instantiating local provider " + info.name);
4509                // XXX Need to create the correct context for this provider.
4510                localProvider.attachInfo(c, info);
4511            } catch (java.lang.Exception e) {
4512                if (!mInstrumentation.onException(null, e)) {
4513                    throw new RuntimeException(
4514                            "Unable to get provider " + info.name
4515                            + ": " + e.toString(), e);
4516                }
4517                return null;
4518            }
4519        } else if (localLOGV) {
4520            Slog.v(TAG, "Installing external provider " + info.authority + ": "
4521                    + info.name);
4522        }
4523
4524        synchronized (mProviderMap) {
4525            // Cache the pointer for the remote provider.
4526            String names[] = PATTERN_SEMICOLON.split(info.authority);
4527            for (int i=0; i<names.length; i++) {
4528                ProviderRecord pr = new ProviderRecord(names[i], provider,
4529                        localProvider);
4530                try {
4531                    provider.asBinder().linkToDeath(pr, 0);
4532                    mProviderMap.put(names[i], pr);
4533                } catch (RemoteException e) {
4534                    return null;
4535                }
4536            }
4537            if (localProvider != null) {
4538                mLocalProviders.put(provider.asBinder(),
4539                        new ProviderRecord(null, provider, localProvider));
4540            }
4541        }
4542
4543        return provider;
4544    }
4545
4546    private final void attach(boolean system) {
4547        sThreadLocal.set(this);
4548        mSystemThread = system;
4549        if (!system) {
4550            ViewRoot.addFirstDrawHandler(new Runnable() {
4551                public void run() {
4552                    ensureJitEnabled();
4553                }
4554            });
4555            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
4556            RuntimeInit.setApplicationObject(mAppThread.asBinder());
4557            IActivityManager mgr = ActivityManagerNative.getDefault();
4558            try {
4559                mgr.attachApplication(mAppThread);
4560            } catch (RemoteException ex) {
4561            }
4562        } else {
4563            // Don't set application object here -- if the system crashes,
4564            // we can't display an alert, we just want to die die die.
4565            android.ddm.DdmHandleAppName.setAppName("system_process");
4566            try {
4567                mInstrumentation = new Instrumentation();
4568                ContextImpl context = new ContextImpl();
4569                context.init(getSystemContext().mPackageInfo, null, this);
4570                Application app = Instrumentation.newApplication(Application.class, context);
4571                mAllApplications.add(app);
4572                mInitialApplication = app;
4573                app.onCreate();
4574            } catch (Exception e) {
4575                throw new RuntimeException(
4576                        "Unable to instantiate Application():" + e.toString(), e);
4577            }
4578        }
4579
4580        ViewRoot.addConfigCallback(new ComponentCallbacks() {
4581            public void onConfigurationChanged(Configuration newConfig) {
4582                synchronized (mPackages) {
4583                    // We need to apply this change to the resources
4584                    // immediately, because upon returning the view
4585                    // hierarchy will be informed about it.
4586                    if (applyConfigurationToResourcesLocked(newConfig)) {
4587                        // This actually changed the resources!  Tell
4588                        // everyone about it.
4589                        if (mPendingConfiguration == null ||
4590                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
4591                            mPendingConfiguration = newConfig;
4592
4593                            queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
4594                        }
4595                    }
4596                }
4597            }
4598            public void onLowMemory() {
4599            }
4600        });
4601    }
4602
4603    private final void detach()
4604    {
4605        sThreadLocal.set(null);
4606    }
4607
4608    public static final ActivityThread systemMain() {
4609        ActivityThread thread = new ActivityThread();
4610        thread.attach(true);
4611        return thread;
4612    }
4613
4614    public final void installSystemProviders(List providers) {
4615        if (providers != null) {
4616            installContentProviders(mInitialApplication,
4617                                    (List<ProviderInfo>)providers);
4618        }
4619    }
4620
4621    public static final void main(String[] args) {
4622        SamplingProfilerIntegration.start();
4623
4624        Process.setArgV0("<pre-initialized>");
4625
4626        Looper.prepareMainLooper();
4627
4628        ActivityThread thread = new ActivityThread();
4629        thread.attach(false);
4630
4631        Looper.loop();
4632
4633        if (Process.supportsProcesses()) {
4634            throw new RuntimeException("Main thread loop unexpectedly exited");
4635        }
4636
4637        thread.detach();
4638        String name = (thread.mInitialApplication != null)
4639            ? thread.mInitialApplication.getPackageName()
4640            : "<unknown>";
4641        Slog.i(TAG, "Main thread of " + name + " is now exiting");
4642    }
4643}
4644