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