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