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