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