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