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