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