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 { 63 public IntentReceiverLeaked(String msg) { 64 super(msg); 65 } 66 } 67 68 final class ServiceConnectionLeaked extends AndroidRuntimeException { 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 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 */ 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 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 */ 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 */ 203 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { 204 assert info.packageName.equals("android"); 205 mApplicationInfo = info; 206 mClassLoader = classLoader; 207 } 208 209 public String getPackageName() { 210 return mPackageName; 211 } 212 213 public ApplicationInfo getApplicationInfo() { 214 return mApplicationInfo; 215 } 216 217 public boolean isSecurityViolation() { 218 return mSecurityViolation; 219 } 220 221 public CompatibilityInfo getCompatibilityInfo() { 222 return mDisplayAdjustments.getCompatibilityInfo(); 223 } 224 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 */ 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 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 */ 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 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 454 @Override public URL getResource(String resName) { 455 warn("getResource"); 456 return getParent().getResource(resName); 457 } 458 459 @Override public Enumeration<URL> getResources(String resName) throws IOException { 460 warn("getResources"); 461 return getParent().getResources(resName); 462 } 463 464 @Override public InputStream getResourceAsStream(String resName) { 465 warn("getResourceAsStream"); 466 return getParent().getResourceAsStream(resName); 467 } 468 469 @Override public Class<?> loadClass(String className) throws ClassNotFoundException { 470 warn("loadClass"); 471 return getParent().loadClass(className); 472 } 473 474 @Override public void setClassAssertionStatus(String cname, boolean enable) { 475 warn("setClassAssertionStatus"); 476 getParent().setClassAssertionStatus(cname, enable); 477 } 478 479 @Override public void setPackageAssertionStatus(String pname, boolean enable) { 480 warn("setPackageAssertionStatus"); 481 getParent().setPackageAssertionStatus(pname, enable); 482 } 483 484 @Override public void setDefaultAssertionStatus(boolean enable) { 485 warn("setDefaultAssertionStatus"); 486 getParent().setDefaultAssertionStatus(enable); 487 } 488 489 @Override public void clearAssertionStatus() { 490 warn("clearAssertionStatus"); 491 getParent().clearAssertionStatus(); 492 } 493 } 494 495 public String getAppDir() { 496 return mAppDir; 497 } 498 499 public String getLibDir() { 500 return mLibDir; 501 } 502 503 public String getResDir() { 504 return mResDir; 505 } 506 507 public String[] getSplitAppDirs() { 508 return mSplitAppDirs; 509 } 510 511 public String[] getSplitResDirs() { 512 return mSplitResDirs; 513 } 514 515 public String[] getOverlayDirs() { 516 return mOverlayDirs; 517 } 518 519 public String getDataDir() { 520 return mDataDir; 521 } 522 523 public File getDataDirFile() { 524 return mDataDirFile; 525 } 526 527 public AssetManager getAssets(ActivityThread mainThread) { 528 return getResources(mainThread).getAssets(); 529 } 530 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 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 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 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 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 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 777 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { 778 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); 779 mStrongRef = strong ? rd : null; 780 } 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 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 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 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 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 921 IntentReceiverLeaked getLocation() { 922 return mLocation; 923 } 924 925 BroadcastReceiver getIntentReceiver() { 926 return mReceiver; 927 } 928 929 IIntentReceiver getIIntentReceiver() { 930 return mIIntentReceiver; 931 } 932 933 void setUnregisterLocation(RuntimeException ex) { 934 mUnregisterLocation = ex; 935 } 936 937 RuntimeException getUnregisterLocation() { 938 return mUnregisterLocation; 939 } 940 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 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 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 1055 InnerConnection(LoadedApk.ServiceDispatcher sd) { 1056 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); 1057 } 1058 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 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 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 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 1107 ServiceConnectionLeaked getLocation() { 1108 return mLocation; 1109 } 1110 1111 ServiceConnection getServiceConnection() { 1112 return mConnection; 1113 } 1114 1115 IServiceConnection getIServiceConnection() { 1116 return mIServiceConnection; 1117 } 1118 1119 int getFlags() { 1120 return mFlags; 1121 } 1122 1123 void setUnbindLocation(RuntimeException ex) { 1124 mUnbindLocation = ex; 1125 } 1126 1127 RuntimeException getUnbindLocation() { 1128 return mUnbindLocation; 1129 } 1130 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 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 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 1212 public void doDeath(ComponentName name, IBinder service) { 1213 mConnection.onServiceDisconnected(name); 1214 } 1215 1216 private final class RunConnection implements Runnable { 1217 RunConnection(ComponentName name, IBinder service, int command) { 1218 mName = name; 1219 mService = service; 1220 mCommand = command; 1221 } 1222 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 { 1238 DeathMonitor(ComponentName name, IBinder service) { 1239 mName = name; 1240 mService = service; 1241 } 1242 1243 public void binderDied() { 1244 death(mName, mService); 1245 } 1246 1247 final ComponentName mName; 1248 final IBinder mService; 1249 } 1250 } 1251 } 1252