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 { 65 public IntentReceiverLeaked(String msg) { 66 super(msg); 67 } 68 } 69 70 final class ServiceConnectionLeaked extends AndroidRuntimeException { 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 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 */ 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 151 private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) { 152 // If we're dealing with a multi-arch application that has both 153 // 32 and 64 bit shared libraries, we might need to choose the secondary 154 // depending on what the current runtime's instruction set is. 155 if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) { 156 final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet(); 157 158 // Get the instruction set that the libraries of secondary Abi is supported. 159 // In presence of a native bridge this might be different than the one secondary Abi used. 160 String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi); 161 final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa); 162 secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa; 163 164 // If the runtimeIsa is the same as the primary isa, then we do nothing. 165 // Everything will be set up correctly because info.nativeLibraryDir will 166 // correspond to the right ISA. 167 if (runtimeIsa.equals(secondaryIsa)) { 168 final ApplicationInfo modified = new ApplicationInfo(info); 169 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir; 170 modified.primaryCpuAbi = modified.secondaryCpuAbi; 171 return modified; 172 } 173 } 174 175 return info; 176 } 177 178 /** 179 * Create information about the system package. 180 * Must call {@link #installSystemApplicationInfo} later. 181 */ 182 LoadedApk(ActivityThread activityThread) { 183 mActivityThread = activityThread; 184 mApplicationInfo = new ApplicationInfo(); 185 mApplicationInfo.packageName = "android"; 186 mPackageName = "android"; 187 mAppDir = null; 188 mResDir = null; 189 mSplitAppDirs = null; 190 mSplitResDirs = null; 191 mOverlayDirs = null; 192 mSharedLibraries = null; 193 mDataDir = null; 194 mDataDirFile = null; 195 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 */ 207 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { 208 assert info.packageName.equals("android"); 209 mApplicationInfo = info; 210 mClassLoader = classLoader; 211 } 212 213 public String getPackageName() { 214 return mPackageName; 215 } 216 217 public ApplicationInfo getApplicationInfo() { 218 return mApplicationInfo; 219 } 220 221 public boolean isSecurityViolation() { 222 return mSecurityViolation; 223 } 224 225 public CompatibilityInfo getCompatibilityInfo() { 226 return mDisplayAdjustments.getCompatibilityInfo(); 227 } 228 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 */ 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 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 */ 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 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 469 @Override public URL getResource(String resName) { 470 warn("getResource"); 471 return getParent().getResource(resName); 472 } 473 474 @Override public Enumeration<URL> getResources(String resName) throws IOException { 475 warn("getResources"); 476 return getParent().getResources(resName); 477 } 478 479 @Override public InputStream getResourceAsStream(String resName) { 480 warn("getResourceAsStream"); 481 return getParent().getResourceAsStream(resName); 482 } 483 484 @Override public Class<?> loadClass(String className) throws ClassNotFoundException { 485 warn("loadClass"); 486 return getParent().loadClass(className); 487 } 488 489 @Override public void setClassAssertionStatus(String cname, boolean enable) { 490 warn("setClassAssertionStatus"); 491 getParent().setClassAssertionStatus(cname, enable); 492 } 493 494 @Override public void setPackageAssertionStatus(String pname, boolean enable) { 495 warn("setPackageAssertionStatus"); 496 getParent().setPackageAssertionStatus(pname, enable); 497 } 498 499 @Override public void setDefaultAssertionStatus(boolean enable) { 500 warn("setDefaultAssertionStatus"); 501 getParent().setDefaultAssertionStatus(enable); 502 } 503 504 @Override public void clearAssertionStatus() { 505 warn("clearAssertionStatus"); 506 getParent().clearAssertionStatus(); 507 } 508 } 509 510 public String getAppDir() { 511 return mAppDir; 512 } 513 514 public String getLibDir() { 515 return mLibDir; 516 } 517 518 public String getResDir() { 519 return mResDir; 520 } 521 522 public String[] getSplitAppDirs() { 523 return mSplitAppDirs; 524 } 525 526 public String[] getSplitResDirs() { 527 return mSplitResDirs; 528 } 529 530 public String[] getOverlayDirs() { 531 return mOverlayDirs; 532 } 533 534 public String getDataDir() { 535 return mDataDir; 536 } 537 538 public File getDataDirFile() { 539 return mDataDirFile; 540 } 541 542 public AssetManager getAssets(ActivityThread mainThread) { 543 return getResources(mainThread).getAssets(); 544 } 545 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 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 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 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 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 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 792 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { 793 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); 794 mStrongRef = strong ? rd : null; 795 } 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 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 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 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 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 936 IntentReceiverLeaked getLocation() { 937 return mLocation; 938 } 939 940 BroadcastReceiver getIntentReceiver() { 941 return mReceiver; 942 } 943 944 IIntentReceiver getIIntentReceiver() { 945 return mIIntentReceiver; 946 } 947 948 void setUnregisterLocation(RuntimeException ex) { 949 mUnregisterLocation = ex; 950 } 951 952 RuntimeException getUnregisterLocation() { 953 return mUnregisterLocation; 954 } 955 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 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 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 1070 InnerConnection(LoadedApk.ServiceDispatcher sd) { 1071 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); 1072 } 1073 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 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 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 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 1122 ServiceConnectionLeaked getLocation() { 1123 return mLocation; 1124 } 1125 1126 ServiceConnection getServiceConnection() { 1127 return mConnection; 1128 } 1129 1130 IServiceConnection getIServiceConnection() { 1131 return mIServiceConnection; 1132 } 1133 1134 int getFlags() { 1135 return mFlags; 1136 } 1137 1138 void setUnbindLocation(RuntimeException ex) { 1139 mUnbindLocation = ex; 1140 } 1141 1142 RuntimeException getUnbindLocation() { 1143 return mUnbindLocation; 1144 } 1145 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 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 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 1227 public void doDeath(ComponentName name, IBinder service) { 1228 mConnection.onServiceDisconnected(name); 1229 } 1230 1231 private final class RunConnection implements Runnable { 1232 RunConnection(ComponentName name, IBinder service, int command) { 1233 mName = name; 1234 mService = service; 1235 mCommand = command; 1236 } 1237 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 { 1253 DeathMonitor(ComponentName name, IBinder service) { 1254 mName = name; 1255 mService = service; 1256 } 1257 1258 public void binderDied() { 1259 death(mName, mService); 1260 } 1261 1262 final ComponentName mName; 1263 final IBinder mService; 1264 } 1265 } 1266 } 1267