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