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