LoadedApk.java revision 4e8628157ad0c8c52e74b720eb0328086272ffda
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 17package android.app; 18 19import android.annotation.NonNull; 20import android.annotation.Nullable; 21import android.content.BroadcastReceiver; 22import android.content.ComponentName; 23import android.content.Context; 24import android.content.IIntentReceiver; 25import android.content.Intent; 26import android.content.ServiceConnection; 27import android.content.pm.ApplicationInfo; 28import android.content.pm.IPackageManager; 29import android.content.pm.PackageManager; 30import android.content.pm.split.SplitDependencyLoaderHelper; 31import android.content.res.AssetManager; 32import android.content.res.CompatibilityInfo; 33import android.content.res.Resources; 34import android.os.Build; 35import android.os.Bundle; 36import android.os.Environment; 37import android.os.FileUtils; 38import android.os.Handler; 39import android.os.IBinder; 40import android.os.Process; 41import android.os.RemoteException; 42import android.os.StrictMode; 43import android.os.SystemProperties; 44import android.os.Trace; 45import android.os.UserHandle; 46import android.text.TextUtils; 47import android.util.AndroidRuntimeException; 48import android.util.ArrayMap; 49import android.util.Log; 50import android.util.Slog; 51import android.util.SparseArray; 52import android.util.SparseIntArray; 53import android.view.Display; 54import android.view.DisplayAdjustments; 55 56import com.android.internal.util.ArrayUtils; 57 58import dalvik.system.BaseDexClassLoader; 59import dalvik.system.VMRuntime; 60 61import java.io.File; 62import java.io.IOException; 63import java.io.InputStream; 64import java.lang.ref.WeakReference; 65import java.lang.reflect.InvocationTargetException; 66import java.lang.reflect.Method; 67import java.net.URL; 68import java.util.ArrayList; 69import java.util.Arrays; 70import java.util.Collections; 71import java.util.Enumeration; 72import java.util.List; 73import java.util.Objects; 74 75final class IntentReceiverLeaked extends AndroidRuntimeException { 76 public IntentReceiverLeaked(String msg) { 77 super(msg); 78 } 79} 80 81final class ServiceConnectionLeaked extends AndroidRuntimeException { 82 public ServiceConnectionLeaked(String msg) { 83 super(msg); 84 } 85} 86 87/** 88 * Local state maintained about a currently loaded .apk. 89 * @hide 90 */ 91public final class LoadedApk { 92 93 private static final String TAG = "LoadedApk"; 94 95 private final ActivityThread mActivityThread; 96 final String mPackageName; 97 private ApplicationInfo mApplicationInfo; 98 private String mAppDir; 99 private String mResDir; 100 private String[] mOverlayDirs; 101 private String[] mSharedLibraries; 102 private String mDataDir; 103 private String mLibDir; 104 private File mDataDirFile; 105 private File mDeviceProtectedDataDirFile; 106 private File mCredentialProtectedDataDirFile; 107 private final ClassLoader mBaseClassLoader; 108 private final boolean mSecurityViolation; 109 private final boolean mIncludeCode; 110 private final boolean mRegisterPackage; 111 private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments(); 112 /** WARNING: This may change. Don't hold external references to it. */ 113 Resources mResources; 114 private ClassLoader mClassLoader; 115 private Application mApplication; 116 117 private String[] mSplitNames; 118 private String[] mSplitAppDirs; 119 private String[] mSplitResDirs; 120 121 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers 122 = new ArrayMap<>(); 123 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers 124 = new ArrayMap<>(); 125 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices 126 = new ArrayMap<>(); 127 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices 128 = new ArrayMap<>(); 129 130 int mClientCount = 0; 131 132 Application getApplication() { 133 return mApplication; 134 } 135 136 /** 137 * Create information about a new .apk 138 * 139 * NOTE: This constructor is called with ActivityThread's lock held, 140 * so MUST NOT call back out to the activity manager. 141 */ 142 public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo, 143 CompatibilityInfo compatInfo, ClassLoader baseLoader, 144 boolean securityViolation, boolean includeCode, boolean registerPackage) { 145 146 mActivityThread = activityThread; 147 setApplicationInfo(aInfo); 148 mPackageName = aInfo.packageName; 149 mBaseClassLoader = baseLoader; 150 mSecurityViolation = securityViolation; 151 mIncludeCode = includeCode; 152 mRegisterPackage = registerPackage; 153 mDisplayAdjustments.setCompatibilityInfo(compatInfo); 154 } 155 156 private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) { 157 // If we're dealing with a multi-arch application that has both 158 // 32 and 64 bit shared libraries, we might need to choose the secondary 159 // depending on what the current runtime's instruction set is. 160 if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) { 161 final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet(); 162 163 // Get the instruction set that the libraries of secondary Abi is supported. 164 // In presence of a native bridge this might be different than the one secondary Abi used. 165 String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi); 166 final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa); 167 secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa; 168 169 // If the runtimeIsa is the same as the primary isa, then we do nothing. 170 // Everything will be set up correctly because info.nativeLibraryDir will 171 // correspond to the right ISA. 172 if (runtimeIsa.equals(secondaryIsa)) { 173 final ApplicationInfo modified = new ApplicationInfo(info); 174 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir; 175 modified.primaryCpuAbi = modified.secondaryCpuAbi; 176 return modified; 177 } 178 } 179 180 return info; 181 } 182 183 /** 184 * Create information about the system package. 185 * Must call {@link #installSystemApplicationInfo} later. 186 */ 187 LoadedApk(ActivityThread activityThread) { 188 mActivityThread = activityThread; 189 mApplicationInfo = new ApplicationInfo(); 190 mApplicationInfo.packageName = "android"; 191 mPackageName = "android"; 192 mAppDir = null; 193 mResDir = null; 194 mSplitAppDirs = null; 195 mSplitResDirs = null; 196 mOverlayDirs = null; 197 mSharedLibraries = null; 198 mDataDir = null; 199 mDataDirFile = null; 200 mDeviceProtectedDataDirFile = null; 201 mCredentialProtectedDataDirFile = null; 202 mLibDir = null; 203 mBaseClassLoader = null; 204 mSecurityViolation = false; 205 mIncludeCode = true; 206 mRegisterPackage = false; 207 mClassLoader = ClassLoader.getSystemClassLoader(); 208 mResources = Resources.getSystem(); 209 } 210 211 /** 212 * Sets application info about the system package. 213 */ 214 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { 215 assert info.packageName.equals("android"); 216 mApplicationInfo = info; 217 mClassLoader = classLoader; 218 } 219 220 public String getPackageName() { 221 return mPackageName; 222 } 223 224 public ApplicationInfo getApplicationInfo() { 225 return mApplicationInfo; 226 } 227 228 public int getTargetSdkVersion() { 229 return mApplicationInfo.targetSdkVersion; 230 } 231 232 public boolean isSecurityViolation() { 233 return mSecurityViolation; 234 } 235 236 public CompatibilityInfo getCompatibilityInfo() { 237 return mDisplayAdjustments.getCompatibilityInfo(); 238 } 239 240 public void setCompatibilityInfo(CompatibilityInfo compatInfo) { 241 mDisplayAdjustments.setCompatibilityInfo(compatInfo); 242 } 243 244 /** 245 * Gets the array of shared libraries that are listed as 246 * used by the given package. 247 * 248 * @param packageName the name of the package (note: not its 249 * file name) 250 * @return null-ok; the array of shared libraries, each one 251 * a fully-qualified path 252 */ 253 private static String[] getLibrariesFor(String packageName) { 254 ApplicationInfo ai = null; 255 try { 256 ai = ActivityThread.getPackageManager().getApplicationInfo(packageName, 257 PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId()); 258 } catch (RemoteException e) { 259 throw e.rethrowFromSystemServer(); 260 } 261 262 if (ai == null) { 263 return null; 264 } 265 266 return ai.sharedLibraryFiles; 267 } 268 269 /** 270 * Update the ApplicationInfo for an app. If oldPaths is null, all the paths are considered 271 * new. 272 * @param aInfo The new ApplicationInfo to use for this LoadedApk 273 * @param oldPaths The code paths for the old ApplicationInfo object. null means no paths can 274 * be reused. 275 */ 276 public void updateApplicationInfo(@NonNull ApplicationInfo aInfo, 277 @Nullable List<String> oldPaths) { 278 setApplicationInfo(aInfo); 279 280 final List<String> newPaths = new ArrayList<>(); 281 makePaths(mActivityThread, aInfo, newPaths, null /*libPaths*/); 282 final List<String> addedPaths = new ArrayList<>(newPaths.size()); 283 284 if (oldPaths != null) { 285 for (String path : newPaths) { 286 final String apkName = path.substring(path.lastIndexOf(File.separator)); 287 boolean match = false; 288 for (String oldPath : oldPaths) { 289 final String oldApkName = oldPath.substring(path.lastIndexOf(File.separator)); 290 if (apkName.equals(oldApkName)) { 291 match = true; 292 break; 293 } 294 } 295 if (!match) { 296 addedPaths.add(path); 297 } 298 } 299 } else { 300 addedPaths.addAll(newPaths); 301 } 302 synchronized (this) { 303 createOrUpdateClassLoaderLocked(addedPaths); 304 if (mResources != null) { 305 final String[] splitPaths; 306 try { 307 splitPaths = getSplitPaths(null); 308 } catch (PackageManager.NameNotFoundException e) { 309 // This should NEVER fail. 310 throw new AssertionError("null split not found"); 311 } 312 313 mResources = ResourcesManager.getInstance().getResources(null, mResDir, 314 splitPaths, mOverlayDirs, mSharedLibraries, 315 Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(), 316 getClassLoader()); 317 } 318 } 319 } 320 321 private void setApplicationInfo(ApplicationInfo aInfo) { 322 final int myUid = Process.myUid(); 323 aInfo = adjustNativeLibraryPaths(aInfo); 324 mApplicationInfo = aInfo; 325 mAppDir = aInfo.sourceDir; 326 mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir; 327 mOverlayDirs = aInfo.resourceDirs; 328 mSharedLibraries = aInfo.sharedLibraryFiles; 329 mDataDir = aInfo.dataDir; 330 mLibDir = aInfo.nativeLibraryDir; 331 mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir); 332 mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir); 333 mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir); 334 335 mSplitNames = aInfo.splitNames; 336 mSplitAppDirs = aInfo.splitSourceDirs; 337 mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs; 338 339 if (aInfo.requestsIsolatedSplitLoading() && !ArrayUtils.isEmpty(mSplitNames)) { 340 mSplitLoader = new SplitDependencyLoader(aInfo.splitDependencies); 341 } 342 } 343 344 public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo, 345 List<String> outZipPaths, List<String> outLibPaths) { 346 final String appDir = aInfo.sourceDir; 347 final String libDir = aInfo.nativeLibraryDir; 348 final String[] sharedLibraries = aInfo.sharedLibraryFiles; 349 350 outZipPaths.clear(); 351 outZipPaths.add(appDir); 352 353 // Do not load all available splits if the app requested isolated split loading. 354 if (aInfo.splitSourceDirs != null && !aInfo.requestsIsolatedSplitLoading()) { 355 Collections.addAll(outZipPaths, aInfo.splitSourceDirs); 356 } 357 358 if (outLibPaths != null) { 359 outLibPaths.clear(); 360 } 361 362 /* 363 * The following is a bit of a hack to inject 364 * instrumentation into the system: If the app 365 * being started matches one of the instrumentation names, 366 * then we combine both the "instrumentation" and 367 * "instrumented" app into the path, along with the 368 * concatenation of both apps' shared library lists. 369 */ 370 371 String[] instrumentationLibs = null; 372 // activityThread will be null when called from the WebView zygote; just assume 373 // no instrumentation applies in this case. 374 if (activityThread != null) { 375 String instrumentationPackageName = activityThread.mInstrumentationPackageName; 376 String instrumentationAppDir = activityThread.mInstrumentationAppDir; 377 String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs; 378 String instrumentationLibDir = activityThread.mInstrumentationLibDir; 379 380 String instrumentedAppDir = activityThread.mInstrumentedAppDir; 381 String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs; 382 String instrumentedLibDir = activityThread.mInstrumentedLibDir; 383 384 if (appDir.equals(instrumentationAppDir) 385 || appDir.equals(instrumentedAppDir)) { 386 outZipPaths.clear(); 387 outZipPaths.add(instrumentationAppDir); 388 389 // Only add splits if the app did not request isolated split loading. 390 if (!aInfo.requestsIsolatedSplitLoading()) { 391 if (instrumentationSplitAppDirs != null) { 392 Collections.addAll(outZipPaths, instrumentationSplitAppDirs); 393 } 394 395 if (!instrumentationAppDir.equals(instrumentedAppDir)) { 396 outZipPaths.add(instrumentedAppDir); 397 if (instrumentedSplitAppDirs != null) { 398 Collections.addAll(outZipPaths, instrumentedSplitAppDirs); 399 } 400 } 401 } 402 403 if (outLibPaths != null) { 404 outLibPaths.add(instrumentationLibDir); 405 if (!instrumentationLibDir.equals(instrumentedLibDir)) { 406 outLibPaths.add(instrumentedLibDir); 407 } 408 } 409 410 if (!instrumentedAppDir.equals(instrumentationAppDir)) { 411 instrumentationLibs = getLibrariesFor(instrumentationPackageName); 412 } 413 } 414 } 415 416 if (outLibPaths != null) { 417 if (outLibPaths.isEmpty()) { 418 outLibPaths.add(libDir); 419 } 420 421 // Add path to libraries in apk for current abi. Do this now because more entries 422 // will be added to zipPaths that shouldn't be part of the library path. 423 if (aInfo.primaryCpuAbi != null) { 424 // Add fake libs into the library search path if we target prior to N. 425 if (aInfo.targetSdkVersion < Build.VERSION_CODES.N) { 426 outLibPaths.add("/system/fake-libs" + 427 (VMRuntime.is64BitAbi(aInfo.primaryCpuAbi) ? "64" : "")); 428 } 429 for (String apk : outZipPaths) { 430 outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi); 431 } 432 } 433 434 if (aInfo.isSystemApp() && !aInfo.isUpdatedSystemApp()) { 435 // Add path to system libraries to libPaths; 436 // Access to system libs should be limited 437 // to bundled applications; this is why updated 438 // system apps are not included. 439 outLibPaths.add(System.getProperty("java.library.path")); 440 } 441 } 442 443 if (sharedLibraries != null) { 444 for (String lib : sharedLibraries) { 445 if (!outZipPaths.contains(lib)) { 446 outZipPaths.add(0, lib); 447 } 448 } 449 } 450 451 if (instrumentationLibs != null) { 452 for (String lib : instrumentationLibs) { 453 if (!outZipPaths.contains(lib)) { 454 outZipPaths.add(0, lib); 455 } 456 } 457 } 458 } 459 460 private class SplitDependencyLoader 461 extends SplitDependencyLoaderHelper<PackageManager.NameNotFoundException> { 462 private String[] mCachedBaseResourcePath; 463 private final String[][] mCachedResourcePaths; 464 private final ClassLoader[] mCachedSplitClassLoaders; 465 466 SplitDependencyLoader(SparseIntArray dependencies) { 467 super(dependencies); 468 mCachedResourcePaths = new String[mSplitNames.length][]; 469 mCachedSplitClassLoaders = new ClassLoader[mSplitNames.length]; 470 } 471 472 @Override 473 protected boolean isSplitCached(int splitIdx) { 474 if (splitIdx != -1) { 475 return mCachedSplitClassLoaders[splitIdx] != null; 476 } 477 return mClassLoader != null && mCachedBaseResourcePath != null; 478 } 479 480 private void addAllConfigSplits(String splitName, ArrayList<String> outAssetPaths) { 481 for (int i = 0; i < mSplitNames.length; i++) { 482 if (isConfigurationSplitOf(mSplitNames[i], splitName)) { 483 outAssetPaths.add(mSplitResDirs[i]); 484 } 485 } 486 } 487 488 @Override 489 protected void constructSplit(int splitIdx, int parentSplitIdx) throws 490 PackageManager.NameNotFoundException { 491 final ArrayList<String> splitPaths = new ArrayList<>(); 492 if (splitIdx == -1) { 493 createOrUpdateClassLoaderLocked(null); 494 addAllConfigSplits(null, splitPaths); 495 mCachedBaseResourcePath = splitPaths.toArray(new String[splitPaths.size()]); 496 return; 497 } 498 499 final ClassLoader parent; 500 if (parentSplitIdx == -1) { 501 // The parent is the base APK, so use its ClassLoader as parent 502 // and its configuration splits as part of our own too. 503 parent = mClassLoader; 504 Collections.addAll(splitPaths, mCachedBaseResourcePath); 505 } else { 506 parent = mCachedSplitClassLoaders[parentSplitIdx]; 507 Collections.addAll(splitPaths, mCachedResourcePaths[parentSplitIdx]); 508 } 509 510 mCachedSplitClassLoaders[splitIdx] = ApplicationLoaders.getDefault().getClassLoader( 511 mSplitAppDirs[splitIdx], getTargetSdkVersion(), false, null, null, parent); 512 513 splitPaths.add(mSplitResDirs[splitIdx]); 514 addAllConfigSplits(mSplitNames[splitIdx], splitPaths); 515 mCachedResourcePaths[splitIdx] = splitPaths.toArray(new String[splitPaths.size()]); 516 } 517 518 private int ensureSplitLoaded(String splitName) 519 throws PackageManager.NameNotFoundException { 520 final int idx; 521 if (splitName == null) { 522 idx = -1; 523 } else { 524 idx = Arrays.binarySearch(mSplitNames, splitName); 525 if (idx < 0) { 526 throw new PackageManager.NameNotFoundException( 527 "Split name '" + splitName + "' is not installed"); 528 } 529 } 530 531 loadDependenciesForSplit(idx); 532 return idx; 533 } 534 535 ClassLoader getClassLoaderForSplit(String splitName) 536 throws PackageManager.NameNotFoundException { 537 final int idx = ensureSplitLoaded(splitName); 538 if (idx < 0) { 539 return mClassLoader; 540 } 541 return mCachedSplitClassLoaders[idx]; 542 } 543 544 String[] getSplitPathsForSplit(String splitName) 545 throws PackageManager.NameNotFoundException { 546 final int idx = ensureSplitLoaded(splitName); 547 if (idx < 0) { 548 return mCachedBaseResourcePath; 549 } 550 return mCachedResourcePaths[idx]; 551 } 552 } 553 554 private SplitDependencyLoader mSplitLoader; 555 556 ClassLoader getSplitClassLoader(String splitName) throws PackageManager.NameNotFoundException { 557 if (mSplitLoader == null) { 558 return mClassLoader; 559 } 560 return mSplitLoader.getClassLoaderForSplit(splitName); 561 } 562 563 String[] getSplitPaths(String splitName) throws PackageManager.NameNotFoundException { 564 if (mSplitLoader == null) { 565 return mSplitResDirs; 566 } 567 return mSplitLoader.getSplitPathsForSplit(splitName); 568 } 569 570 private void createOrUpdateClassLoaderLocked(List<String> addedPaths) { 571 if (mPackageName.equals("android")) { 572 // Note: This branch is taken for system server and we don't need to setup 573 // jit profiling support. 574 if (mClassLoader != null) { 575 // nothing to update 576 return; 577 } 578 579 if (mBaseClassLoader != null) { 580 mClassLoader = mBaseClassLoader; 581 } else { 582 mClassLoader = ClassLoader.getSystemClassLoader(); 583 } 584 585 return; 586 } 587 588 // Avoid the binder call when the package is the current application package. 589 // The activity manager will perform ensure that dexopt is performed before 590 // spinning up the process. 591 if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) { 592 VMRuntime.getRuntime().vmInstructionSet(); 593 try { 594 ActivityThread.getPackageManager().notifyPackageUse(mPackageName, 595 PackageManager.NOTIFY_PACKAGE_USE_CROSS_PACKAGE); 596 } catch (RemoteException re) { 597 throw re.rethrowFromSystemServer(); 598 } 599 } 600 601 if (mRegisterPackage) { 602 try { 603 ActivityManager.getService().addPackageDependency(mPackageName); 604 } catch (RemoteException e) { 605 throw e.rethrowFromSystemServer(); 606 } 607 } 608 609 // Lists for the elements of zip/code and native libraries. 610 // 611 // Both lists are usually not empty. We expect on average one APK for the zip component, 612 // but shared libraries and splits are not uncommon. We expect at least three elements 613 // for native libraries (app-based, system, vendor). As such, give both some breathing 614 // space and initialize to a small value (instead of incurring growth code). 615 final List<String> zipPaths = new ArrayList<>(10); 616 final List<String> libPaths = new ArrayList<>(10); 617 makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths); 618 619 final boolean isBundledApp = mApplicationInfo.isSystemApp() 620 && !mApplicationInfo.isUpdatedSystemApp(); 621 622 String libraryPermittedPath = mDataDir; 623 if (isBundledApp) { 624 // This is necessary to grant bundled apps access to 625 // libraries located in subdirectories of /system/lib 626 libraryPermittedPath += File.pathSeparator + 627 System.getProperty("java.library.path"); 628 } 629 630 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths); 631 632 // If we're not asked to include code, we construct a classloader that has 633 // no code path included. We still need to set up the library search paths 634 // and permitted path because NativeActivity relies on it (it attempts to 635 // call System.loadLibrary() on a classloader from a LoadedApk with 636 // mIncludeCode == false). 637 if (!mIncludeCode) { 638 if (mClassLoader == null) { 639 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); 640 mClassLoader = ApplicationLoaders.getDefault().getClassLoader( 641 "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp, 642 librarySearchPath, libraryPermittedPath, mBaseClassLoader); 643 StrictMode.setThreadPolicy(oldPolicy); 644 } 645 646 return; 647 } 648 649 /* 650 * With all the combination done (if necessary, actually create the java class 651 * loader and set up JIT profiling support if necessary. 652 * 653 * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils. 654 */ 655 final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) : 656 TextUtils.join(File.pathSeparator, zipPaths); 657 658 if (ActivityThread.localLOGV) 659 Slog.v(ActivityThread.TAG, "Class path: " + zip + 660 ", JNI path: " + librarySearchPath); 661 662 boolean needToSetupJitProfiles = false; 663 if (mClassLoader == null) { 664 // Temporarily disable logging of disk reads on the Looper thread 665 // as this is early and necessary. 666 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); 667 668 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, 669 mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath, 670 libraryPermittedPath, mBaseClassLoader); 671 672 StrictMode.setThreadPolicy(oldPolicy); 673 // Setup the class loader paths for profiling. 674 needToSetupJitProfiles = true; 675 } 676 677 if (addedPaths != null && addedPaths.size() > 0) { 678 final String add = TextUtils.join(File.pathSeparator, addedPaths); 679 ApplicationLoaders.getDefault().addPath(mClassLoader, add); 680 // Setup the new code paths for profiling. 681 needToSetupJitProfiles = true; 682 } 683 684 // Setup jit profile support. 685 // 686 // It is ok to call this multiple times if the application gets updated with new splits. 687 // The runtime only keeps track of unique code paths and can handle re-registration of 688 // the same code path. There's no need to pass `addedPaths` since any new code paths 689 // are already in `mApplicationInfo`. 690 // 691 // It is NOT ok to call this function from the system_server (for any of the packages it 692 // loads code from) so we explicitly disallow it there. 693 if (needToSetupJitProfiles && !ActivityThread.isSystem()) { 694 setupJitProfileSupport(); 695 } 696 } 697 698 public ClassLoader getClassLoader() { 699 synchronized (this) { 700 if (mClassLoader == null) { 701 createOrUpdateClassLoaderLocked(null /*addedPaths*/); 702 } 703 return mClassLoader; 704 } 705 } 706 707 // Keep in sync with installd (frameworks/native/cmds/installd/commands.cpp). 708 private static File getPrimaryProfileFile(String packageName) { 709 File profileDir = Environment.getDataProfilesDePackageDirectory( 710 UserHandle.myUserId(), packageName); 711 return new File(profileDir, "primary.prof"); 712 } 713 714 private void setupJitProfileSupport() { 715 if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) { 716 return; 717 } 718 // Only set up profile support if the loaded apk has the same uid as the 719 // current process. 720 // Currently, we do not support profiling across different apps. 721 // (e.g. application's uid might be different when the code is 722 // loaded by another app via createApplicationContext) 723 if (mApplicationInfo.uid != Process.myUid()) { 724 return; 725 } 726 727 final List<String> codePaths = new ArrayList<>(); 728 if ((mApplicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) { 729 codePaths.add(mApplicationInfo.sourceDir); 730 } 731 if (mApplicationInfo.splitSourceDirs != null) { 732 Collections.addAll(codePaths, mApplicationInfo.splitSourceDirs); 733 } 734 735 if (codePaths.isEmpty()) { 736 // If there are no code paths there's no need to setup a profile file and register with 737 // the runtime, 738 return; 739 } 740 741 final File profileFile = getPrimaryProfileFile(mPackageName); 742 final File foreignDexProfilesFile = 743 Environment.getDataProfilesDeForeignDexDirectory(UserHandle.myUserId()); 744 745 VMRuntime.registerAppInfo(profileFile.getPath(), mApplicationInfo.dataDir, 746 codePaths.toArray(new String[codePaths.size()]), foreignDexProfilesFile.getPath()); 747 748 // Setup the reporter to notify package manager of any relevant dex loads. 749 // At this point the primary apk is loaded and will not be reported. 750 // Anything loaded from now on will be tracked as a potential secondary 751 // or foreign dex file. The goal is to enable: 752 // 1) monitoring and compilation of secondary dex file 753 // 2) track foreign dex file usage (used to determined the 754 // compilation filter of apks). 755 if (BaseDexClassLoader.getReporter() != DexLoadReporter.INSTANCE) { 756 // Set the dex load reporter if not already set. 757 // Note that during the app's life cycle different LoadedApks may be 758 // created and loaded (e.g. if two different apps share the same runtime). 759 BaseDexClassLoader.setReporter(DexLoadReporter.INSTANCE); 760 } 761 } 762 763 private static class DexLoadReporter implements BaseDexClassLoader.Reporter { 764 private static final DexLoadReporter INSTANCE = new DexLoadReporter(); 765 766 private DexLoadReporter() {} 767 768 @Override 769 public void report(List<String> dexPaths) { 770 if (dexPaths.isEmpty()) { 771 return; 772 } 773 String packageName = ActivityThread.currentPackageName(); 774 try { 775 ActivityThread.getPackageManager().notifyDexLoad( 776 packageName, dexPaths, VMRuntime.getRuntime().vmInstructionSet()); 777 } catch (RemoteException re) { 778 Slog.e(TAG, "Failed to notify PM about dex load for package " + packageName, re); 779 } 780 } 781 } 782 783 /** 784 * Setup value for Thread.getContextClassLoader(). If the 785 * package will not run in in a VM with other packages, we set 786 * the Java context ClassLoader to the 787 * PackageInfo.getClassLoader value. However, if this VM can 788 * contain multiple packages, we intead set the Java context 789 * ClassLoader to a proxy that will warn about the use of Java 790 * context ClassLoaders and then fall through to use the 791 * system ClassLoader. 792 * 793 * <p> Note that this is similar to but not the same as the 794 * android.content.Context.getClassLoader(). While both 795 * context class loaders are typically set to the 796 * PathClassLoader used to load the package archive in the 797 * single application per VM case, a single Android process 798 * may contain several Contexts executing on one thread with 799 * their own logical ClassLoaders while the Java context 800 * ClassLoader is a thread local. This is why in the case when 801 * we have multiple packages per VM we do not set the Java 802 * context ClassLoader to an arbitrary but instead warn the 803 * user to set their own if we detect that they are using a 804 * Java library that expects it to be set. 805 */ 806 private void initializeJavaContextClassLoader() { 807 IPackageManager pm = ActivityThread.getPackageManager(); 808 android.content.pm.PackageInfo pi; 809 try { 810 pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 811 UserHandle.myUserId()); 812 } catch (RemoteException e) { 813 throw e.rethrowFromSystemServer(); 814 } 815 if (pi == null) { 816 throw new IllegalStateException("Unable to get package info for " 817 + mPackageName + "; is package not installed?"); 818 } 819 /* 820 * Two possible indications that this package could be 821 * sharing its virtual machine with other packages: 822 * 823 * 1.) the sharedUserId attribute is set in the manifest, 824 * indicating a request to share a VM with other 825 * packages with the same sharedUserId. 826 * 827 * 2.) the application element of the manifest has an 828 * attribute specifying a non-default process name, 829 * indicating the desire to run in another packages VM. 830 */ 831 boolean sharedUserIdSet = (pi.sharedUserId != null); 832 boolean processNameNotDefault = 833 (pi.applicationInfo != null && 834 !mPackageName.equals(pi.applicationInfo.processName)); 835 boolean sharable = (sharedUserIdSet || processNameNotDefault); 836 ClassLoader contextClassLoader = 837 (sharable) 838 ? new WarningContextClassLoader() 839 : mClassLoader; 840 Thread.currentThread().setContextClassLoader(contextClassLoader); 841 } 842 843 private static class WarningContextClassLoader extends ClassLoader { 844 845 private static boolean warned = false; 846 847 private void warn(String methodName) { 848 if (warned) { 849 return; 850 } 851 warned = true; 852 Thread.currentThread().setContextClassLoader(getParent()); 853 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " + 854 "The class loader returned by " + 855 "Thread.getContextClassLoader() may fail for processes " + 856 "that host multiple applications. You should explicitly " + 857 "specify a context class loader. For example: " + 858 "Thread.setContextClassLoader(getClass().getClassLoader());"); 859 } 860 861 @Override public URL getResource(String resName) { 862 warn("getResource"); 863 return getParent().getResource(resName); 864 } 865 866 @Override public Enumeration<URL> getResources(String resName) throws IOException { 867 warn("getResources"); 868 return getParent().getResources(resName); 869 } 870 871 @Override public InputStream getResourceAsStream(String resName) { 872 warn("getResourceAsStream"); 873 return getParent().getResourceAsStream(resName); 874 } 875 876 @Override public Class<?> loadClass(String className) throws ClassNotFoundException { 877 warn("loadClass"); 878 return getParent().loadClass(className); 879 } 880 881 @Override public void setClassAssertionStatus(String cname, boolean enable) { 882 warn("setClassAssertionStatus"); 883 getParent().setClassAssertionStatus(cname, enable); 884 } 885 886 @Override public void setPackageAssertionStatus(String pname, boolean enable) { 887 warn("setPackageAssertionStatus"); 888 getParent().setPackageAssertionStatus(pname, enable); 889 } 890 891 @Override public void setDefaultAssertionStatus(boolean enable) { 892 warn("setDefaultAssertionStatus"); 893 getParent().setDefaultAssertionStatus(enable); 894 } 895 896 @Override public void clearAssertionStatus() { 897 warn("clearAssertionStatus"); 898 getParent().clearAssertionStatus(); 899 } 900 } 901 902 public String getAppDir() { 903 return mAppDir; 904 } 905 906 public String getLibDir() { 907 return mLibDir; 908 } 909 910 public String getResDir() { 911 return mResDir; 912 } 913 914 public String[] getSplitAppDirs() { 915 return mSplitAppDirs; 916 } 917 918 public String[] getSplitResDirs() { 919 return mSplitResDirs; 920 } 921 922 public String[] getOverlayDirs() { 923 return mOverlayDirs; 924 } 925 926 public String[] getSharedLibraries() { 927 return mSharedLibraries; 928 } 929 930 public String getDataDir() { 931 return mDataDir; 932 } 933 934 public File getDataDirFile() { 935 return mDataDirFile; 936 } 937 938 public File getDeviceProtectedDataDirFile() { 939 return mDeviceProtectedDataDirFile; 940 } 941 942 public File getCredentialProtectedDataDirFile() { 943 return mCredentialProtectedDataDirFile; 944 } 945 946 public AssetManager getAssets() { 947 return getResources().getAssets(); 948 } 949 950 public Resources getResources() { 951 if (mResources == null) { 952 final String[] splitPaths; 953 try { 954 splitPaths = getSplitPaths(null); 955 } catch (PackageManager.NameNotFoundException e) { 956 // This should never fail. 957 throw new AssertionError("null split not found"); 958 } 959 960 mResources = ResourcesManager.getInstance().getResources(null, mResDir, 961 splitPaths, mOverlayDirs, mSharedLibraries, 962 Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(), 963 getClassLoader()); 964 } 965 return mResources; 966 } 967 968 public Application makeApplication(boolean forceDefaultAppClass, 969 Instrumentation instrumentation) { 970 if (mApplication != null) { 971 return mApplication; 972 } 973 974 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication"); 975 976 Application app = null; 977 978 String appClass = mApplicationInfo.className; 979 if (forceDefaultAppClass || (appClass == null)) { 980 appClass = "android.app.Application"; 981 } 982 983 try { 984 java.lang.ClassLoader cl = getClassLoader(); 985 if (!mPackageName.equals("android")) { 986 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 987 "initializeJavaContextClassLoader"); 988 initializeJavaContextClassLoader(); 989 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 990 } 991 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); 992 app = mActivityThread.mInstrumentation.newApplication( 993 cl, appClass, appContext); 994 appContext.setOuterContext(app); 995 } catch (Exception e) { 996 if (!mActivityThread.mInstrumentation.onException(app, e)) { 997 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 998 throw new RuntimeException( 999 "Unable to instantiate application " + appClass 1000 + ": " + e.toString(), e); 1001 } 1002 } 1003 mActivityThread.mAllApplications.add(app); 1004 mApplication = app; 1005 1006 if (instrumentation != null) { 1007 try { 1008 instrumentation.callApplicationOnCreate(app); 1009 } catch (Exception e) { 1010 if (!instrumentation.onException(app, e)) { 1011 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1012 throw new RuntimeException( 1013 "Unable to create application " + app.getClass().getName() 1014 + ": " + e.toString(), e); 1015 } 1016 } 1017 } 1018 1019 // Rewrite the R 'constants' for all library apks. 1020 SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(); 1021 final int N = packageIdentifiers.size(); 1022 for (int i = 0; i < N; i++) { 1023 final int id = packageIdentifiers.keyAt(i); 1024 if (id == 0x01 || id == 0x7f) { 1025 continue; 1026 } 1027 1028 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id); 1029 } 1030 1031 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1032 1033 return app; 1034 } 1035 1036 private void rewriteRValues(ClassLoader cl, String packageName, int id) { 1037 final Class<?> rClazz; 1038 try { 1039 rClazz = cl.loadClass(packageName + ".R"); 1040 } catch (ClassNotFoundException e) { 1041 // This is not necessarily an error, as some packages do not ship with resources 1042 // (or they do not need rewriting). 1043 Log.i(TAG, "No resource references to update in package " + packageName); 1044 return; 1045 } 1046 1047 final Method callback; 1048 try { 1049 callback = rClazz.getMethod("onResourcesLoaded", int.class); 1050 } catch (NoSuchMethodException e) { 1051 // No rewriting to be done. 1052 return; 1053 } 1054 1055 Throwable cause; 1056 try { 1057 callback.invoke(null, id); 1058 return; 1059 } catch (IllegalAccessException e) { 1060 cause = e; 1061 } catch (InvocationTargetException e) { 1062 cause = e.getCause(); 1063 } 1064 1065 throw new RuntimeException("Failed to rewrite resource references for " + packageName, 1066 cause); 1067 } 1068 1069 public void removeContextRegistrations(Context context, 1070 String who, String what) { 1071 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled(); 1072 synchronized (mReceivers) { 1073 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap = 1074 mReceivers.remove(context); 1075 if (rmap != null) { 1076 for (int i = 0; i < rmap.size(); i++) { 1077 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i); 1078 IntentReceiverLeaked leak = new IntentReceiverLeaked( 1079 what + " " + who + " has leaked IntentReceiver " 1080 + rd.getIntentReceiver() + " that was " + 1081 "originally registered here. Are you missing a " + 1082 "call to unregisterReceiver()?"); 1083 leak.setStackTrace(rd.getLocation().getStackTrace()); 1084 Slog.e(ActivityThread.TAG, leak.getMessage(), leak); 1085 if (reportRegistrationLeaks) { 1086 StrictMode.onIntentReceiverLeaked(leak); 1087 } 1088 try { 1089 ActivityManager.getService().unregisterReceiver( 1090 rd.getIIntentReceiver()); 1091 } catch (RemoteException e) { 1092 throw e.rethrowFromSystemServer(); 1093 } 1094 } 1095 } 1096 mUnregisteredReceivers.remove(context); 1097 } 1098 1099 synchronized (mServices) { 1100 //Slog.i(TAG, "Receiver registrations: " + mReceivers); 1101 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap = 1102 mServices.remove(context); 1103 if (smap != null) { 1104 for (int i = 0; i < smap.size(); i++) { 1105 LoadedApk.ServiceDispatcher sd = smap.valueAt(i); 1106 ServiceConnectionLeaked leak = new ServiceConnectionLeaked( 1107 what + " " + who + " has leaked ServiceConnection " 1108 + sd.getServiceConnection() + " that was originally bound here"); 1109 leak.setStackTrace(sd.getLocation().getStackTrace()); 1110 Slog.e(ActivityThread.TAG, leak.getMessage(), leak); 1111 if (reportRegistrationLeaks) { 1112 StrictMode.onServiceConnectionLeaked(leak); 1113 } 1114 try { 1115 ActivityManager.getService().unbindService( 1116 sd.getIServiceConnection()); 1117 } catch (RemoteException e) { 1118 throw e.rethrowFromSystemServer(); 1119 } 1120 sd.doForget(); 1121 } 1122 } 1123 mUnboundServices.remove(context); 1124 //Slog.i(TAG, "Service registrations: " + mServices); 1125 } 1126 } 1127 1128 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r, 1129 Context context, Handler handler, 1130 Instrumentation instrumentation, boolean registered) { 1131 synchronized (mReceivers) { 1132 LoadedApk.ReceiverDispatcher rd = null; 1133 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null; 1134 if (registered) { 1135 map = mReceivers.get(context); 1136 if (map != null) { 1137 rd = map.get(r); 1138 } 1139 } 1140 if (rd == null) { 1141 rd = new ReceiverDispatcher(r, context, handler, 1142 instrumentation, registered); 1143 if (registered) { 1144 if (map == null) { 1145 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); 1146 mReceivers.put(context, map); 1147 } 1148 map.put(r, rd); 1149 } 1150 } else { 1151 rd.validate(context, handler); 1152 } 1153 rd.mForgotten = false; 1154 return rd.getIIntentReceiver(); 1155 } 1156 } 1157 1158 public IIntentReceiver forgetReceiverDispatcher(Context context, 1159 BroadcastReceiver r) { 1160 synchronized (mReceivers) { 1161 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context); 1162 LoadedApk.ReceiverDispatcher rd = null; 1163 if (map != null) { 1164 rd = map.get(r); 1165 if (rd != null) { 1166 map.remove(r); 1167 if (map.size() == 0) { 1168 mReceivers.remove(context); 1169 } 1170 if (r.getDebugUnregister()) { 1171 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder 1172 = mUnregisteredReceivers.get(context); 1173 if (holder == null) { 1174 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); 1175 mUnregisteredReceivers.put(context, holder); 1176 } 1177 RuntimeException ex = new IllegalArgumentException( 1178 "Originally unregistered here:"); 1179 ex.fillInStackTrace(); 1180 rd.setUnregisterLocation(ex); 1181 holder.put(r, rd); 1182 } 1183 rd.mForgotten = true; 1184 return rd.getIIntentReceiver(); 1185 } 1186 } 1187 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder 1188 = mUnregisteredReceivers.get(context); 1189 if (holder != null) { 1190 rd = holder.get(r); 1191 if (rd != null) { 1192 RuntimeException ex = rd.getUnregisterLocation(); 1193 throw new IllegalArgumentException( 1194 "Unregistering Receiver " + r 1195 + " that was already unregistered", ex); 1196 } 1197 } 1198 if (context == null) { 1199 throw new IllegalStateException("Unbinding Receiver " + r 1200 + " from Context that is no longer in use: " + context); 1201 } else { 1202 throw new IllegalArgumentException("Receiver not registered: " + r); 1203 } 1204 1205 } 1206 } 1207 1208 static final class ReceiverDispatcher { 1209 1210 final static class InnerReceiver extends IIntentReceiver.Stub { 1211 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher; 1212 final LoadedApk.ReceiverDispatcher mStrongRef; 1213 1214 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { 1215 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); 1216 mStrongRef = strong ? rd : null; 1217 } 1218 1219 @Override 1220 public void performReceive(Intent intent, int resultCode, String data, 1221 Bundle extras, boolean ordered, boolean sticky, int sendingUser) { 1222 final LoadedApk.ReceiverDispatcher rd; 1223 if (intent == null) { 1224 Log.wtf(TAG, "Null intent received"); 1225 rd = null; 1226 } else { 1227 rd = mDispatcher.get(); 1228 } 1229 if (ActivityThread.DEBUG_BROADCAST) { 1230 int seq = intent.getIntExtra("seq", -1); 1231 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() 1232 + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null)); 1233 } 1234 if (rd != null) { 1235 rd.performReceive(intent, resultCode, data, extras, 1236 ordered, sticky, sendingUser); 1237 } else { 1238 // The activity manager dispatched a broadcast to a registered 1239 // receiver in this process, but before it could be delivered the 1240 // receiver was unregistered. Acknowledge the broadcast on its 1241 // behalf so that the system's broadcast sequence can continue. 1242 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1243 "Finishing broadcast to unregistered receiver"); 1244 IActivityManager mgr = ActivityManager.getService(); 1245 try { 1246 if (extras != null) { 1247 extras.setAllowFds(false); 1248 } 1249 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags()); 1250 } catch (RemoteException e) { 1251 throw e.rethrowFromSystemServer(); 1252 } 1253 } 1254 } 1255 } 1256 1257 final IIntentReceiver.Stub mIIntentReceiver; 1258 final BroadcastReceiver mReceiver; 1259 final Context mContext; 1260 final Handler mActivityThread; 1261 final Instrumentation mInstrumentation; 1262 final boolean mRegistered; 1263 final IntentReceiverLeaked mLocation; 1264 RuntimeException mUnregisterLocation; 1265 boolean mForgotten; 1266 1267 final class Args extends BroadcastReceiver.PendingResult implements Runnable { 1268 private Intent mCurIntent; 1269 private final boolean mOrdered; 1270 private boolean mDispatched; 1271 1272 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, 1273 boolean ordered, boolean sticky, int sendingUser) { 1274 super(resultCode, resultData, resultExtras, 1275 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered, 1276 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags()); 1277 mCurIntent = intent; 1278 mOrdered = ordered; 1279 } 1280 1281 public void run() { 1282 final BroadcastReceiver receiver = mReceiver; 1283 final boolean ordered = mOrdered; 1284 1285 if (ActivityThread.DEBUG_BROADCAST) { 1286 int seq = mCurIntent.getIntExtra("seq", -1); 1287 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction() 1288 + " seq=" + seq + " to " + mReceiver); 1289 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered 1290 + " mOrderedHint=" + ordered); 1291 } 1292 1293 final IActivityManager mgr = ActivityManager.getService(); 1294 final Intent intent = mCurIntent; 1295 if (intent == null) { 1296 Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched); 1297 } 1298 1299 mCurIntent = null; 1300 mDispatched = true; 1301 if (receiver == null || intent == null || mForgotten) { 1302 if (mRegistered && ordered) { 1303 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1304 "Finishing null broadcast to " + mReceiver); 1305 sendFinished(mgr); 1306 } 1307 return; 1308 } 1309 1310 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg"); 1311 try { 1312 ClassLoader cl = mReceiver.getClass().getClassLoader(); 1313 intent.setExtrasClassLoader(cl); 1314 intent.prepareToEnterProcess(); 1315 setExtrasClassLoader(cl); 1316 receiver.setPendingResult(this); 1317 receiver.onReceive(mContext, intent); 1318 } catch (Exception e) { 1319 if (mRegistered && ordered) { 1320 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1321 "Finishing failed broadcast to " + mReceiver); 1322 sendFinished(mgr); 1323 } 1324 if (mInstrumentation == null || 1325 !mInstrumentation.onException(mReceiver, e)) { 1326 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1327 throw new RuntimeException( 1328 "Error receiving broadcast " + intent 1329 + " in " + mReceiver, e); 1330 } 1331 } 1332 1333 if (receiver.getPendingResult() != null) { 1334 finish(); 1335 } 1336 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1337 } 1338 } 1339 1340 ReceiverDispatcher(BroadcastReceiver receiver, Context context, 1341 Handler activityThread, Instrumentation instrumentation, 1342 boolean registered) { 1343 if (activityThread == null) { 1344 throw new NullPointerException("Handler must not be null"); 1345 } 1346 1347 mIIntentReceiver = new InnerReceiver(this, !registered); 1348 mReceiver = receiver; 1349 mContext = context; 1350 mActivityThread = activityThread; 1351 mInstrumentation = instrumentation; 1352 mRegistered = registered; 1353 mLocation = new IntentReceiverLeaked(null); 1354 mLocation.fillInStackTrace(); 1355 } 1356 1357 void validate(Context context, Handler activityThread) { 1358 if (mContext != context) { 1359 throw new IllegalStateException( 1360 "Receiver " + mReceiver + 1361 " registered with differing Context (was " + 1362 mContext + " now " + context + ")"); 1363 } 1364 if (mActivityThread != activityThread) { 1365 throw new IllegalStateException( 1366 "Receiver " + mReceiver + 1367 " registered with differing handler (was " + 1368 mActivityThread + " now " + activityThread + ")"); 1369 } 1370 } 1371 1372 IntentReceiverLeaked getLocation() { 1373 return mLocation; 1374 } 1375 1376 BroadcastReceiver getIntentReceiver() { 1377 return mReceiver; 1378 } 1379 1380 IIntentReceiver getIIntentReceiver() { 1381 return mIIntentReceiver; 1382 } 1383 1384 void setUnregisterLocation(RuntimeException ex) { 1385 mUnregisterLocation = ex; 1386 } 1387 1388 RuntimeException getUnregisterLocation() { 1389 return mUnregisterLocation; 1390 } 1391 1392 public void performReceive(Intent intent, int resultCode, String data, 1393 Bundle extras, boolean ordered, boolean sticky, int sendingUser) { 1394 final Args args = new Args(intent, resultCode, data, extras, ordered, 1395 sticky, sendingUser); 1396 if (intent == null) { 1397 Log.wtf(TAG, "Null intent received"); 1398 } else { 1399 if (ActivityThread.DEBUG_BROADCAST) { 1400 int seq = intent.getIntExtra("seq", -1); 1401 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() 1402 + " seq=" + seq + " to " + mReceiver); 1403 } 1404 } 1405 if (intent == null || !mActivityThread.post(args)) { 1406 if (mRegistered && ordered) { 1407 IActivityManager mgr = ActivityManager.getService(); 1408 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1409 "Finishing sync broadcast to " + mReceiver); 1410 args.sendFinished(mgr); 1411 } 1412 } 1413 } 1414 1415 } 1416 1417 public final IServiceConnection getServiceDispatcher(ServiceConnection c, 1418 Context context, Handler handler, int flags) { 1419 synchronized (mServices) { 1420 LoadedApk.ServiceDispatcher sd = null; 1421 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); 1422 if (map != null) { 1423 sd = map.get(c); 1424 } 1425 if (sd == null) { 1426 sd = new ServiceDispatcher(c, context, handler, flags); 1427 if (map == null) { 1428 map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); 1429 mServices.put(context, map); 1430 } 1431 map.put(c, sd); 1432 } else { 1433 sd.validate(context, handler); 1434 } 1435 return sd.getIServiceConnection(); 1436 } 1437 } 1438 1439 public final IServiceConnection forgetServiceDispatcher(Context context, 1440 ServiceConnection c) { 1441 synchronized (mServices) { 1442 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map 1443 = mServices.get(context); 1444 LoadedApk.ServiceDispatcher sd = null; 1445 if (map != null) { 1446 sd = map.get(c); 1447 if (sd != null) { 1448 map.remove(c); 1449 sd.doForget(); 1450 if (map.size() == 0) { 1451 mServices.remove(context); 1452 } 1453 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) { 1454 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder 1455 = mUnboundServices.get(context); 1456 if (holder == null) { 1457 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); 1458 mUnboundServices.put(context, holder); 1459 } 1460 RuntimeException ex = new IllegalArgumentException( 1461 "Originally unbound here:"); 1462 ex.fillInStackTrace(); 1463 sd.setUnbindLocation(ex); 1464 holder.put(c, sd); 1465 } 1466 return sd.getIServiceConnection(); 1467 } 1468 } 1469 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder 1470 = mUnboundServices.get(context); 1471 if (holder != null) { 1472 sd = holder.get(c); 1473 if (sd != null) { 1474 RuntimeException ex = sd.getUnbindLocation(); 1475 throw new IllegalArgumentException( 1476 "Unbinding Service " + c 1477 + " that was already unbound", ex); 1478 } 1479 } 1480 if (context == null) { 1481 throw new IllegalStateException("Unbinding Service " + c 1482 + " from Context that is no longer in use: " + context); 1483 } else { 1484 throw new IllegalArgumentException("Service not registered: " + c); 1485 } 1486 } 1487 } 1488 1489 static final class ServiceDispatcher { 1490 private final ServiceDispatcher.InnerConnection mIServiceConnection; 1491 private final ServiceConnection mConnection; 1492 private final Context mContext; 1493 private final Handler mActivityThread; 1494 private final ServiceConnectionLeaked mLocation; 1495 private final int mFlags; 1496 1497 private RuntimeException mUnbindLocation; 1498 1499 private boolean mForgotten; 1500 1501 private static class ConnectionInfo { 1502 IBinder binder; 1503 IBinder.DeathRecipient deathMonitor; 1504 } 1505 1506 private static class InnerConnection extends IServiceConnection.Stub { 1507 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; 1508 1509 InnerConnection(LoadedApk.ServiceDispatcher sd) { 1510 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); 1511 } 1512 1513 public void connected(ComponentName name, IBinder service) throws RemoteException { 1514 LoadedApk.ServiceDispatcher sd = mDispatcher.get(); 1515 if (sd != null) { 1516 sd.connected(name, service); 1517 } 1518 } 1519 } 1520 1521 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections 1522 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>(); 1523 1524 ServiceDispatcher(ServiceConnection conn, 1525 Context context, Handler activityThread, int flags) { 1526 mIServiceConnection = new InnerConnection(this); 1527 mConnection = conn; 1528 mContext = context; 1529 mActivityThread = activityThread; 1530 mLocation = new ServiceConnectionLeaked(null); 1531 mLocation.fillInStackTrace(); 1532 mFlags = flags; 1533 } 1534 1535 void validate(Context context, Handler activityThread) { 1536 if (mContext != context) { 1537 throw new RuntimeException( 1538 "ServiceConnection " + mConnection + 1539 " registered with differing Context (was " + 1540 mContext + " now " + context + ")"); 1541 } 1542 if (mActivityThread != activityThread) { 1543 throw new RuntimeException( 1544 "ServiceConnection " + mConnection + 1545 " registered with differing handler (was " + 1546 mActivityThread + " now " + activityThread + ")"); 1547 } 1548 } 1549 1550 void doForget() { 1551 synchronized(this) { 1552 for (int i=0; i<mActiveConnections.size(); i++) { 1553 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i); 1554 ci.binder.unlinkToDeath(ci.deathMonitor, 0); 1555 } 1556 mActiveConnections.clear(); 1557 mForgotten = true; 1558 } 1559 } 1560 1561 ServiceConnectionLeaked getLocation() { 1562 return mLocation; 1563 } 1564 1565 ServiceConnection getServiceConnection() { 1566 return mConnection; 1567 } 1568 1569 IServiceConnection getIServiceConnection() { 1570 return mIServiceConnection; 1571 } 1572 1573 int getFlags() { 1574 return mFlags; 1575 } 1576 1577 void setUnbindLocation(RuntimeException ex) { 1578 mUnbindLocation = ex; 1579 } 1580 1581 RuntimeException getUnbindLocation() { 1582 return mUnbindLocation; 1583 } 1584 1585 public void connected(ComponentName name, IBinder service) { 1586 if (mActivityThread != null) { 1587 mActivityThread.post(new RunConnection(name, service, 0)); 1588 } else { 1589 doConnected(name, service); 1590 } 1591 } 1592 1593 public void death(ComponentName name, IBinder service) { 1594 if (mActivityThread != null) { 1595 mActivityThread.post(new RunConnection(name, service, 1)); 1596 } else { 1597 doDeath(name, service); 1598 } 1599 } 1600 1601 public void doConnected(ComponentName name, IBinder service) { 1602 ServiceDispatcher.ConnectionInfo old; 1603 ServiceDispatcher.ConnectionInfo info; 1604 1605 synchronized (this) { 1606 if (mForgotten) { 1607 // We unbound before receiving the connection; ignore 1608 // any connection received. 1609 return; 1610 } 1611 old = mActiveConnections.get(name); 1612 if (old != null && old.binder == service) { 1613 // Huh, already have this one. Oh well! 1614 return; 1615 } 1616 1617 if (service != null) { 1618 // A new service is being connected... set it all up. 1619 info = new ConnectionInfo(); 1620 info.binder = service; 1621 info.deathMonitor = new DeathMonitor(name, service); 1622 try { 1623 service.linkToDeath(info.deathMonitor, 0); 1624 mActiveConnections.put(name, info); 1625 } catch (RemoteException e) { 1626 // This service was dead before we got it... just 1627 // don't do anything with it. 1628 mActiveConnections.remove(name); 1629 return; 1630 } 1631 1632 } else { 1633 // The named service is being disconnected... clean up. 1634 mActiveConnections.remove(name); 1635 } 1636 1637 if (old != null) { 1638 old.binder.unlinkToDeath(old.deathMonitor, 0); 1639 } 1640 } 1641 1642 // If there was an old service, it is now disconnected. 1643 if (old != null) { 1644 mConnection.onServiceDisconnected(name); 1645 } 1646 // If there is a new service, it is now connected. 1647 if (service != null) { 1648 mConnection.onServiceConnected(name, service); 1649 } 1650 } 1651 1652 public void doDeath(ComponentName name, IBinder service) { 1653 synchronized (this) { 1654 ConnectionInfo old = mActiveConnections.get(name); 1655 if (old == null || old.binder != service) { 1656 // Death for someone different than who we last 1657 // reported... just ignore it. 1658 return; 1659 } 1660 mActiveConnections.remove(name); 1661 old.binder.unlinkToDeath(old.deathMonitor, 0); 1662 } 1663 1664 mConnection.onServiceDisconnected(name); 1665 } 1666 1667 private final class RunConnection implements Runnable { 1668 RunConnection(ComponentName name, IBinder service, int command) { 1669 mName = name; 1670 mService = service; 1671 mCommand = command; 1672 } 1673 1674 public void run() { 1675 if (mCommand == 0) { 1676 doConnected(mName, mService); 1677 } else if (mCommand == 1) { 1678 doDeath(mName, mService); 1679 } 1680 } 1681 1682 final ComponentName mName; 1683 final IBinder mService; 1684 final int mCommand; 1685 } 1686 1687 private final class DeathMonitor implements IBinder.DeathRecipient 1688 { 1689 DeathMonitor(ComponentName name, IBinder service) { 1690 mName = name; 1691 mService = service; 1692 } 1693 1694 public void binderDied() { 1695 death(mName, mService); 1696 } 1697 1698 final ComponentName mName; 1699 final IBinder mService; 1700 } 1701 } 1702} 1703