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