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