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 synchronized (mReceivers) { 636 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap = 637 mReceivers.remove(context); 638 if (rmap != null) { 639 for (int i = 0; i < rmap.size(); i++) { 640 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i); 641 IntentReceiverLeaked leak = new IntentReceiverLeaked( 642 what + " " + who + " has leaked IntentReceiver " 643 + rd.getIntentReceiver() + " that was " + 644 "originally registered here. Are you missing a " + 645 "call to unregisterReceiver()?"); 646 leak.setStackTrace(rd.getLocation().getStackTrace()); 647 Slog.e(ActivityThread.TAG, leak.getMessage(), leak); 648 if (reportRegistrationLeaks) { 649 StrictMode.onIntentReceiverLeaked(leak); 650 } 651 try { 652 ActivityManagerNative.getDefault().unregisterReceiver( 653 rd.getIIntentReceiver()); 654 } catch (RemoteException e) { 655 // system crashed, nothing we can do 656 } 657 } 658 } 659 mUnregisteredReceivers.remove(context); 660 } 661 662 synchronized (mServices) { 663 //Slog.i(TAG, "Receiver registrations: " + mReceivers); 664 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap = 665 mServices.remove(context); 666 if (smap != null) { 667 for (int i = 0; i < smap.size(); i++) { 668 LoadedApk.ServiceDispatcher sd = smap.valueAt(i); 669 ServiceConnectionLeaked leak = new ServiceConnectionLeaked( 670 what + " " + who + " has leaked ServiceConnection " 671 + sd.getServiceConnection() + " that was originally bound here"); 672 leak.setStackTrace(sd.getLocation().getStackTrace()); 673 Slog.e(ActivityThread.TAG, leak.getMessage(), leak); 674 if (reportRegistrationLeaks) { 675 StrictMode.onServiceConnectionLeaked(leak); 676 } 677 try { 678 ActivityManagerNative.getDefault().unbindService( 679 sd.getIServiceConnection()); 680 } catch (RemoteException e) { 681 // system crashed, nothing we can do 682 } 683 sd.doForget(); 684 } 685 } 686 mUnboundServices.remove(context); 687 //Slog.i(TAG, "Service registrations: " + mServices); 688 } 689 } 690 getReceiverDispatcher(BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered)691 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r, 692 Context context, Handler handler, 693 Instrumentation instrumentation, boolean registered) { 694 synchronized (mReceivers) { 695 LoadedApk.ReceiverDispatcher rd = null; 696 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null; 697 if (registered) { 698 map = mReceivers.get(context); 699 if (map != null) { 700 rd = map.get(r); 701 } 702 } 703 if (rd == null) { 704 rd = new ReceiverDispatcher(r, context, handler, 705 instrumentation, registered); 706 if (registered) { 707 if (map == null) { 708 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); 709 mReceivers.put(context, map); 710 } 711 map.put(r, rd); 712 } 713 } else { 714 rd.validate(context, handler); 715 } 716 rd.mForgotten = false; 717 return rd.getIIntentReceiver(); 718 } 719 } 720 forgetReceiverDispatcher(Context context, BroadcastReceiver r)721 public IIntentReceiver forgetReceiverDispatcher(Context context, 722 BroadcastReceiver r) { 723 synchronized (mReceivers) { 724 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context); 725 LoadedApk.ReceiverDispatcher rd = null; 726 if (map != null) { 727 rd = map.get(r); 728 if (rd != null) { 729 map.remove(r); 730 if (map.size() == 0) { 731 mReceivers.remove(context); 732 } 733 if (r.getDebugUnregister()) { 734 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder 735 = mUnregisteredReceivers.get(context); 736 if (holder == null) { 737 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); 738 mUnregisteredReceivers.put(context, holder); 739 } 740 RuntimeException ex = new IllegalArgumentException( 741 "Originally unregistered here:"); 742 ex.fillInStackTrace(); 743 rd.setUnregisterLocation(ex); 744 holder.put(r, rd); 745 } 746 rd.mForgotten = true; 747 return rd.getIIntentReceiver(); 748 } 749 } 750 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder 751 = mUnregisteredReceivers.get(context); 752 if (holder != null) { 753 rd = holder.get(r); 754 if (rd != null) { 755 RuntimeException ex = rd.getUnregisterLocation(); 756 throw new IllegalArgumentException( 757 "Unregistering Receiver " + r 758 + " that was already unregistered", ex); 759 } 760 } 761 if (context == null) { 762 throw new IllegalStateException("Unbinding Receiver " + r 763 + " from Context that is no longer in use: " + context); 764 } else { 765 throw new IllegalArgumentException("Receiver not registered: " + r); 766 } 767 768 } 769 } 770 771 static final class ReceiverDispatcher { 772 773 final static class InnerReceiver extends IIntentReceiver.Stub { 774 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher; 775 final LoadedApk.ReceiverDispatcher mStrongRef; 776 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong)777 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { 778 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); 779 mStrongRef = strong ? rd : null; 780 } performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)781 public void performReceive(Intent intent, int resultCode, String data, 782 Bundle extras, boolean ordered, boolean sticky, int sendingUser) { 783 LoadedApk.ReceiverDispatcher rd = mDispatcher.get(); 784 if (ActivityThread.DEBUG_BROADCAST) { 785 int seq = intent.getIntExtra("seq", -1); 786 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq 787 + " to " + (rd != null ? rd.mReceiver : null)); 788 } 789 if (rd != null) { 790 rd.performReceive(intent, resultCode, data, extras, 791 ordered, sticky, sendingUser); 792 } else { 793 // The activity manager dispatched a broadcast to a registered 794 // receiver in this process, but before it could be delivered the 795 // receiver was unregistered. Acknowledge the broadcast on its 796 // behalf so that the system's broadcast sequence can continue. 797 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 798 "Finishing broadcast to unregistered receiver"); 799 IActivityManager mgr = ActivityManagerNative.getDefault(); 800 try { 801 if (extras != null) { 802 extras.setAllowFds(false); 803 } 804 mgr.finishReceiver(this, resultCode, data, extras, false); 805 } catch (RemoteException e) { 806 Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver"); 807 } 808 } 809 } 810 } 811 812 final IIntentReceiver.Stub mIIntentReceiver; 813 final BroadcastReceiver mReceiver; 814 final Context mContext; 815 final Handler mActivityThread; 816 final Instrumentation mInstrumentation; 817 final boolean mRegistered; 818 final IntentReceiverLeaked mLocation; 819 RuntimeException mUnregisterLocation; 820 boolean mForgotten; 821 822 final class Args extends BroadcastReceiver.PendingResult implements Runnable { 823 private Intent mCurIntent; 824 private final boolean mOrdered; 825 Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser)826 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, 827 boolean ordered, boolean sticky, int sendingUser) { 828 super(resultCode, resultData, resultExtras, 829 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, 830 ordered, sticky, mIIntentReceiver.asBinder(), sendingUser); 831 mCurIntent = intent; 832 mOrdered = ordered; 833 } 834 run()835 public void run() { 836 final BroadcastReceiver receiver = mReceiver; 837 final boolean ordered = mOrdered; 838 839 if (ActivityThread.DEBUG_BROADCAST) { 840 int seq = mCurIntent.getIntExtra("seq", -1); 841 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction() 842 + " seq=" + seq + " to " + mReceiver); 843 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered 844 + " mOrderedHint=" + ordered); 845 } 846 847 final IActivityManager mgr = ActivityManagerNative.getDefault(); 848 final Intent intent = mCurIntent; 849 mCurIntent = null; 850 851 if (receiver == null || mForgotten) { 852 if (mRegistered && ordered) { 853 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 854 "Finishing null broadcast to " + mReceiver); 855 sendFinished(mgr); 856 } 857 return; 858 } 859 860 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg"); 861 try { 862 ClassLoader cl = mReceiver.getClass().getClassLoader(); 863 intent.setExtrasClassLoader(cl); 864 setExtrasClassLoader(cl); 865 receiver.setPendingResult(this); 866 receiver.onReceive(mContext, intent); 867 } catch (Exception e) { 868 if (mRegistered && ordered) { 869 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 870 "Finishing failed broadcast to " + mReceiver); 871 sendFinished(mgr); 872 } 873 if (mInstrumentation == null || 874 !mInstrumentation.onException(mReceiver, e)) { 875 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 876 throw new RuntimeException( 877 "Error receiving broadcast " + intent 878 + " in " + mReceiver, e); 879 } 880 } 881 882 if (receiver.getPendingResult() != null) { 883 finish(); 884 } 885 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 886 } 887 } 888 ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered)889 ReceiverDispatcher(BroadcastReceiver receiver, Context context, 890 Handler activityThread, Instrumentation instrumentation, 891 boolean registered) { 892 if (activityThread == null) { 893 throw new NullPointerException("Handler must not be null"); 894 } 895 896 mIIntentReceiver = new InnerReceiver(this, !registered); 897 mReceiver = receiver; 898 mContext = context; 899 mActivityThread = activityThread; 900 mInstrumentation = instrumentation; 901 mRegistered = registered; 902 mLocation = new IntentReceiverLeaked(null); 903 mLocation.fillInStackTrace(); 904 } 905 validate(Context context, Handler activityThread)906 void validate(Context context, Handler activityThread) { 907 if (mContext != context) { 908 throw new IllegalStateException( 909 "Receiver " + mReceiver + 910 " registered with differing Context (was " + 911 mContext + " now " + context + ")"); 912 } 913 if (mActivityThread != activityThread) { 914 throw new IllegalStateException( 915 "Receiver " + mReceiver + 916 " registered with differing handler (was " + 917 mActivityThread + " now " + activityThread + ")"); 918 } 919 } 920 getLocation()921 IntentReceiverLeaked getLocation() { 922 return mLocation; 923 } 924 getIntentReceiver()925 BroadcastReceiver getIntentReceiver() { 926 return mReceiver; 927 } 928 getIIntentReceiver()929 IIntentReceiver getIIntentReceiver() { 930 return mIIntentReceiver; 931 } 932 setUnregisterLocation(RuntimeException ex)933 void setUnregisterLocation(RuntimeException ex) { 934 mUnregisterLocation = ex; 935 } 936 getUnregisterLocation()937 RuntimeException getUnregisterLocation() { 938 return mUnregisterLocation; 939 } 940 performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)941 public void performReceive(Intent intent, int resultCode, String data, 942 Bundle extras, boolean ordered, boolean sticky, int sendingUser) { 943 if (ActivityThread.DEBUG_BROADCAST) { 944 int seq = intent.getIntExtra("seq", -1); 945 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq 946 + " to " + mReceiver); 947 } 948 Args args = new Args(intent, resultCode, data, extras, ordered, 949 sticky, sendingUser); 950 if (!mActivityThread.post(args)) { 951 if (mRegistered && ordered) { 952 IActivityManager mgr = ActivityManagerNative.getDefault(); 953 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 954 "Finishing sync broadcast to " + mReceiver); 955 args.sendFinished(mgr); 956 } 957 } 958 } 959 960 } 961 getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags)962 public final IServiceConnection getServiceDispatcher(ServiceConnection c, 963 Context context, Handler handler, int flags) { 964 synchronized (mServices) { 965 LoadedApk.ServiceDispatcher sd = null; 966 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); 967 if (map != null) { 968 sd = map.get(c); 969 } 970 if (sd == null) { 971 sd = new ServiceDispatcher(c, context, handler, flags); 972 if (map == null) { 973 map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); 974 mServices.put(context, map); 975 } 976 map.put(c, sd); 977 } else { 978 sd.validate(context, handler); 979 } 980 return sd.getIServiceConnection(); 981 } 982 } 983 forgetServiceDispatcher(Context context, ServiceConnection c)984 public final IServiceConnection forgetServiceDispatcher(Context context, 985 ServiceConnection c) { 986 synchronized (mServices) { 987 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map 988 = mServices.get(context); 989 LoadedApk.ServiceDispatcher sd = null; 990 if (map != null) { 991 sd = map.get(c); 992 if (sd != null) { 993 map.remove(c); 994 sd.doForget(); 995 if (map.size() == 0) { 996 mServices.remove(context); 997 } 998 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) { 999 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder 1000 = mUnboundServices.get(context); 1001 if (holder == null) { 1002 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); 1003 mUnboundServices.put(context, holder); 1004 } 1005 RuntimeException ex = new IllegalArgumentException( 1006 "Originally unbound here:"); 1007 ex.fillInStackTrace(); 1008 sd.setUnbindLocation(ex); 1009 holder.put(c, sd); 1010 } 1011 return sd.getIServiceConnection(); 1012 } 1013 } 1014 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder 1015 = mUnboundServices.get(context); 1016 if (holder != null) { 1017 sd = holder.get(c); 1018 if (sd != null) { 1019 RuntimeException ex = sd.getUnbindLocation(); 1020 throw new IllegalArgumentException( 1021 "Unbinding Service " + c 1022 + " that was already unbound", ex); 1023 } 1024 } 1025 if (context == null) { 1026 throw new IllegalStateException("Unbinding Service " + c 1027 + " from Context that is no longer in use: " + context); 1028 } else { 1029 throw new IllegalArgumentException("Service not registered: " + c); 1030 } 1031 } 1032 } 1033 1034 static final class ServiceDispatcher { 1035 private final ServiceDispatcher.InnerConnection mIServiceConnection; 1036 private final ServiceConnection mConnection; 1037 private final Context mContext; 1038 private final Handler mActivityThread; 1039 private final ServiceConnectionLeaked mLocation; 1040 private final int mFlags; 1041 1042 private RuntimeException mUnbindLocation; 1043 1044 private boolean mDied; 1045 private boolean mForgotten; 1046 1047 private static class ConnectionInfo { 1048 IBinder binder; 1049 IBinder.DeathRecipient deathMonitor; 1050 } 1051 1052 private static class InnerConnection extends IServiceConnection.Stub { 1053 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; 1054 InnerConnection(LoadedApk.ServiceDispatcher sd)1055 InnerConnection(LoadedApk.ServiceDispatcher sd) { 1056 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); 1057 } 1058 connected(ComponentName name, IBinder service)1059 public void connected(ComponentName name, IBinder service) throws RemoteException { 1060 LoadedApk.ServiceDispatcher sd = mDispatcher.get(); 1061 if (sd != null) { 1062 sd.connected(name, service); 1063 } 1064 } 1065 } 1066 1067 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections 1068 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>(); 1069 ServiceDispatcher(ServiceConnection conn, Context context, Handler activityThread, int flags)1070 ServiceDispatcher(ServiceConnection conn, 1071 Context context, Handler activityThread, int flags) { 1072 mIServiceConnection = new InnerConnection(this); 1073 mConnection = conn; 1074 mContext = context; 1075 mActivityThread = activityThread; 1076 mLocation = new ServiceConnectionLeaked(null); 1077 mLocation.fillInStackTrace(); 1078 mFlags = flags; 1079 } 1080 validate(Context context, Handler activityThread)1081 void validate(Context context, Handler activityThread) { 1082 if (mContext != context) { 1083 throw new RuntimeException( 1084 "ServiceConnection " + mConnection + 1085 " registered with differing Context (was " + 1086 mContext + " now " + context + ")"); 1087 } 1088 if (mActivityThread != activityThread) { 1089 throw new RuntimeException( 1090 "ServiceConnection " + mConnection + 1091 " registered with differing handler (was " + 1092 mActivityThread + " now " + activityThread + ")"); 1093 } 1094 } 1095 doForget()1096 void doForget() { 1097 synchronized(this) { 1098 for (int i=0; i<mActiveConnections.size(); i++) { 1099 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i); 1100 ci.binder.unlinkToDeath(ci.deathMonitor, 0); 1101 } 1102 mActiveConnections.clear(); 1103 mForgotten = true; 1104 } 1105 } 1106 getLocation()1107 ServiceConnectionLeaked getLocation() { 1108 return mLocation; 1109 } 1110 getServiceConnection()1111 ServiceConnection getServiceConnection() { 1112 return mConnection; 1113 } 1114 getIServiceConnection()1115 IServiceConnection getIServiceConnection() { 1116 return mIServiceConnection; 1117 } 1118 getFlags()1119 int getFlags() { 1120 return mFlags; 1121 } 1122 setUnbindLocation(RuntimeException ex)1123 void setUnbindLocation(RuntimeException ex) { 1124 mUnbindLocation = ex; 1125 } 1126 getUnbindLocation()1127 RuntimeException getUnbindLocation() { 1128 return mUnbindLocation; 1129 } 1130 connected(ComponentName name, IBinder service)1131 public void connected(ComponentName name, IBinder service) { 1132 if (mActivityThread != null) { 1133 mActivityThread.post(new RunConnection(name, service, 0)); 1134 } else { 1135 doConnected(name, service); 1136 } 1137 } 1138 death(ComponentName name, IBinder service)1139 public void death(ComponentName name, IBinder service) { 1140 ServiceDispatcher.ConnectionInfo old; 1141 1142 synchronized (this) { 1143 mDied = true; 1144 old = mActiveConnections.remove(name); 1145 if (old == null || old.binder != service) { 1146 // Death for someone different than who we last 1147 // reported... just ignore it. 1148 return; 1149 } 1150 old.binder.unlinkToDeath(old.deathMonitor, 0); 1151 } 1152 1153 if (mActivityThread != null) { 1154 mActivityThread.post(new RunConnection(name, service, 1)); 1155 } else { 1156 doDeath(name, service); 1157 } 1158 } 1159 doConnected(ComponentName name, IBinder service)1160 public void doConnected(ComponentName name, IBinder service) { 1161 ServiceDispatcher.ConnectionInfo old; 1162 ServiceDispatcher.ConnectionInfo info; 1163 1164 synchronized (this) { 1165 if (mForgotten) { 1166 // We unbound before receiving the connection; ignore 1167 // any connection received. 1168 return; 1169 } 1170 old = mActiveConnections.get(name); 1171 if (old != null && old.binder == service) { 1172 // Huh, already have this one. Oh well! 1173 return; 1174 } 1175 1176 if (service != null) { 1177 // A new service is being connected... set it all up. 1178 mDied = false; 1179 info = new ConnectionInfo(); 1180 info.binder = service; 1181 info.deathMonitor = new DeathMonitor(name, service); 1182 try { 1183 service.linkToDeath(info.deathMonitor, 0); 1184 mActiveConnections.put(name, info); 1185 } catch (RemoteException e) { 1186 // This service was dead before we got it... just 1187 // don't do anything with it. 1188 mActiveConnections.remove(name); 1189 return; 1190 } 1191 1192 } else { 1193 // The named service is being disconnected... clean up. 1194 mActiveConnections.remove(name); 1195 } 1196 1197 if (old != null) { 1198 old.binder.unlinkToDeath(old.deathMonitor, 0); 1199 } 1200 } 1201 1202 // If there was an old service, it is not disconnected. 1203 if (old != null) { 1204 mConnection.onServiceDisconnected(name); 1205 } 1206 // If there is a new service, it is now connected. 1207 if (service != null) { 1208 mConnection.onServiceConnected(name, service); 1209 } 1210 } 1211 doDeath(ComponentName name, IBinder service)1212 public void doDeath(ComponentName name, IBinder service) { 1213 mConnection.onServiceDisconnected(name); 1214 } 1215 1216 private final class RunConnection implements Runnable { RunConnection(ComponentName name, IBinder service, int command)1217 RunConnection(ComponentName name, IBinder service, int command) { 1218 mName = name; 1219 mService = service; 1220 mCommand = command; 1221 } 1222 run()1223 public void run() { 1224 if (mCommand == 0) { 1225 doConnected(mName, mService); 1226 } else if (mCommand == 1) { 1227 doDeath(mName, mService); 1228 } 1229 } 1230 1231 final ComponentName mName; 1232 final IBinder mService; 1233 final int mCommand; 1234 } 1235 1236 private final class DeathMonitor implements IBinder.DeathRecipient 1237 { DeathMonitor(ComponentName name, IBinder service)1238 DeathMonitor(ComponentName name, IBinder service) { 1239 mName = name; 1240 mService = service; 1241 } 1242 binderDied()1243 public void binderDied() { 1244 death(mName, mService); 1245 } 1246 1247 final ComponentName mName; 1248 final IBinder mService; 1249 } 1250 } 1251 } 1252