LoadedApk.java revision 1bea237aa296a35c263f0c4965ba0f5a140cd848
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.util.ArrayList; 68import java.util.Arrays; 69import java.util.Collections; 70import java.util.Enumeration; 71import java.util.List; 72import java.util.Objects; 73 74final class IntentReceiverLeaked extends AndroidRuntimeException { 75 public IntentReceiverLeaked(String msg) { 76 super(msg); 77 } 78} 79 80final class ServiceConnectionLeaked extends AndroidRuntimeException { 81 public ServiceConnectionLeaked(String msg) { 82 super(msg); 83 } 84} 85 86/** 87 * Local state maintained about a currently loaded .apk. 88 * @hide 89 */ 90public final class LoadedApk { 91 static final String TAG = "LoadedApk"; 92 static final boolean DEBUG = false; 93 private static final String PROPERTY_NAME_APPEND_NATIVE = "pi.append_native_lib_paths"; 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 if (isBundledApp) { 672 // This is necessary to grant bundled apps access to 673 // libraries located in subdirectories of /system/lib 674 libraryPermittedPath += File.pathSeparator + defaultSearchPaths; 675 } 676 677 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths); 678 679 // If we're not asked to include code, we construct a classloader that has 680 // no code path included. We still need to set up the library search paths 681 // and permitted path because NativeActivity relies on it (it attempts to 682 // call System.loadLibrary() on a classloader from a LoadedApk with 683 // mIncludeCode == false). 684 if (!mIncludeCode) { 685 if (mClassLoader == null) { 686 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); 687 mClassLoader = ApplicationLoaders.getDefault().getClassLoader( 688 "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp, 689 librarySearchPath, libraryPermittedPath, mBaseClassLoader, 690 null /* classLoaderName */); 691 StrictMode.setThreadPolicy(oldPolicy); 692 mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader); 693 } 694 695 return; 696 } 697 698 /* 699 * With all the combination done (if necessary, actually create the java class 700 * loader and set up JIT profiling support if necessary. 701 * 702 * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils. 703 */ 704 final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) : 705 TextUtils.join(File.pathSeparator, zipPaths); 706 707 if (DEBUG) Slog.v(ActivityThread.TAG, "Class path: " + zip + 708 ", JNI path: " + librarySearchPath); 709 710 boolean needToSetupJitProfiles = false; 711 if (mClassLoader == null) { 712 // Temporarily disable logging of disk reads on the Looper thread 713 // as this is early and necessary. 714 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); 715 716 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, 717 mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath, 718 libraryPermittedPath, mBaseClassLoader, 719 mApplicationInfo.classLoaderName); 720 mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader); 721 722 StrictMode.setThreadPolicy(oldPolicy); 723 // Setup the class loader paths for profiling. 724 needToSetupJitProfiles = true; 725 } 726 727 if (!libPaths.isEmpty() && SystemProperties.getBoolean(PROPERTY_NAME_APPEND_NATIVE, true)) { 728 ApplicationLoaders.getDefault().addNative(mClassLoader, libPaths); 729 } 730 731 if (addedPaths != null && addedPaths.size() > 0) { 732 final String add = TextUtils.join(File.pathSeparator, addedPaths); 733 ApplicationLoaders.getDefault().addPath(mClassLoader, add); 734 // Setup the new code paths for profiling. 735 needToSetupJitProfiles = true; 736 } 737 738 // Setup jit profile support. 739 // 740 // It is ok to call this multiple times if the application gets updated with new splits. 741 // The runtime only keeps track of unique code paths and can handle re-registration of 742 // the same code path. There's no need to pass `addedPaths` since any new code paths 743 // are already in `mApplicationInfo`. 744 // 745 // It is NOT ok to call this function from the system_server (for any of the packages it 746 // loads code from) so we explicitly disallow it there. 747 if (needToSetupJitProfiles && !ActivityThread.isSystem()) { 748 setupJitProfileSupport(); 749 } 750 } 751 752 public ClassLoader getClassLoader() { 753 synchronized (this) { 754 if (mClassLoader == null) { 755 createOrUpdateClassLoaderLocked(null /*addedPaths*/); 756 } 757 return mClassLoader; 758 } 759 } 760 761 private void setupJitProfileSupport() { 762 if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) { 763 return; 764 } 765 // Only set up profile support if the loaded apk has the same uid as the 766 // current process. 767 // Currently, we do not support profiling across different apps. 768 // (e.g. application's uid might be different when the code is 769 // loaded by another app via createApplicationContext) 770 if (mApplicationInfo.uid != Process.myUid()) { 771 return; 772 } 773 774 final List<String> codePaths = new ArrayList<>(); 775 if ((mApplicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) { 776 codePaths.add(mApplicationInfo.sourceDir); 777 } 778 if (mApplicationInfo.splitSourceDirs != null) { 779 Collections.addAll(codePaths, mApplicationInfo.splitSourceDirs); 780 } 781 782 if (codePaths.isEmpty()) { 783 // If there are no code paths there's no need to setup a profile file and register with 784 // the runtime, 785 return; 786 } 787 788 for (int i = codePaths.size() - 1; i >= 0; i--) { 789 String splitName = i == 0 ? null : mApplicationInfo.splitNames[i - 1]; 790 String profileFile = ArtManager.getCurrentProfilePath( 791 mPackageName, UserHandle.myUserId(), splitName); 792 VMRuntime.registerAppInfo(profileFile, new String[] {codePaths.get(i)}); 793 } 794 795 // Register the app data directory with the reporter. It will 796 // help deciding whether or not a dex file is the primary apk or a 797 // secondary dex. 798 DexLoadReporter.getInstance().registerAppDataDir(mPackageName, mDataDir); 799 } 800 801 /** 802 * Setup value for Thread.getContextClassLoader(). If the 803 * package will not run in in a VM with other packages, we set 804 * the Java context ClassLoader to the 805 * PackageInfo.getClassLoader value. However, if this VM can 806 * contain multiple packages, we intead set the Java context 807 * ClassLoader to a proxy that will warn about the use of Java 808 * context ClassLoaders and then fall through to use the 809 * system ClassLoader. 810 * 811 * <p> Note that this is similar to but not the same as the 812 * android.content.Context.getClassLoader(). While both 813 * context class loaders are typically set to the 814 * PathClassLoader used to load the package archive in the 815 * single application per VM case, a single Android process 816 * may contain several Contexts executing on one thread with 817 * their own logical ClassLoaders while the Java context 818 * ClassLoader is a thread local. This is why in the case when 819 * we have multiple packages per VM we do not set the Java 820 * context ClassLoader to an arbitrary but instead warn the 821 * user to set their own if we detect that they are using a 822 * Java library that expects it to be set. 823 */ 824 private void initializeJavaContextClassLoader() { 825 IPackageManager pm = ActivityThread.getPackageManager(); 826 android.content.pm.PackageInfo pi; 827 try { 828 pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 829 UserHandle.myUserId()); 830 } catch (RemoteException e) { 831 throw e.rethrowFromSystemServer(); 832 } 833 if (pi == null) { 834 throw new IllegalStateException("Unable to get package info for " 835 + mPackageName + "; is package not installed?"); 836 } 837 /* 838 * Two possible indications that this package could be 839 * sharing its virtual machine with other packages: 840 * 841 * 1.) the sharedUserId attribute is set in the manifest, 842 * indicating a request to share a VM with other 843 * packages with the same sharedUserId. 844 * 845 * 2.) the application element of the manifest has an 846 * attribute specifying a non-default process name, 847 * indicating the desire to run in another packages VM. 848 */ 849 boolean sharedUserIdSet = (pi.sharedUserId != null); 850 boolean processNameNotDefault = 851 (pi.applicationInfo != null && 852 !mPackageName.equals(pi.applicationInfo.processName)); 853 boolean sharable = (sharedUserIdSet || processNameNotDefault); 854 ClassLoader contextClassLoader = 855 (sharable) 856 ? new WarningContextClassLoader() 857 : mClassLoader; 858 Thread.currentThread().setContextClassLoader(contextClassLoader); 859 } 860 861 private static class WarningContextClassLoader extends ClassLoader { 862 863 private static boolean warned = false; 864 865 private void warn(String methodName) { 866 if (warned) { 867 return; 868 } 869 warned = true; 870 Thread.currentThread().setContextClassLoader(getParent()); 871 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " + 872 "The class loader returned by " + 873 "Thread.getContextClassLoader() may fail for processes " + 874 "that host multiple applications. You should explicitly " + 875 "specify a context class loader. For example: " + 876 "Thread.setContextClassLoader(getClass().getClassLoader());"); 877 } 878 879 @Override public URL getResource(String resName) { 880 warn("getResource"); 881 return getParent().getResource(resName); 882 } 883 884 @Override public Enumeration<URL> getResources(String resName) throws IOException { 885 warn("getResources"); 886 return getParent().getResources(resName); 887 } 888 889 @Override public InputStream getResourceAsStream(String resName) { 890 warn("getResourceAsStream"); 891 return getParent().getResourceAsStream(resName); 892 } 893 894 @Override public Class<?> loadClass(String className) throws ClassNotFoundException { 895 warn("loadClass"); 896 return getParent().loadClass(className); 897 } 898 899 @Override public void setClassAssertionStatus(String cname, boolean enable) { 900 warn("setClassAssertionStatus"); 901 getParent().setClassAssertionStatus(cname, enable); 902 } 903 904 @Override public void setPackageAssertionStatus(String pname, boolean enable) { 905 warn("setPackageAssertionStatus"); 906 getParent().setPackageAssertionStatus(pname, enable); 907 } 908 909 @Override public void setDefaultAssertionStatus(boolean enable) { 910 warn("setDefaultAssertionStatus"); 911 getParent().setDefaultAssertionStatus(enable); 912 } 913 914 @Override public void clearAssertionStatus() { 915 warn("clearAssertionStatus"); 916 getParent().clearAssertionStatus(); 917 } 918 } 919 920 public String getAppDir() { 921 return mAppDir; 922 } 923 924 public String getLibDir() { 925 return mLibDir; 926 } 927 928 public String getResDir() { 929 return mResDir; 930 } 931 932 public String[] getSplitAppDirs() { 933 return mSplitAppDirs; 934 } 935 936 public String[] getSplitResDirs() { 937 return mSplitResDirs; 938 } 939 940 public String[] getOverlayDirs() { 941 return mOverlayDirs; 942 } 943 944 public String getDataDir() { 945 return mDataDir; 946 } 947 948 public File getDataDirFile() { 949 return mDataDirFile; 950 } 951 952 public File getDeviceProtectedDataDirFile() { 953 return mDeviceProtectedDataDirFile; 954 } 955 956 public File getCredentialProtectedDataDirFile() { 957 return mCredentialProtectedDataDirFile; 958 } 959 960 public AssetManager getAssets() { 961 return getResources().getAssets(); 962 } 963 964 public Resources getResources() { 965 if (mResources == null) { 966 final String[] splitPaths; 967 try { 968 splitPaths = getSplitPaths(null); 969 } catch (NameNotFoundException e) { 970 // This should never fail. 971 throw new AssertionError("null split not found"); 972 } 973 974 mResources = ResourcesManager.getInstance().getResources(null, mResDir, 975 splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles, 976 Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(), 977 getClassLoader()); 978 } 979 return mResources; 980 } 981 982 public Application makeApplication(boolean forceDefaultAppClass, 983 Instrumentation instrumentation) { 984 if (mApplication != null) { 985 return mApplication; 986 } 987 988 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication"); 989 990 Application app = null; 991 992 String appClass = mApplicationInfo.className; 993 if (forceDefaultAppClass || (appClass == null)) { 994 appClass = "android.app.Application"; 995 } 996 997 try { 998 java.lang.ClassLoader cl = getClassLoader(); 999 if (!mPackageName.equals("android")) { 1000 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 1001 "initializeJavaContextClassLoader"); 1002 initializeJavaContextClassLoader(); 1003 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1004 } 1005 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); 1006 app = mActivityThread.mInstrumentation.newApplication( 1007 cl, appClass, appContext); 1008 appContext.setOuterContext(app); 1009 } catch (Exception e) { 1010 if (!mActivityThread.mInstrumentation.onException(app, e)) { 1011 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1012 throw new RuntimeException( 1013 "Unable to instantiate application " + appClass 1014 + ": " + e.toString(), e); 1015 } 1016 } 1017 mActivityThread.mAllApplications.add(app); 1018 mApplication = app; 1019 1020 if (instrumentation != null) { 1021 try { 1022 instrumentation.callApplicationOnCreate(app); 1023 } catch (Exception e) { 1024 if (!instrumentation.onException(app, e)) { 1025 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1026 throw new RuntimeException( 1027 "Unable to create application " + app.getClass().getName() 1028 + ": " + e.toString(), e); 1029 } 1030 } 1031 } 1032 1033 // Rewrite the R 'constants' for all library apks. 1034 SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(); 1035 final int N = packageIdentifiers.size(); 1036 for (int i = 0; i < N; i++) { 1037 final int id = packageIdentifiers.keyAt(i); 1038 if (id == 0x01 || id == 0x7f) { 1039 continue; 1040 } 1041 1042 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id); 1043 } 1044 1045 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1046 1047 return app; 1048 } 1049 1050 private void rewriteRValues(ClassLoader cl, String packageName, int id) { 1051 final Class<?> rClazz; 1052 try { 1053 rClazz = cl.loadClass(packageName + ".R"); 1054 } catch (ClassNotFoundException e) { 1055 // This is not necessarily an error, as some packages do not ship with resources 1056 // (or they do not need rewriting). 1057 Log.i(TAG, "No resource references to update in package " + packageName); 1058 return; 1059 } 1060 1061 final Method callback; 1062 try { 1063 callback = rClazz.getMethod("onResourcesLoaded", int.class); 1064 } catch (NoSuchMethodException e) { 1065 // No rewriting to be done. 1066 return; 1067 } 1068 1069 Throwable cause; 1070 try { 1071 callback.invoke(null, id); 1072 return; 1073 } catch (IllegalAccessException e) { 1074 cause = e; 1075 } catch (InvocationTargetException e) { 1076 cause = e.getCause(); 1077 } 1078 1079 throw new RuntimeException("Failed to rewrite resource references for " + packageName, 1080 cause); 1081 } 1082 1083 public void removeContextRegistrations(Context context, 1084 String who, String what) { 1085 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled(); 1086 synchronized (mReceivers) { 1087 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap = 1088 mReceivers.remove(context); 1089 if (rmap != null) { 1090 for (int i = 0; i < rmap.size(); i++) { 1091 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i); 1092 IntentReceiverLeaked leak = new IntentReceiverLeaked( 1093 what + " " + who + " has leaked IntentReceiver " 1094 + rd.getIntentReceiver() + " that was " + 1095 "originally registered here. Are you missing a " + 1096 "call to unregisterReceiver()?"); 1097 leak.setStackTrace(rd.getLocation().getStackTrace()); 1098 Slog.e(ActivityThread.TAG, leak.getMessage(), leak); 1099 if (reportRegistrationLeaks) { 1100 StrictMode.onIntentReceiverLeaked(leak); 1101 } 1102 try { 1103 ActivityManager.getService().unregisterReceiver( 1104 rd.getIIntentReceiver()); 1105 } catch (RemoteException e) { 1106 throw e.rethrowFromSystemServer(); 1107 } 1108 } 1109 } 1110 mUnregisteredReceivers.remove(context); 1111 } 1112 1113 synchronized (mServices) { 1114 //Slog.i(TAG, "Receiver registrations: " + mReceivers); 1115 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap = 1116 mServices.remove(context); 1117 if (smap != null) { 1118 for (int i = 0; i < smap.size(); i++) { 1119 LoadedApk.ServiceDispatcher sd = smap.valueAt(i); 1120 ServiceConnectionLeaked leak = new ServiceConnectionLeaked( 1121 what + " " + who + " has leaked ServiceConnection " 1122 + sd.getServiceConnection() + " that was originally bound here"); 1123 leak.setStackTrace(sd.getLocation().getStackTrace()); 1124 Slog.e(ActivityThread.TAG, leak.getMessage(), leak); 1125 if (reportRegistrationLeaks) { 1126 StrictMode.onServiceConnectionLeaked(leak); 1127 } 1128 try { 1129 ActivityManager.getService().unbindService( 1130 sd.getIServiceConnection()); 1131 } catch (RemoteException e) { 1132 throw e.rethrowFromSystemServer(); 1133 } 1134 sd.doForget(); 1135 } 1136 } 1137 mUnboundServices.remove(context); 1138 //Slog.i(TAG, "Service registrations: " + mServices); 1139 } 1140 } 1141 1142 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r, 1143 Context context, Handler handler, 1144 Instrumentation instrumentation, boolean registered) { 1145 synchronized (mReceivers) { 1146 LoadedApk.ReceiverDispatcher rd = null; 1147 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null; 1148 if (registered) { 1149 map = mReceivers.get(context); 1150 if (map != null) { 1151 rd = map.get(r); 1152 } 1153 } 1154 if (rd == null) { 1155 rd = new ReceiverDispatcher(r, context, handler, 1156 instrumentation, registered); 1157 if (registered) { 1158 if (map == null) { 1159 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); 1160 mReceivers.put(context, map); 1161 } 1162 map.put(r, rd); 1163 } 1164 } else { 1165 rd.validate(context, handler); 1166 } 1167 rd.mForgotten = false; 1168 return rd.getIIntentReceiver(); 1169 } 1170 } 1171 1172 public IIntentReceiver forgetReceiverDispatcher(Context context, 1173 BroadcastReceiver r) { 1174 synchronized (mReceivers) { 1175 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context); 1176 LoadedApk.ReceiverDispatcher rd = null; 1177 if (map != null) { 1178 rd = map.get(r); 1179 if (rd != null) { 1180 map.remove(r); 1181 if (map.size() == 0) { 1182 mReceivers.remove(context); 1183 } 1184 if (r.getDebugUnregister()) { 1185 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder 1186 = mUnregisteredReceivers.get(context); 1187 if (holder == null) { 1188 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); 1189 mUnregisteredReceivers.put(context, holder); 1190 } 1191 RuntimeException ex = new IllegalArgumentException( 1192 "Originally unregistered here:"); 1193 ex.fillInStackTrace(); 1194 rd.setUnregisterLocation(ex); 1195 holder.put(r, rd); 1196 } 1197 rd.mForgotten = true; 1198 return rd.getIIntentReceiver(); 1199 } 1200 } 1201 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder 1202 = mUnregisteredReceivers.get(context); 1203 if (holder != null) { 1204 rd = holder.get(r); 1205 if (rd != null) { 1206 RuntimeException ex = rd.getUnregisterLocation(); 1207 throw new IllegalArgumentException( 1208 "Unregistering Receiver " + r 1209 + " that was already unregistered", ex); 1210 } 1211 } 1212 if (context == null) { 1213 throw new IllegalStateException("Unbinding Receiver " + r 1214 + " from Context that is no longer in use: " + context); 1215 } else { 1216 throw new IllegalArgumentException("Receiver not registered: " + r); 1217 } 1218 1219 } 1220 } 1221 1222 static final class ReceiverDispatcher { 1223 1224 final static class InnerReceiver extends IIntentReceiver.Stub { 1225 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher; 1226 final LoadedApk.ReceiverDispatcher mStrongRef; 1227 1228 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { 1229 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); 1230 mStrongRef = strong ? rd : null; 1231 } 1232 1233 @Override 1234 public void performReceive(Intent intent, int resultCode, String data, 1235 Bundle extras, boolean ordered, boolean sticky, int sendingUser) { 1236 final LoadedApk.ReceiverDispatcher rd; 1237 if (intent == null) { 1238 Log.wtf(TAG, "Null intent received"); 1239 rd = null; 1240 } else { 1241 rd = mDispatcher.get(); 1242 } 1243 if (ActivityThread.DEBUG_BROADCAST) { 1244 int seq = intent.getIntExtra("seq", -1); 1245 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() 1246 + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null)); 1247 } 1248 if (rd != null) { 1249 rd.performReceive(intent, resultCode, data, extras, 1250 ordered, sticky, sendingUser); 1251 } else { 1252 // The activity manager dispatched a broadcast to a registered 1253 // receiver in this process, but before it could be delivered the 1254 // receiver was unregistered. Acknowledge the broadcast on its 1255 // behalf so that the system's broadcast sequence can continue. 1256 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1257 "Finishing broadcast to unregistered receiver"); 1258 IActivityManager mgr = ActivityManager.getService(); 1259 try { 1260 if (extras != null) { 1261 extras.setAllowFds(false); 1262 } 1263 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags()); 1264 } catch (RemoteException e) { 1265 throw e.rethrowFromSystemServer(); 1266 } 1267 } 1268 } 1269 } 1270 1271 final IIntentReceiver.Stub mIIntentReceiver; 1272 final BroadcastReceiver mReceiver; 1273 final Context mContext; 1274 final Handler mActivityThread; 1275 final Instrumentation mInstrumentation; 1276 final boolean mRegistered; 1277 final IntentReceiverLeaked mLocation; 1278 RuntimeException mUnregisterLocation; 1279 boolean mForgotten; 1280 1281 final class Args extends BroadcastReceiver.PendingResult { 1282 private Intent mCurIntent; 1283 private final boolean mOrdered; 1284 private boolean mDispatched; 1285 private Throwable mPreviousRunStacktrace; // To investigate b/37809561. STOPSHIP remove. 1286 1287 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, 1288 boolean ordered, boolean sticky, int sendingUser) { 1289 super(resultCode, resultData, resultExtras, 1290 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered, 1291 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags()); 1292 mCurIntent = intent; 1293 mOrdered = ordered; 1294 } 1295 1296 public final Runnable getRunnable() { 1297 return () -> { 1298 final BroadcastReceiver receiver = mReceiver; 1299 final boolean ordered = mOrdered; 1300 1301 if (ActivityThread.DEBUG_BROADCAST) { 1302 int seq = mCurIntent.getIntExtra("seq", -1); 1303 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction() 1304 + " seq=" + seq + " to " + mReceiver); 1305 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered 1306 + " mOrderedHint=" + ordered); 1307 } 1308 1309 final IActivityManager mgr = ActivityManager.getService(); 1310 final Intent intent = mCurIntent; 1311 if (intent == null) { 1312 Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched 1313 + ": run() previously called at " 1314 + Log.getStackTraceString(mPreviousRunStacktrace)); 1315 } 1316 1317 mCurIntent = null; 1318 mDispatched = true; 1319 mPreviousRunStacktrace = new Throwable("Previous stacktrace"); 1320 if (receiver == null || intent == null || mForgotten) { 1321 if (mRegistered && ordered) { 1322 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1323 "Finishing null broadcast to " + mReceiver); 1324 sendFinished(mgr); 1325 } 1326 return; 1327 } 1328 1329 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg"); 1330 try { 1331 ClassLoader cl = mReceiver.getClass().getClassLoader(); 1332 intent.setExtrasClassLoader(cl); 1333 intent.prepareToEnterProcess(); 1334 setExtrasClassLoader(cl); 1335 receiver.setPendingResult(this); 1336 receiver.onReceive(mContext, intent); 1337 } catch (Exception e) { 1338 if (mRegistered && ordered) { 1339 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1340 "Finishing failed broadcast to " + mReceiver); 1341 sendFinished(mgr); 1342 } 1343 if (mInstrumentation == null || 1344 !mInstrumentation.onException(mReceiver, e)) { 1345 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1346 throw new RuntimeException( 1347 "Error receiving broadcast " + intent 1348 + " in " + mReceiver, e); 1349 } 1350 } 1351 1352 if (receiver.getPendingResult() != null) { 1353 finish(); 1354 } 1355 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1356 }; 1357 } 1358 } 1359 1360 ReceiverDispatcher(BroadcastReceiver receiver, Context context, 1361 Handler activityThread, Instrumentation instrumentation, 1362 boolean registered) { 1363 if (activityThread == null) { 1364 throw new NullPointerException("Handler must not be null"); 1365 } 1366 1367 mIIntentReceiver = new InnerReceiver(this, !registered); 1368 mReceiver = receiver; 1369 mContext = context; 1370 mActivityThread = activityThread; 1371 mInstrumentation = instrumentation; 1372 mRegistered = registered; 1373 mLocation = new IntentReceiverLeaked(null); 1374 mLocation.fillInStackTrace(); 1375 } 1376 1377 void validate(Context context, Handler activityThread) { 1378 if (mContext != context) { 1379 throw new IllegalStateException( 1380 "Receiver " + mReceiver + 1381 " registered with differing Context (was " + 1382 mContext + " now " + context + ")"); 1383 } 1384 if (mActivityThread != activityThread) { 1385 throw new IllegalStateException( 1386 "Receiver " + mReceiver + 1387 " registered with differing handler (was " + 1388 mActivityThread + " now " + activityThread + ")"); 1389 } 1390 } 1391 1392 IntentReceiverLeaked getLocation() { 1393 return mLocation; 1394 } 1395 1396 BroadcastReceiver getIntentReceiver() { 1397 return mReceiver; 1398 } 1399 1400 IIntentReceiver getIIntentReceiver() { 1401 return mIIntentReceiver; 1402 } 1403 1404 void setUnregisterLocation(RuntimeException ex) { 1405 mUnregisterLocation = ex; 1406 } 1407 1408 RuntimeException getUnregisterLocation() { 1409 return mUnregisterLocation; 1410 } 1411 1412 public void performReceive(Intent intent, int resultCode, String data, 1413 Bundle extras, boolean ordered, boolean sticky, int sendingUser) { 1414 final Args args = new Args(intent, resultCode, data, extras, ordered, 1415 sticky, sendingUser); 1416 if (intent == null) { 1417 Log.wtf(TAG, "Null intent received"); 1418 } else { 1419 if (ActivityThread.DEBUG_BROADCAST) { 1420 int seq = intent.getIntExtra("seq", -1); 1421 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() 1422 + " seq=" + seq + " to " + mReceiver); 1423 } 1424 } 1425 if (intent == null || !mActivityThread.post(args.getRunnable())) { 1426 if (mRegistered && ordered) { 1427 IActivityManager mgr = ActivityManager.getService(); 1428 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1429 "Finishing sync broadcast to " + mReceiver); 1430 args.sendFinished(mgr); 1431 } 1432 } 1433 } 1434 1435 } 1436 1437 public final IServiceConnection getServiceDispatcher(ServiceConnection c, 1438 Context context, Handler handler, int flags) { 1439 synchronized (mServices) { 1440 LoadedApk.ServiceDispatcher sd = null; 1441 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); 1442 if (map != null) { 1443 if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c); 1444 sd = map.get(c); 1445 } 1446 if (sd == null) { 1447 sd = new ServiceDispatcher(c, context, handler, flags); 1448 if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c); 1449 if (map == null) { 1450 map = new ArrayMap<>(); 1451 mServices.put(context, map); 1452 } 1453 map.put(c, sd); 1454 } else { 1455 sd.validate(context, handler); 1456 } 1457 return sd.getIServiceConnection(); 1458 } 1459 } 1460 1461 public final IServiceConnection forgetServiceDispatcher(Context context, 1462 ServiceConnection c) { 1463 synchronized (mServices) { 1464 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map 1465 = mServices.get(context); 1466 LoadedApk.ServiceDispatcher sd = null; 1467 if (map != null) { 1468 sd = map.get(c); 1469 if (sd != null) { 1470 if (DEBUG) Slog.d(TAG, "Removing dispatcher " + sd + " for conn " + c); 1471 map.remove(c); 1472 sd.doForget(); 1473 if (map.size() == 0) { 1474 mServices.remove(context); 1475 } 1476 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) { 1477 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder 1478 = mUnboundServices.get(context); 1479 if (holder == null) { 1480 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); 1481 mUnboundServices.put(context, holder); 1482 } 1483 RuntimeException ex = new IllegalArgumentException( 1484 "Originally unbound here:"); 1485 ex.fillInStackTrace(); 1486 sd.setUnbindLocation(ex); 1487 holder.put(c, sd); 1488 } 1489 return sd.getIServiceConnection(); 1490 } 1491 } 1492 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder 1493 = mUnboundServices.get(context); 1494 if (holder != null) { 1495 sd = holder.get(c); 1496 if (sd != null) { 1497 RuntimeException ex = sd.getUnbindLocation(); 1498 throw new IllegalArgumentException( 1499 "Unbinding Service " + c 1500 + " that was already unbound", ex); 1501 } 1502 } 1503 if (context == null) { 1504 throw new IllegalStateException("Unbinding Service " + c 1505 + " from Context that is no longer in use: " + context); 1506 } else { 1507 throw new IllegalArgumentException("Service not registered: " + c); 1508 } 1509 } 1510 } 1511 1512 static final class ServiceDispatcher { 1513 private final ServiceDispatcher.InnerConnection mIServiceConnection; 1514 private final ServiceConnection mConnection; 1515 private final Context mContext; 1516 private final Handler mActivityThread; 1517 private final ServiceConnectionLeaked mLocation; 1518 private final int mFlags; 1519 1520 private RuntimeException mUnbindLocation; 1521 1522 private boolean mForgotten; 1523 1524 private static class ConnectionInfo { 1525 IBinder binder; 1526 IBinder.DeathRecipient deathMonitor; 1527 } 1528 1529 private static class InnerConnection extends IServiceConnection.Stub { 1530 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; 1531 1532 InnerConnection(LoadedApk.ServiceDispatcher sd) { 1533 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); 1534 } 1535 1536 public void connected(ComponentName name, IBinder service, boolean dead) 1537 throws RemoteException { 1538 LoadedApk.ServiceDispatcher sd = mDispatcher.get(); 1539 if (sd != null) { 1540 sd.connected(name, service, dead); 1541 } 1542 } 1543 } 1544 1545 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections 1546 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>(); 1547 1548 ServiceDispatcher(ServiceConnection conn, 1549 Context context, Handler activityThread, int flags) { 1550 mIServiceConnection = new InnerConnection(this); 1551 mConnection = conn; 1552 mContext = context; 1553 mActivityThread = activityThread; 1554 mLocation = new ServiceConnectionLeaked(null); 1555 mLocation.fillInStackTrace(); 1556 mFlags = flags; 1557 } 1558 1559 void validate(Context context, Handler activityThread) { 1560 if (mContext != context) { 1561 throw new RuntimeException( 1562 "ServiceConnection " + mConnection + 1563 " registered with differing Context (was " + 1564 mContext + " now " + context + ")"); 1565 } 1566 if (mActivityThread != activityThread) { 1567 throw new RuntimeException( 1568 "ServiceConnection " + mConnection + 1569 " registered with differing handler (was " + 1570 mActivityThread + " now " + activityThread + ")"); 1571 } 1572 } 1573 1574 void doForget() { 1575 synchronized(this) { 1576 for (int i=0; i<mActiveConnections.size(); i++) { 1577 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i); 1578 ci.binder.unlinkToDeath(ci.deathMonitor, 0); 1579 } 1580 mActiveConnections.clear(); 1581 mForgotten = true; 1582 } 1583 } 1584 1585 ServiceConnectionLeaked getLocation() { 1586 return mLocation; 1587 } 1588 1589 ServiceConnection getServiceConnection() { 1590 return mConnection; 1591 } 1592 1593 IServiceConnection getIServiceConnection() { 1594 return mIServiceConnection; 1595 } 1596 1597 int getFlags() { 1598 return mFlags; 1599 } 1600 1601 void setUnbindLocation(RuntimeException ex) { 1602 mUnbindLocation = ex; 1603 } 1604 1605 RuntimeException getUnbindLocation() { 1606 return mUnbindLocation; 1607 } 1608 1609 public void connected(ComponentName name, IBinder service, boolean dead) { 1610 if (mActivityThread != null) { 1611 mActivityThread.post(new RunConnection(name, service, 0, dead)); 1612 } else { 1613 doConnected(name, service, dead); 1614 } 1615 } 1616 1617 public void death(ComponentName name, IBinder service) { 1618 if (mActivityThread != null) { 1619 mActivityThread.post(new RunConnection(name, service, 1, false)); 1620 } else { 1621 doDeath(name, service); 1622 } 1623 } 1624 1625 public void doConnected(ComponentName name, IBinder service, boolean dead) { 1626 ServiceDispatcher.ConnectionInfo old; 1627 ServiceDispatcher.ConnectionInfo info; 1628 1629 synchronized (this) { 1630 if (mForgotten) { 1631 // We unbound before receiving the connection; ignore 1632 // any connection received. 1633 return; 1634 } 1635 old = mActiveConnections.get(name); 1636 if (old != null && old.binder == service) { 1637 // Huh, already have this one. Oh well! 1638 return; 1639 } 1640 1641 if (service != null) { 1642 // A new service is being connected... set it all up. 1643 info = new ConnectionInfo(); 1644 info.binder = service; 1645 info.deathMonitor = new DeathMonitor(name, service); 1646 try { 1647 service.linkToDeath(info.deathMonitor, 0); 1648 mActiveConnections.put(name, info); 1649 } catch (RemoteException e) { 1650 // This service was dead before we got it... just 1651 // don't do anything with it. 1652 mActiveConnections.remove(name); 1653 return; 1654 } 1655 1656 } else { 1657 // The named service is being disconnected... clean up. 1658 mActiveConnections.remove(name); 1659 } 1660 1661 if (old != null) { 1662 old.binder.unlinkToDeath(old.deathMonitor, 0); 1663 } 1664 } 1665 1666 // If there was an old service, it is now disconnected. 1667 if (old != null) { 1668 mConnection.onServiceDisconnected(name); 1669 } 1670 if (dead) { 1671 mConnection.onBindingDied(name); 1672 } 1673 // If there is a new viable service, it is now connected. 1674 if (service != null) { 1675 mConnection.onServiceConnected(name, service); 1676 } else { 1677 // The binding machinery worked, but the remote returned null from onBind(). 1678 mConnection.onNullBinding(name); 1679 } 1680 } 1681 1682 public void doDeath(ComponentName name, IBinder service) { 1683 synchronized (this) { 1684 ConnectionInfo old = mActiveConnections.get(name); 1685 if (old == null || old.binder != service) { 1686 // Death for someone different than who we last 1687 // reported... just ignore it. 1688 return; 1689 } 1690 mActiveConnections.remove(name); 1691 old.binder.unlinkToDeath(old.deathMonitor, 0); 1692 } 1693 1694 mConnection.onServiceDisconnected(name); 1695 } 1696 1697 private final class RunConnection implements Runnable { 1698 RunConnection(ComponentName name, IBinder service, int command, boolean dead) { 1699 mName = name; 1700 mService = service; 1701 mCommand = command; 1702 mDead = dead; 1703 } 1704 1705 public void run() { 1706 if (mCommand == 0) { 1707 doConnected(mName, mService, mDead); 1708 } else if (mCommand == 1) { 1709 doDeath(mName, mService); 1710 } 1711 } 1712 1713 final ComponentName mName; 1714 final IBinder mService; 1715 final int mCommand; 1716 final boolean mDead; 1717 } 1718 1719 private final class DeathMonitor implements IBinder.DeathRecipient 1720 { 1721 DeathMonitor(ComponentName name, IBinder service) { 1722 mName = name; 1723 mService = service; 1724 } 1725 1726 public void binderDied() { 1727 death(mName, mService); 1728 } 1729 1730 final ComponentName mName; 1731 final IBinder mService; 1732 } 1733 } 1734} 1735