OSDN Git Service

Defuse Bundles parsed by the system process.
[android-x86/frameworks-base.git] / core / java / android / app / LoadedApk.java
1 /*
2  * Copyright (C) 2010 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.text.TextUtils;
20 import android.util.ArrayMap;
21 import android.content.BroadcastReceiver;
22 import android.content.ComponentName;
23 import android.content.Context;
24 import android.content.IIntentReceiver;
25 import android.content.Intent;
26 import android.content.ServiceConnection;
27 import android.content.pm.ApplicationInfo;
28 import android.content.pm.IPackageManager;
29 import android.content.pm.PackageManager;
30 import android.content.res.AssetManager;
31 import android.content.res.CompatibilityInfo;
32 import android.content.res.Resources;
33 import android.os.Bundle;
34 import android.os.FileUtils;
35 import android.os.Handler;
36 import android.os.IBinder;
37 import android.os.Process;
38 import android.os.RemoteException;
39 import android.os.StrictMode;
40 import android.os.Trace;
41 import android.os.UserHandle;
42 import android.util.AndroidRuntimeException;
43 import android.util.Log;
44 import android.util.Slog;
45 import android.util.SparseArray;
46 import android.view.DisplayAdjustments;
47 import android.view.Display;
48 import android.os.SystemProperties;
49
50 import dalvik.system.VMRuntime;
51
52 import java.io.File;
53 import java.io.IOException;
54 import java.io.InputStream;
55 import java.lang.ref.WeakReference;
56 import java.lang.reflect.InvocationTargetException;
57 import java.lang.reflect.Method;
58 import java.net.URL;
59 import java.util.List;
60 import java.util.ArrayList;
61 import java.util.Arrays;
62 import java.util.Collections;
63 import java.util.Enumeration;
64 import java.util.Objects;
65
66 final class IntentReceiverLeaked extends AndroidRuntimeException {
67     public IntentReceiverLeaked(String msg) {
68         super(msg);
69     }
70 }
71
72 final class ServiceConnectionLeaked extends AndroidRuntimeException {
73     public ServiceConnectionLeaked(String msg) {
74         super(msg);
75     }
76 }
77
78 /**
79  * Local state maintained about a currently loaded .apk.
80  * @hide
81  */
82 public final class LoadedApk {
83
84     private static final String TAG = "LoadedApk";
85
86     private final ActivityThread mActivityThread;
87     final String mPackageName;
88     private ApplicationInfo mApplicationInfo;
89     private String mAppDir;
90     private String mResDir;
91     private String[] mSplitAppDirs;
92     private String[] mSplitResDirs;
93     private String[] mOverlayDirs;
94     private String[] mSharedLibraries;
95     private String mDataDir;
96     private String mLibDir;
97     private File mDataDirFile;
98     private File mDeviceEncryptedDataDirFile;
99     private File mCredentialEncryptedDataDirFile;
100     private final ClassLoader mBaseClassLoader;
101     private final boolean mSecurityViolation;
102     private final boolean mIncludeCode;
103     private final boolean mRegisterPackage;
104     private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
105     /** WARNING: This may change. Don't hold external references to it. */
106     Resources mResources;
107     private ClassLoader mClassLoader;
108     private Application mApplication;
109
110     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
111         = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
112     private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
113         = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
114     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
115         = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
116     private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
117         = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
118
119     int mClientCount = 0;
120
121     Application getApplication() {
122         return mApplication;
123     }
124
125     /**
126      * Create information about a new .apk
127      *
128      * NOTE: This constructor is called with ActivityThread's lock held,
129      * so MUST NOT call back out to the activity manager.
130      */
131     public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
132             CompatibilityInfo compatInfo, ClassLoader baseLoader,
133             boolean securityViolation, boolean includeCode, boolean registerPackage) {
134
135         mActivityThread = activityThread;
136         setApplicationInfo(aInfo);
137         mPackageName = aInfo.packageName;
138         mBaseClassLoader = baseLoader;
139         mSecurityViolation = securityViolation;
140         mIncludeCode = includeCode;
141         mRegisterPackage = registerPackage;
142         mDisplayAdjustments.setCompatibilityInfo(compatInfo);
143     }
144
145     private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) {
146         // If we're dealing with a multi-arch application that has both
147         // 32 and 64 bit shared libraries, we might need to choose the secondary
148         // depending on what the current runtime's instruction set is.
149         if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
150             final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
151
152             // Get the instruction set that the libraries of secondary Abi is supported.
153             // In presence of a native bridge this might be different than the one secondary Abi used.
154             String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
155             final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
156             secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
157
158             // If the runtimeIsa is the same as the primary isa, then we do nothing.
159             // Everything will be set up correctly because info.nativeLibraryDir will
160             // correspond to the right ISA.
161             if (runtimeIsa.equals(secondaryIsa)) {
162                 final ApplicationInfo modified = new ApplicationInfo(info);
163                 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
164                 modified.primaryCpuAbi = modified.secondaryCpuAbi;
165                 return modified;
166             }
167         }
168
169         return info;
170     }
171
172     /**
173      * Create information about the system package.
174      * Must call {@link #installSystemApplicationInfo} later.
175      */
176     LoadedApk(ActivityThread activityThread) {
177         mActivityThread = activityThread;
178         mApplicationInfo = new ApplicationInfo();
179         mApplicationInfo.packageName = "android";
180         mPackageName = "android";
181         mAppDir = null;
182         mResDir = null;
183         mSplitAppDirs = null;
184         mSplitResDirs = null;
185         mOverlayDirs = null;
186         mSharedLibraries = null;
187         mDataDir = null;
188         mDataDirFile = null;
189         mDeviceEncryptedDataDirFile = null;
190         mCredentialEncryptedDataDirFile = null;
191         mLibDir = null;
192         mBaseClassLoader = null;
193         mSecurityViolation = false;
194         mIncludeCode = true;
195         mRegisterPackage = false;
196         mClassLoader = ClassLoader.getSystemClassLoader();
197         mResources = Resources.getSystem();
198     }
199
200     /**
201      * Sets application info about the system package.
202      */
203     void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
204         assert info.packageName.equals("android");
205         mApplicationInfo = info;
206         mClassLoader = classLoader;
207     }
208
209     public String getPackageName() {
210         return mPackageName;
211     }
212
213     public ApplicationInfo getApplicationInfo() {
214         return mApplicationInfo;
215     }
216
217     public int getTargetSdkVersion() {
218         return mApplicationInfo.targetSdkVersion;
219     }
220
221     public boolean isSecurityViolation() {
222         return mSecurityViolation;
223     }
224
225     public CompatibilityInfo getCompatibilityInfo() {
226         return mDisplayAdjustments.getCompatibilityInfo();
227     }
228
229     public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
230         mDisplayAdjustments.setCompatibilityInfo(compatInfo);
231     }
232
233     /**
234      * Gets the array of shared libraries that are listed as
235      * used by the given package.
236      *
237      * @param packageName the name of the package (note: not its
238      * file name)
239      * @return null-ok; the array of shared libraries, each one
240      * a fully-qualified path
241      */
242     private static String[] getLibrariesFor(String packageName) {
243         ApplicationInfo ai = null;
244         try {
245             ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
246                     PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
247         } catch (RemoteException e) {
248             throw e.rethrowFromSystemServer();
249         }
250
251         if (ai == null) {
252             return null;
253         }
254
255         return ai.sharedLibraryFiles;
256     }
257
258     public void updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths) {
259         setApplicationInfo(aInfo);
260
261         final List<String> newPaths = new ArrayList<>();
262         makePaths(mActivityThread, aInfo, newPaths, null /*libPaths*/);
263         final List<String> addedPaths = new ArrayList<>(newPaths.size());
264
265         if (oldPaths != null) {
266             for (String path : newPaths) {
267                 final String apkName = path.substring(path.lastIndexOf(File.separator));
268                 boolean match = false;
269                 for (String oldPath : oldPaths) {
270                     final String oldApkName = oldPath.substring(path.lastIndexOf(File.separator));
271                     if (apkName.equals(oldApkName)) {
272                         match = true;
273                         break;
274                     }
275                 }
276                 if (!match) {
277                     addedPaths.add(path);
278                 }
279             }
280         } else {
281             addedPaths.addAll(newPaths);
282         }
283         synchronized (this) {
284             createOrUpdateClassLoaderLocked(addedPaths);
285             if (mResources != null) {
286                 mResources = mActivityThread.getTopLevelResources(mResDir, mSplitResDirs,
287                         mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
288                         this);
289             }
290         }
291     }
292
293     private void setApplicationInfo(ApplicationInfo aInfo) {
294         final int myUid = Process.myUid();
295         aInfo = adjustNativeLibraryPaths(aInfo);
296         mApplicationInfo = aInfo;
297         mAppDir = aInfo.sourceDir;
298         mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
299         mSplitAppDirs = aInfo.splitSourceDirs;
300         mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
301         mOverlayDirs = aInfo.resourceDirs;
302         mSharedLibraries = aInfo.sharedLibraryFiles;
303         mDataDir = aInfo.dataDir;
304         mLibDir = aInfo.nativeLibraryDir;
305         mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
306         mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
307         mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
308     }
309
310     public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
311             List<String> outZipPaths, List<String> outLibPaths) {
312         final String appDir = aInfo.sourceDir;
313         final String[] splitAppDirs = aInfo.splitSourceDirs;
314         final String libDir = aInfo.nativeLibraryDir;
315         final String[] sharedLibraries = aInfo.sharedLibraryFiles;
316
317         outZipPaths.clear();
318         outZipPaths.add(appDir);
319         if (splitAppDirs != null) {
320             Collections.addAll(outZipPaths, splitAppDirs);
321         }
322
323         if (outLibPaths != null) {
324             outLibPaths.clear();
325         }
326
327         /*
328          * The following is a bit of a hack to inject
329          * instrumentation into the system: If the app
330          * being started matches one of the instrumentation names,
331          * then we combine both the "instrumentation" and
332          * "instrumented" app into the path, along with the
333          * concatenation of both apps' shared library lists.
334          */
335
336         String instrumentationPackageName = activityThread.mInstrumentationPackageName;
337         String instrumentationAppDir = activityThread.mInstrumentationAppDir;
338         String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
339         String instrumentationLibDir = activityThread.mInstrumentationLibDir;
340
341         String instrumentedAppDir = activityThread.mInstrumentedAppDir;
342         String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
343         String instrumentedLibDir = activityThread.mInstrumentedLibDir;
344         String[] instrumentationLibs = null;
345
346         if (appDir.equals(instrumentationAppDir)
347                 || appDir.equals(instrumentedAppDir)) {
348             outZipPaths.clear();
349             outZipPaths.add(instrumentationAppDir);
350             if (instrumentationSplitAppDirs != null) {
351                 Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
352             }
353             outZipPaths.add(instrumentedAppDir);
354             if (instrumentedSplitAppDirs != null) {
355                 Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
356             }
357
358             if (outLibPaths != null) {
359                 outLibPaths.add(instrumentationLibDir);
360                 outLibPaths.add(instrumentedLibDir);
361             }
362
363             if (!instrumentedAppDir.equals(instrumentationAppDir)) {
364                 instrumentationLibs = getLibrariesFor(instrumentationPackageName);
365             }
366         }
367
368         if (outLibPaths != null) {
369             if (outLibPaths.isEmpty()) {
370                 outLibPaths.add(libDir);
371             }
372
373             // Add path to libraries in apk for current abi. Do this now because more entries
374             // will be added to zipPaths that shouldn't be part of the library path.
375             if (aInfo.primaryCpuAbi != null) {
376                 for (String apk : outZipPaths) {
377                     outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
378                 }
379             }
380
381             if (aInfo.isSystemApp() && !aInfo.isUpdatedSystemApp()) {
382                 // Add path to system libraries to libPaths;
383                 // Access to system libs should be limited
384                 // to bundled applications; this is why updated
385                 // system apps are not included.
386                 outLibPaths.add(System.getProperty("java.library.path"));
387             }
388         }
389
390         if (sharedLibraries != null) {
391             for (String lib : sharedLibraries) {
392                 if (!outZipPaths.contains(lib)) {
393                     outZipPaths.add(0, lib);
394                 }
395             }
396         }
397
398         if (instrumentationLibs != null) {
399             for (String lib : instrumentationLibs) {
400                 if (!outZipPaths.contains(lib)) {
401                     outZipPaths.add(0, lib);
402                 }
403             }
404         }
405     }
406
407     private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
408         if (mPackageName.equals("android")) {
409             if (mClassLoader != null) {
410                 // nothing to update
411                 return;
412             }
413
414             if (mBaseClassLoader != null) {
415                 mClassLoader = mBaseClassLoader;
416             } else {
417                 mClassLoader = ClassLoader.getSystemClassLoader();
418             }
419
420             return;
421         }
422
423         // Avoid the binder call when the package is the current application package.
424         // The activity manager will perform ensure that dexopt is performed before
425         // spinning up the process.
426         if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
427             VMRuntime.getRuntime().vmInstructionSet();
428             try {
429                 ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
430             } catch (RemoteException re) {
431                 throw re.rethrowFromSystemServer();
432             }
433         }
434
435         final List<String> zipPaths = new ArrayList<>();
436         final List<String> libPaths = new ArrayList<>();
437
438         if (mRegisterPackage) {
439             try {
440                 ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
441             } catch (RemoteException e) {
442                 throw e.rethrowFromSystemServer();
443             }
444         }
445
446         makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
447         final String zip = mIncludeCode ? TextUtils.join(File.pathSeparator, zipPaths) : "";
448         final boolean isBundledApp = mApplicationInfo.isSystemApp()
449                 && !mApplicationInfo.isUpdatedSystemApp();
450         String libraryPermittedPath = mDataDir;
451         if (isBundledApp) {
452             // This is necessary to grant bundled apps access to
453             // libraries located in subdirectories of /system/lib
454             libraryPermittedPath += File.pathSeparator +
455                                     System.getProperty("java.library.path");
456         }
457         // DO NOT SHIP: this is a workaround for apps loading native libraries
458         // provided by 3rd party apps using absolute path instead of corresponding
459         // classloader; see http://b/26954419 for example.
460         if (mApplicationInfo.targetSdkVersion <= 23) {
461             libraryPermittedPath += File.pathSeparator + "/data/app";
462         }
463         // -----------------------------------------------------------------------------
464
465         final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
466
467         /*
468          * With all the combination done (if necessary, actually
469          * create the class loader.
470          */
471
472         if (ActivityThread.localLOGV)
473             Slog.v(ActivityThread.TAG, "Class path: " + zip +
474                     ", JNI path: " + librarySearchPath);
475
476         if (mClassLoader == null) {
477             // Temporarily disable logging of disk reads on the Looper thread
478             // as this is early and necessary.
479             StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
480
481             mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
482                     mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
483                     libraryPermittedPath, mBaseClassLoader);
484
485             StrictMode.setThreadPolicy(oldPolicy);
486         }
487
488         if (addedPaths != null && addedPaths.size() > 0) {
489             final String add = TextUtils.join(File.pathSeparator, addedPaths);
490             ApplicationLoaders.getDefault().addPath(mClassLoader, add);
491         }
492     }
493
494     public ClassLoader getClassLoader() {
495         synchronized (this) {
496             if (mClassLoader == null) {
497                 createOrUpdateClassLoaderLocked(null /*addedPaths*/);
498             }
499             return mClassLoader;
500         }
501     }
502
503     /**
504      * Setup value for Thread.getContextClassLoader(). If the
505      * package will not run in in a VM with other packages, we set
506      * the Java context ClassLoader to the
507      * PackageInfo.getClassLoader value. However, if this VM can
508      * contain multiple packages, we intead set the Java context
509      * ClassLoader to a proxy that will warn about the use of Java
510      * context ClassLoaders and then fall through to use the
511      * system ClassLoader.
512      *
513      * <p> Note that this is similar to but not the same as the
514      * android.content.Context.getClassLoader(). While both
515      * context class loaders are typically set to the
516      * PathClassLoader used to load the package archive in the
517      * single application per VM case, a single Android process
518      * may contain several Contexts executing on one thread with
519      * their own logical ClassLoaders while the Java context
520      * ClassLoader is a thread local. This is why in the case when
521      * we have multiple packages per VM we do not set the Java
522      * context ClassLoader to an arbitrary but instead warn the
523      * user to set their own if we detect that they are using a
524      * Java library that expects it to be set.
525      */
526     private void initializeJavaContextClassLoader() {
527         IPackageManager pm = ActivityThread.getPackageManager();
528         android.content.pm.PackageInfo pi;
529         try {
530             pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
531                     UserHandle.myUserId());
532         } catch (RemoteException e) {
533             throw e.rethrowFromSystemServer();
534         }
535         if (pi == null) {
536             throw new IllegalStateException("Unable to get package info for "
537                     + mPackageName + "; is package not installed?");
538         }
539         /*
540          * Two possible indications that this package could be
541          * sharing its virtual machine with other packages:
542          *
543          * 1.) the sharedUserId attribute is set in the manifest,
544          *     indicating a request to share a VM with other
545          *     packages with the same sharedUserId.
546          *
547          * 2.) the application element of the manifest has an
548          *     attribute specifying a non-default process name,
549          *     indicating the desire to run in another packages VM.
550          */
551         boolean sharedUserIdSet = (pi.sharedUserId != null);
552         boolean processNameNotDefault =
553             (pi.applicationInfo != null &&
554              !mPackageName.equals(pi.applicationInfo.processName));
555         boolean sharable = (sharedUserIdSet || processNameNotDefault);
556         ClassLoader contextClassLoader =
557             (sharable)
558             ? new WarningContextClassLoader()
559             : mClassLoader;
560         Thread.currentThread().setContextClassLoader(contextClassLoader);
561     }
562
563     private static class WarningContextClassLoader extends ClassLoader {
564
565         private static boolean warned = false;
566
567         private void warn(String methodName) {
568             if (warned) {
569                 return;
570             }
571             warned = true;
572             Thread.currentThread().setContextClassLoader(getParent());
573             Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
574                   "The class loader returned by " +
575                   "Thread.getContextClassLoader() may fail for processes " +
576                   "that host multiple applications. You should explicitly " +
577                   "specify a context class loader. For example: " +
578                   "Thread.setContextClassLoader(getClass().getClassLoader());");
579         }
580
581         @Override public URL getResource(String resName) {
582             warn("getResource");
583             return getParent().getResource(resName);
584         }
585
586         @Override public Enumeration<URL> getResources(String resName) throws IOException {
587             warn("getResources");
588             return getParent().getResources(resName);
589         }
590
591         @Override public InputStream getResourceAsStream(String resName) {
592             warn("getResourceAsStream");
593             return getParent().getResourceAsStream(resName);
594         }
595
596         @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
597             warn("loadClass");
598             return getParent().loadClass(className);
599         }
600
601         @Override public void setClassAssertionStatus(String cname, boolean enable) {
602             warn("setClassAssertionStatus");
603             getParent().setClassAssertionStatus(cname, enable);
604         }
605
606         @Override public void setPackageAssertionStatus(String pname, boolean enable) {
607             warn("setPackageAssertionStatus");
608             getParent().setPackageAssertionStatus(pname, enable);
609         }
610
611         @Override public void setDefaultAssertionStatus(boolean enable) {
612             warn("setDefaultAssertionStatus");
613             getParent().setDefaultAssertionStatus(enable);
614         }
615
616         @Override public void clearAssertionStatus() {
617             warn("clearAssertionStatus");
618             getParent().clearAssertionStatus();
619         }
620     }
621
622     public String getAppDir() {
623         return mAppDir;
624     }
625
626     public String getLibDir() {
627         return mLibDir;
628     }
629
630     public String getResDir() {
631         return mResDir;
632     }
633
634     public String[] getSplitAppDirs() {
635         return mSplitAppDirs;
636     }
637
638     public String[] getSplitResDirs() {
639         return mSplitResDirs;
640     }
641
642     public String[] getOverlayDirs() {
643         return mOverlayDirs;
644     }
645
646     public String getDataDir() {
647         return mDataDir;
648     }
649
650     public File getDataDirFile() {
651         return mDataDirFile;
652     }
653
654     public File getDeviceEncryptedDataDirFile() {
655         return mDeviceEncryptedDataDirFile;
656     }
657
658     public File getCredentialEncryptedDataDirFile() {
659         return mCredentialEncryptedDataDirFile;
660     }
661
662     public AssetManager getAssets(ActivityThread mainThread) {
663         return getResources(mainThread).getAssets();
664     }
665
666     public Resources getResources(ActivityThread mainThread) {
667         if (mResources == null) {
668             mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
669                     mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, this);
670         }
671         return mResources;
672     }
673
674     public Application makeApplication(boolean forceDefaultAppClass,
675             Instrumentation instrumentation) {
676         if (mApplication != null) {
677             return mApplication;
678         }
679
680         Application app = null;
681
682         String appClass = mApplicationInfo.className;
683         if (forceDefaultAppClass || (appClass == null)) {
684             appClass = "android.app.Application";
685         }
686
687         try {
688             java.lang.ClassLoader cl = getClassLoader();
689             if (!mPackageName.equals("android")) {
690                 initializeJavaContextClassLoader();
691             }
692             ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
693             app = mActivityThread.mInstrumentation.newApplication(
694                     cl, appClass, appContext);
695             appContext.setOuterContext(app);
696         } catch (Exception e) {
697             if (!mActivityThread.mInstrumentation.onException(app, e)) {
698                 throw new RuntimeException(
699                     "Unable to instantiate application " + appClass
700                     + ": " + e.toString(), e);
701             }
702         }
703         mActivityThread.mAllApplications.add(app);
704         mApplication = app;
705
706         if (instrumentation != null) {
707             try {
708                 instrumentation.callApplicationOnCreate(app);
709             } catch (Exception e) {
710                 if (!instrumentation.onException(app, e)) {
711                     throw new RuntimeException(
712                         "Unable to create application " + app.getClass().getName()
713                         + ": " + e.toString(), e);
714                 }
715             }
716         }
717
718         // Rewrite the R 'constants' for all library apks.
719         SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
720                 .getAssignedPackageIdentifiers();
721         final int N = packageIdentifiers.size();
722         for (int i = 0; i < N; i++) {
723             final int id = packageIdentifiers.keyAt(i);
724             if (id == 0x01 || id == 0x7f) {
725                 continue;
726             }
727
728             rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
729         }
730
731         return app;
732     }
733
734     private void rewriteRValues(ClassLoader cl, String packageName, int id) {
735         final Class<?> rClazz;
736         try {
737             rClazz = cl.loadClass(packageName + ".R");
738         } catch (ClassNotFoundException e) {
739             // This is not necessarily an error, as some packages do not ship with resources
740             // (or they do not need rewriting).
741             Log.i(TAG, "No resource references to update in package " + packageName);
742             return;
743         }
744
745         final Method callback;
746         try {
747             callback = rClazz.getMethod("onResourcesLoaded", int.class);
748         } catch (NoSuchMethodException e) {
749             // No rewriting to be done.
750             return;
751         }
752
753         Throwable cause;
754         try {
755             callback.invoke(null, id);
756             return;
757         } catch (IllegalAccessException e) {
758             cause = e;
759         } catch (InvocationTargetException e) {
760             cause = e.getCause();
761         }
762
763         throw new RuntimeException("Failed to rewrite resource references for " + packageName,
764                 cause);
765     }
766
767     public void removeContextRegistrations(Context context,
768             String who, String what) {
769         final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
770         synchronized (mReceivers) {
771             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
772                     mReceivers.remove(context);
773             if (rmap != null) {
774                 for (int i = 0; i < rmap.size(); i++) {
775                     LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
776                     IntentReceiverLeaked leak = new IntentReceiverLeaked(
777                             what + " " + who + " has leaked IntentReceiver "
778                             + rd.getIntentReceiver() + " that was " +
779                             "originally registered here. Are you missing a " +
780                             "call to unregisterReceiver()?");
781                     leak.setStackTrace(rd.getLocation().getStackTrace());
782                     Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
783                     if (reportRegistrationLeaks) {
784                         StrictMode.onIntentReceiverLeaked(leak);
785                     }
786                     try {
787                         ActivityManagerNative.getDefault().unregisterReceiver(
788                                 rd.getIIntentReceiver());
789                     } catch (RemoteException e) {
790                         throw e.rethrowFromSystemServer();
791                     }
792                 }
793             }
794             mUnregisteredReceivers.remove(context);
795         }
796
797         synchronized (mServices) {
798             //Slog.i(TAG, "Receiver registrations: " + mReceivers);
799             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
800                     mServices.remove(context);
801             if (smap != null) {
802                 for (int i = 0; i < smap.size(); i++) {
803                     LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
804                     ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
805                             what + " " + who + " has leaked ServiceConnection "
806                             + sd.getServiceConnection() + " that was originally bound here");
807                     leak.setStackTrace(sd.getLocation().getStackTrace());
808                     Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
809                     if (reportRegistrationLeaks) {
810                         StrictMode.onServiceConnectionLeaked(leak);
811                     }
812                     try {
813                         ActivityManagerNative.getDefault().unbindService(
814                                 sd.getIServiceConnection());
815                     } catch (RemoteException e) {
816                         throw e.rethrowFromSystemServer();
817                     }
818                     sd.doForget();
819                 }
820             }
821             mUnboundServices.remove(context);
822             //Slog.i(TAG, "Service registrations: " + mServices);
823         }
824     }
825
826     public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
827             Context context, Handler handler,
828             Instrumentation instrumentation, boolean registered) {
829         synchronized (mReceivers) {
830             LoadedApk.ReceiverDispatcher rd = null;
831             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
832             if (registered) {
833                 map = mReceivers.get(context);
834                 if (map != null) {
835                     rd = map.get(r);
836                 }
837             }
838             if (rd == null) {
839                 rd = new ReceiverDispatcher(r, context, handler,
840                         instrumentation, registered);
841                 if (registered) {
842                     if (map == null) {
843                         map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
844                         mReceivers.put(context, map);
845                     }
846                     map.put(r, rd);
847                 }
848             } else {
849                 rd.validate(context, handler);
850             }
851             rd.mForgotten = false;
852             return rd.getIIntentReceiver();
853         }
854     }
855
856     public IIntentReceiver forgetReceiverDispatcher(Context context,
857             BroadcastReceiver r) {
858         synchronized (mReceivers) {
859             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
860             LoadedApk.ReceiverDispatcher rd = null;
861             if (map != null) {
862                 rd = map.get(r);
863                 if (rd != null) {
864                     map.remove(r);
865                     if (map.size() == 0) {
866                         mReceivers.remove(context);
867                     }
868                     if (r.getDebugUnregister()) {
869                         ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
870                                 = mUnregisteredReceivers.get(context);
871                         if (holder == null) {
872                             holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
873                             mUnregisteredReceivers.put(context, holder);
874                         }
875                         RuntimeException ex = new IllegalArgumentException(
876                                 "Originally unregistered here:");
877                         ex.fillInStackTrace();
878                         rd.setUnregisterLocation(ex);
879                         holder.put(r, rd);
880                     }
881                     rd.mForgotten = true;
882                     return rd.getIIntentReceiver();
883                 }
884             }
885             ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
886                     = mUnregisteredReceivers.get(context);
887             if (holder != null) {
888                 rd = holder.get(r);
889                 if (rd != null) {
890                     RuntimeException ex = rd.getUnregisterLocation();
891                     throw new IllegalArgumentException(
892                             "Unregistering Receiver " + r
893                             + " that was already unregistered", ex);
894                 }
895             }
896             if (context == null) {
897                 throw new IllegalStateException("Unbinding Receiver " + r
898                         + " from Context that is no longer in use: " + context);
899             } else {
900                 throw new IllegalArgumentException("Receiver not registered: " + r);
901             }
902
903         }
904     }
905
906     static final class ReceiverDispatcher {
907
908         final static class InnerReceiver extends IIntentReceiver.Stub {
909             final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
910             final LoadedApk.ReceiverDispatcher mStrongRef;
911
912             InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
913                 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
914                 mStrongRef = strong ? rd : null;
915             }
916
917             @Override
918             public void performReceive(Intent intent, int resultCode, String data,
919                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
920                 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
921                 if (ActivityThread.DEBUG_BROADCAST) {
922                     int seq = intent.getIntExtra("seq", -1);
923                     Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
924                             + " to " + (rd != null ? rd.mReceiver : null));
925                 }
926                 if (rd != null) {
927                     rd.performReceive(intent, resultCode, data, extras,
928                             ordered, sticky, sendingUser);
929                 } else {
930                     // The activity manager dispatched a broadcast to a registered
931                     // receiver in this process, but before it could be delivered the
932                     // receiver was unregistered.  Acknowledge the broadcast on its
933                     // behalf so that the system's broadcast sequence can continue.
934                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
935                             "Finishing broadcast to unregistered receiver");
936                     IActivityManager mgr = ActivityManagerNative.getDefault();
937                     try {
938                         if (extras != null) {
939                             extras.setAllowFds(false);
940                         }
941                         mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
942                     } catch (RemoteException e) {
943                         throw e.rethrowFromSystemServer();
944                     }
945                 }
946             }
947         }
948
949         final IIntentReceiver.Stub mIIntentReceiver;
950         final BroadcastReceiver mReceiver;
951         final Context mContext;
952         final Handler mActivityThread;
953         final Instrumentation mInstrumentation;
954         final boolean mRegistered;
955         final IntentReceiverLeaked mLocation;
956         RuntimeException mUnregisterLocation;
957         boolean mForgotten;
958
959         final class Args extends BroadcastReceiver.PendingResult implements Runnable {
960             private Intent mCurIntent;
961             private final boolean mOrdered;
962
963             public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
964                     boolean ordered, boolean sticky, int sendingUser) {
965                 super(resultCode, resultData, resultExtras,
966                         mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
967                         sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
968                 mCurIntent = intent;
969                 mOrdered = ordered;
970             }
971             
972             public void run() {
973                 final BroadcastReceiver receiver = mReceiver;
974                 final boolean ordered = mOrdered;
975                 
976                 if (ActivityThread.DEBUG_BROADCAST) {
977                     int seq = mCurIntent.getIntExtra("seq", -1);
978                     Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
979                             + " seq=" + seq + " to " + mReceiver);
980                     Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
981                             + " mOrderedHint=" + ordered);
982                 }
983                 
984                 final IActivityManager mgr = ActivityManagerNative.getDefault();
985                 final Intent intent = mCurIntent;
986                 mCurIntent = null;
987                 
988                 if (receiver == null || mForgotten) {
989                     if (mRegistered && ordered) {
990                         if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
991                                 "Finishing null broadcast to " + mReceiver);
992                         sendFinished(mgr);
993                     }
994                     return;
995                 }
996
997                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
998                 try {
999                     ClassLoader cl =  mReceiver.getClass().getClassLoader();
1000                     intent.setExtrasClassLoader(cl);
1001                     intent.prepareToEnterProcess();
1002                     setExtrasClassLoader(cl);
1003                     receiver.setPendingResult(this);
1004                     receiver.onReceive(mContext, intent);
1005                 } catch (Exception e) {
1006                     if (mRegistered && ordered) {
1007                         if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1008                                 "Finishing failed broadcast to " + mReceiver);
1009                         sendFinished(mgr);
1010                     }
1011                     if (mInstrumentation == null ||
1012                             !mInstrumentation.onException(mReceiver, e)) {
1013                         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1014                         throw new RuntimeException(
1015                             "Error receiving broadcast " + intent
1016                             + " in " + mReceiver, e);
1017                     }
1018                 }
1019                 
1020                 if (receiver.getPendingResult() != null) {
1021                     finish();
1022                 }
1023                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1024             }
1025         }
1026
1027         ReceiverDispatcher(BroadcastReceiver receiver, Context context,
1028                 Handler activityThread, Instrumentation instrumentation,
1029                 boolean registered) {
1030             if (activityThread == null) {
1031                 throw new NullPointerException("Handler must not be null");
1032             }
1033
1034             mIIntentReceiver = new InnerReceiver(this, !registered);
1035             mReceiver = receiver;
1036             mContext = context;
1037             mActivityThread = activityThread;
1038             mInstrumentation = instrumentation;
1039             mRegistered = registered;
1040             mLocation = new IntentReceiverLeaked(null);
1041             mLocation.fillInStackTrace();
1042         }
1043
1044         void validate(Context context, Handler activityThread) {
1045             if (mContext != context) {
1046                 throw new IllegalStateException(
1047                     "Receiver " + mReceiver +
1048                     " registered with differing Context (was " +
1049                     mContext + " now " + context + ")");
1050             }
1051             if (mActivityThread != activityThread) {
1052                 throw new IllegalStateException(
1053                     "Receiver " + mReceiver +
1054                     " registered with differing handler (was " +
1055                     mActivityThread + " now " + activityThread + ")");
1056             }
1057         }
1058
1059         IntentReceiverLeaked getLocation() {
1060             return mLocation;
1061         }
1062
1063         BroadcastReceiver getIntentReceiver() {
1064             return mReceiver;
1065         }
1066
1067         IIntentReceiver getIIntentReceiver() {
1068             return mIIntentReceiver;
1069         }
1070
1071         void setUnregisterLocation(RuntimeException ex) {
1072             mUnregisterLocation = ex;
1073         }
1074
1075         RuntimeException getUnregisterLocation() {
1076             return mUnregisterLocation;
1077         }
1078
1079         public void performReceive(Intent intent, int resultCode, String data,
1080                 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
1081             if (ActivityThread.DEBUG_BROADCAST) {
1082                 int seq = intent.getIntExtra("seq", -1);
1083                 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
1084                         + " to " + mReceiver);
1085             }
1086             Args args = new Args(intent, resultCode, data, extras, ordered,
1087                     sticky, sendingUser);
1088             if (!mActivityThread.post(args)) {
1089                 if (mRegistered && ordered) {
1090                     IActivityManager mgr = ActivityManagerNative.getDefault();
1091                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1092                             "Finishing sync broadcast to " + mReceiver);
1093                     args.sendFinished(mgr);
1094                 }
1095             }
1096         }
1097
1098     }
1099
1100     public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1101             Context context, Handler handler, int flags) {
1102         synchronized (mServices) {
1103             LoadedApk.ServiceDispatcher sd = null;
1104             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
1105             if (map != null) {
1106                 sd = map.get(c);
1107             }
1108             if (sd == null) {
1109                 sd = new ServiceDispatcher(c, context, handler, flags);
1110                 if (map == null) {
1111                     map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
1112                     mServices.put(context, map);
1113                 }
1114                 map.put(c, sd);
1115             } else {
1116                 sd.validate(context, handler);
1117             }
1118             return sd.getIServiceConnection();
1119         }
1120     }
1121
1122     public final IServiceConnection forgetServiceDispatcher(Context context,
1123             ServiceConnection c) {
1124         synchronized (mServices) {
1125             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
1126                     = mServices.get(context);
1127             LoadedApk.ServiceDispatcher sd = null;
1128             if (map != null) {
1129                 sd = map.get(c);
1130                 if (sd != null) {
1131                     map.remove(c);
1132                     sd.doForget();
1133                     if (map.size() == 0) {
1134                         mServices.remove(context);
1135                     }
1136                     if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
1137                         ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
1138                                 = mUnboundServices.get(context);
1139                         if (holder == null) {
1140                             holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
1141                             mUnboundServices.put(context, holder);
1142                         }
1143                         RuntimeException ex = new IllegalArgumentException(
1144                                 "Originally unbound here:");
1145                         ex.fillInStackTrace();
1146                         sd.setUnbindLocation(ex);
1147                         holder.put(c, sd);
1148                     }
1149                     return sd.getIServiceConnection();
1150                 }
1151             }
1152             ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
1153                     = mUnboundServices.get(context);
1154             if (holder != null) {
1155                 sd = holder.get(c);
1156                 if (sd != null) {
1157                     RuntimeException ex = sd.getUnbindLocation();
1158                     throw new IllegalArgumentException(
1159                             "Unbinding Service " + c
1160                             + " that was already unbound", ex);
1161                 }
1162             }
1163             if (context == null) {
1164                 throw new IllegalStateException("Unbinding Service " + c
1165                         + " from Context that is no longer in use: " + context);
1166             } else {
1167                 throw new IllegalArgumentException("Service not registered: " + c);
1168             }
1169         }
1170     }
1171
1172     static final class ServiceDispatcher {
1173         private final ServiceDispatcher.InnerConnection mIServiceConnection;
1174         private final ServiceConnection mConnection;
1175         private final Context mContext;
1176         private final Handler mActivityThread;
1177         private final ServiceConnectionLeaked mLocation;
1178         private final int mFlags;
1179
1180         private RuntimeException mUnbindLocation;
1181
1182         private boolean mForgotten;
1183
1184         private static class ConnectionInfo {
1185             IBinder binder;
1186             IBinder.DeathRecipient deathMonitor;
1187         }
1188
1189         private static class InnerConnection extends IServiceConnection.Stub {
1190             final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1191
1192             InnerConnection(LoadedApk.ServiceDispatcher sd) {
1193                 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1194             }
1195
1196             public void connected(ComponentName name, IBinder service) throws RemoteException {
1197                 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1198                 if (sd != null) {
1199                     sd.connected(name, service);
1200                 }
1201             }
1202         }
1203
1204         private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1205             = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
1206
1207         ServiceDispatcher(ServiceConnection conn,
1208                 Context context, Handler activityThread, int flags) {
1209             mIServiceConnection = new InnerConnection(this);
1210             mConnection = conn;
1211             mContext = context;
1212             mActivityThread = activityThread;
1213             mLocation = new ServiceConnectionLeaked(null);
1214             mLocation.fillInStackTrace();
1215             mFlags = flags;
1216         }
1217
1218         void validate(Context context, Handler activityThread) {
1219             if (mContext != context) {
1220                 throw new RuntimeException(
1221                     "ServiceConnection " + mConnection +
1222                     " registered with differing Context (was " +
1223                     mContext + " now " + context + ")");
1224             }
1225             if (mActivityThread != activityThread) {
1226                 throw new RuntimeException(
1227                     "ServiceConnection " + mConnection +
1228                     " registered with differing handler (was " +
1229                     mActivityThread + " now " + activityThread + ")");
1230             }
1231         }
1232
1233         void doForget() {
1234             synchronized(this) {
1235                 for (int i=0; i<mActiveConnections.size(); i++) {
1236                     ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
1237                     ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1238                 }
1239                 mActiveConnections.clear();
1240                 mForgotten = true;
1241             }
1242         }
1243
1244         ServiceConnectionLeaked getLocation() {
1245             return mLocation;
1246         }
1247
1248         ServiceConnection getServiceConnection() {
1249             return mConnection;
1250         }
1251
1252         IServiceConnection getIServiceConnection() {
1253             return mIServiceConnection;
1254         }
1255
1256         int getFlags() {
1257             return mFlags;
1258         }
1259
1260         void setUnbindLocation(RuntimeException ex) {
1261             mUnbindLocation = ex;
1262         }
1263
1264         RuntimeException getUnbindLocation() {
1265             return mUnbindLocation;
1266         }
1267
1268         public void connected(ComponentName name, IBinder service) {
1269             if (mActivityThread != null) {
1270                 mActivityThread.post(new RunConnection(name, service, 0));
1271             } else {
1272                 doConnected(name, service);
1273             }
1274         }
1275
1276         public void death(ComponentName name, IBinder service) {
1277             ServiceDispatcher.ConnectionInfo old;
1278
1279             synchronized (this) {
1280                 old = mActiveConnections.remove(name);
1281                 if (old == null || old.binder != service) {
1282                     // Death for someone different than who we last
1283                     // reported...  just ignore it.
1284                     return;
1285                 }
1286                 old.binder.unlinkToDeath(old.deathMonitor, 0);
1287             }
1288
1289             if (mActivityThread != null) {
1290                 mActivityThread.post(new RunConnection(name, service, 1));
1291             } else {
1292                 doDeath(name, service);
1293             }
1294         }
1295
1296         public void doConnected(ComponentName name, IBinder service) {
1297             ServiceDispatcher.ConnectionInfo old;
1298             ServiceDispatcher.ConnectionInfo info;
1299
1300             synchronized (this) {
1301                 if (mForgotten) {
1302                     // We unbound before receiving the connection; ignore
1303                     // any connection received.
1304                     return;
1305                 }
1306                 old = mActiveConnections.get(name);
1307                 if (old != null && old.binder == service) {
1308                     // Huh, already have this one.  Oh well!
1309                     return;
1310                 }
1311
1312                 if (service != null) {
1313                     // A new service is being connected... set it all up.
1314                     info = new ConnectionInfo();
1315                     info.binder = service;
1316                     info.deathMonitor = new DeathMonitor(name, service);
1317                     try {
1318                         service.linkToDeath(info.deathMonitor, 0);
1319                         mActiveConnections.put(name, info);
1320                     } catch (RemoteException e) {
1321                         // This service was dead before we got it...  just
1322                         // don't do anything with it.
1323                         mActiveConnections.remove(name);
1324                         return;
1325                     }
1326
1327                 } else {
1328                     // The named service is being disconnected... clean up.
1329                     mActiveConnections.remove(name);
1330                 }
1331
1332                 if (old != null) {
1333                     old.binder.unlinkToDeath(old.deathMonitor, 0);
1334                 }
1335             }
1336
1337             // If there was an old service, it is not disconnected.
1338             if (old != null) {
1339                 mConnection.onServiceDisconnected(name);
1340             }
1341             // If there is a new service, it is now connected.
1342             if (service != null) {
1343                 mConnection.onServiceConnected(name, service);
1344             }
1345         }
1346
1347         public void doDeath(ComponentName name, IBinder service) {
1348             mConnection.onServiceDisconnected(name);
1349         }
1350
1351         private final class RunConnection implements Runnable {
1352             RunConnection(ComponentName name, IBinder service, int command) {
1353                 mName = name;
1354                 mService = service;
1355                 mCommand = command;
1356             }
1357
1358             public void run() {
1359                 if (mCommand == 0) {
1360                     doConnected(mName, mService);
1361                 } else if (mCommand == 1) {
1362                     doDeath(mName, mService);
1363                 }
1364             }
1365
1366             final ComponentName mName;
1367             final IBinder mService;
1368             final int mCommand;
1369         }
1370
1371         private final class DeathMonitor implements IBinder.DeathRecipient
1372         {
1373             DeathMonitor(ComponentName name, IBinder service) {
1374                 mName = name;
1375                 mService = service;
1376             }
1377
1378             public void binderDied() {
1379                 death(mName, mService);
1380             }
1381
1382             final ComponentName mName;
1383             final IBinder mService;
1384         }
1385     }
1386 }