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