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