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