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