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 { 73 public IntentReceiverLeaked(String msg) { 74 super(msg); 75 } 76 } 77 78 final class ServiceConnectionLeaked extends AndroidRuntimeException { 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 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 */ 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 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 */ 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 */ 209 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { 210 assert info.packageName.equals("android"); 211 mApplicationInfo = info; 212 mClassLoader = classLoader; 213 } 214 215 public String getPackageName() { 216 return mPackageName; 217 } 218 219 public ApplicationInfo getApplicationInfo() { 220 return mApplicationInfo; 221 } 222 223 public int getTargetSdkVersion() { 224 return mApplicationInfo.targetSdkVersion; 225 } 226 227 public boolean isSecurityViolation() { 228 return mSecurityViolation; 229 } 230 231 public CompatibilityInfo getCompatibilityInfo() { 232 return mDisplayAdjustments.getCompatibilityInfo(); 233 } 234 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 */ 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 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 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 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 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 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). 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 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 */ 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 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 679 @Override public URL getResource(String resName) { 680 warn("getResource"); 681 return getParent().getResource(resName); 682 } 683 684 @Override public Enumeration<URL> getResources(String resName) throws IOException { 685 warn("getResources"); 686 return getParent().getResources(resName); 687 } 688 689 @Override public InputStream getResourceAsStream(String resName) { 690 warn("getResourceAsStream"); 691 return getParent().getResourceAsStream(resName); 692 } 693 694 @Override public Class<?> loadClass(String className) throws ClassNotFoundException { 695 warn("loadClass"); 696 return getParent().loadClass(className); 697 } 698 699 @Override public void setClassAssertionStatus(String cname, boolean enable) { 700 warn("setClassAssertionStatus"); 701 getParent().setClassAssertionStatus(cname, enable); 702 } 703 704 @Override public void setPackageAssertionStatus(String pname, boolean enable) { 705 warn("setPackageAssertionStatus"); 706 getParent().setPackageAssertionStatus(pname, enable); 707 } 708 709 @Override public void setDefaultAssertionStatus(boolean enable) { 710 warn("setDefaultAssertionStatus"); 711 getParent().setDefaultAssertionStatus(enable); 712 } 713 714 @Override public void clearAssertionStatus() { 715 warn("clearAssertionStatus"); 716 getParent().clearAssertionStatus(); 717 } 718 } 719 720 public String getAppDir() { 721 return mAppDir; 722 } 723 724 public String getLibDir() { 725 return mLibDir; 726 } 727 728 public String getResDir() { 729 return mResDir; 730 } 731 732 public String[] getSplitAppDirs() { 733 return mSplitAppDirs; 734 } 735 736 public String[] getSplitResDirs() { 737 return mSplitResDirs; 738 } 739 740 public String[] getOverlayDirs() { 741 return mOverlayDirs; 742 } 743 744 public String getDataDir() { 745 return mDataDir; 746 } 747 748 public File getDataDirFile() { 749 return mDataDirFile; 750 } 751 752 public File getDeviceProtectedDataDirFile() { 753 return mDeviceProtectedDataDirFile; 754 } 755 756 public File getCredentialProtectedDataDirFile() { 757 return mCredentialProtectedDataDirFile; 758 } 759 760 public AssetManager getAssets(ActivityThread mainThread) { 761 return getResources(mainThread).getAssets(); 762 } 763 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 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 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 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 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 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 1019 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { 1020 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); 1021 mStrongRef = strong ? rd : null; 1022 } 1023 1024 @Override 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 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 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 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 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 1177 IntentReceiverLeaked getLocation() { 1178 return mLocation; 1179 } 1180 1181 BroadcastReceiver getIntentReceiver() { 1182 return mReceiver; 1183 } 1184 1185 IIntentReceiver getIIntentReceiver() { 1186 return mIIntentReceiver; 1187 } 1188 1189 void setUnregisterLocation(RuntimeException ex) { 1190 mUnregisterLocation = ex; 1191 } 1192 1193 RuntimeException getUnregisterLocation() { 1194 return mUnregisterLocation; 1195 } 1196 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 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 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 1314 InnerConnection(LoadedApk.ServiceDispatcher sd) { 1315 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); 1316 } 1317 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 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 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 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 1366 ServiceConnectionLeaked getLocation() { 1367 return mLocation; 1368 } 1369 1370 ServiceConnection getServiceConnection() { 1371 return mConnection; 1372 } 1373 1374 IServiceConnection getIServiceConnection() { 1375 return mIServiceConnection; 1376 } 1377 1378 int getFlags() { 1379 return mFlags; 1380 } 1381 1382 void setUnbindLocation(RuntimeException ex) { 1383 mUnbindLocation = ex; 1384 } 1385 1386 RuntimeException getUnbindLocation() { 1387 return mUnbindLocation; 1388 } 1389 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 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 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 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 { 1473 RunConnection(ComponentName name, IBinder service, int command) { 1474 mName = name; 1475 mService = service; 1476 mCommand = command; 1477 } 1478 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 { 1494 DeathMonitor(ComponentName name, IBinder service) { 1495 mName = name; 1496 mService = service; 1497 } 1498 1499 public void binderDied() { 1500 death(mName, mService); 1501 } 1502 1503 final ComponentName mName; 1504 final IBinder mService; 1505 } 1506 } 1507 } 1508