1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.compat.annotation.UnsupportedAppUsage; 22 import android.content.BroadcastReceiver; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.IIntentReceiver; 26 import android.content.Intent; 27 import android.content.ServiceConnection; 28 import android.content.pm.ApplicationInfo; 29 import android.content.pm.IPackageManager; 30 import android.content.pm.PackageManager; 31 import android.content.pm.PackageManager.NameNotFoundException; 32 import android.content.pm.SharedLibraryInfo; 33 import android.content.pm.dex.ArtManager; 34 import android.content.pm.split.SplitDependencyLoader; 35 import android.content.res.AssetManager; 36 import android.content.res.CompatibilityInfo; 37 import android.content.res.Resources; 38 import android.os.Build; 39 import android.os.Bundle; 40 import android.os.Environment; 41 import android.os.FileUtils; 42 import android.os.GraphicsEnvironment; 43 import android.os.Handler; 44 import android.os.IBinder; 45 import android.os.Process; 46 import android.os.RemoteException; 47 import android.os.StrictMode; 48 import android.os.SystemProperties; 49 import android.os.Trace; 50 import android.os.UserHandle; 51 import android.provider.Settings; 52 import android.security.net.config.NetworkSecurityConfigProvider; 53 import android.sysprop.VndkProperties; 54 import android.text.TextUtils; 55 import android.util.AndroidRuntimeException; 56 import android.util.ArrayMap; 57 import android.util.Log; 58 import android.util.Pair; 59 import android.util.Slog; 60 import android.util.SparseArray; 61 import android.view.DisplayAdjustments; 62 63 import com.android.internal.R; 64 import com.android.internal.annotations.GuardedBy; 65 import com.android.internal.util.ArrayUtils; 66 67 import dalvik.system.BaseDexClassLoader; 68 import dalvik.system.VMRuntime; 69 70 import java.io.File; 71 import java.io.IOException; 72 import java.io.InputStream; 73 import java.lang.ref.WeakReference; 74 import java.lang.reflect.InvocationTargetException; 75 import java.lang.reflect.Method; 76 import java.net.URL; 77 import java.nio.file.Paths; 78 import java.util.ArrayList; 79 import java.util.Arrays; 80 import java.util.Collections; 81 import java.util.Enumeration; 82 import java.util.HashSet; 83 import java.util.LinkedHashSet; 84 import java.util.List; 85 import java.util.Objects; 86 import java.util.Set; 87 import java.util.concurrent.Executor; 88 89 final class IntentReceiverLeaked extends AndroidRuntimeException { 90 @UnsupportedAppUsage IntentReceiverLeaked(String msg)91 public IntentReceiverLeaked(String msg) { 92 super(msg); 93 } 94 } 95 96 final class ServiceConnectionLeaked extends AndroidRuntimeException { 97 @UnsupportedAppUsage ServiceConnectionLeaked(String msg)98 public ServiceConnectionLeaked(String msg) { 99 super(msg); 100 } 101 } 102 103 /** 104 * Local state maintained about a currently loaded .apk. 105 * @hide 106 */ 107 public final class LoadedApk { 108 static final String TAG = "LoadedApk"; 109 static final boolean DEBUG = false; 110 111 @UnsupportedAppUsage 112 private final ActivityThread mActivityThread; 113 @UnsupportedAppUsage 114 final String mPackageName; 115 @UnsupportedAppUsage 116 private ApplicationInfo mApplicationInfo; 117 @UnsupportedAppUsage 118 private String mAppDir; 119 @UnsupportedAppUsage 120 private String mResDir; 121 private String[] mLegacyOverlayDirs; 122 private String[] mOverlayPaths; 123 @UnsupportedAppUsage 124 private String mDataDir; 125 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 126 private String mLibDir; 127 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 128 private File mDataDirFile; 129 private File mDeviceProtectedDataDirFile; 130 private File mCredentialProtectedDataDirFile; 131 @UnsupportedAppUsage 132 private final ClassLoader mBaseClassLoader; 133 private ClassLoader mDefaultClassLoader; 134 private final boolean mSecurityViolation; 135 private final boolean mIncludeCode; 136 private final boolean mRegisterPackage; 137 @UnsupportedAppUsage 138 private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments(); 139 /** WARNING: This may change. Don't hold external references to it. */ 140 @UnsupportedAppUsage 141 Resources mResources; 142 @UnsupportedAppUsage 143 private ClassLoader mClassLoader; 144 @UnsupportedAppUsage 145 private Application mApplication; 146 147 private String[] mSplitNames; 148 private String[] mSplitAppDirs; 149 @UnsupportedAppUsage 150 private String[] mSplitResDirs; 151 private String[] mSplitClassLoaderNames; 152 153 @UnsupportedAppUsage 154 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers 155 = new ArrayMap<>(); 156 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers 157 = new ArrayMap<>(); 158 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 159 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices 160 = new ArrayMap<>(); 161 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices 162 = new ArrayMap<>(); 163 private AppComponentFactory mAppComponentFactory; 164 165 /** 166 * We cache the instantiated application object for each package on this process here. 167 */ 168 @GuardedBy("sApplications") 169 private static final ArrayMap<String, Application> sApplications = new ArrayMap<>(4); 170 171 private final Object mLock = new Object(); 172 getApplication()173 Application getApplication() { 174 return mApplication; 175 } 176 177 /** 178 * Create information about a new .apk 179 * 180 * NOTE: This constructor is called with ActivityThread's lock held, 181 * so MUST NOT call back out to the activity manager. 182 */ LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode, boolean registerPackage)183 public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo, 184 CompatibilityInfo compatInfo, ClassLoader baseLoader, 185 boolean securityViolation, boolean includeCode, boolean registerPackage) { 186 187 mActivityThread = activityThread; 188 setApplicationInfo(aInfo); 189 mPackageName = aInfo.packageName; 190 mBaseClassLoader = baseLoader; 191 mSecurityViolation = securityViolation; 192 mIncludeCode = includeCode; 193 mRegisterPackage = registerPackage; 194 mDisplayAdjustments.setCompatibilityInfo(compatInfo); 195 mAppComponentFactory = createAppFactory(mApplicationInfo, mBaseClassLoader); 196 } 197 adjustNativeLibraryPaths(ApplicationInfo info)198 private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) { 199 // If we're dealing with a multi-arch application that has both 200 // 32 and 64 bit shared libraries, we might need to choose the secondary 201 // depending on what the current runtime's instruction set is. 202 if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) { 203 final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet(); 204 205 // Get the instruction set that the libraries of secondary Abi is supported. 206 // In presence of a native bridge this might be different than the one secondary Abi used. 207 String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi); 208 final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa); 209 secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa; 210 211 // If the runtimeIsa is the same as the primary isa, then we do nothing. 212 // Everything will be set up correctly because info.nativeLibraryDir will 213 // correspond to the right ISA. 214 if (runtimeIsa.equals(secondaryIsa)) { 215 final ApplicationInfo modified = new ApplicationInfo(info); 216 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir; 217 modified.primaryCpuAbi = modified.secondaryCpuAbi; 218 return modified; 219 } 220 } 221 222 return info; 223 } 224 225 /** 226 * Create information about the system package. 227 * Must call {@link #installSystemApplicationInfo} later. 228 */ LoadedApk(ActivityThread activityThread)229 LoadedApk(ActivityThread activityThread) { 230 mActivityThread = activityThread; 231 mApplicationInfo = new ApplicationInfo(); 232 mApplicationInfo.packageName = "android"; 233 mPackageName = "android"; 234 mAppDir = null; 235 mResDir = null; 236 mSplitAppDirs = null; 237 mSplitResDirs = null; 238 mSplitClassLoaderNames = null; 239 mLegacyOverlayDirs = null; 240 mOverlayPaths = null; 241 mDataDir = null; 242 mDataDirFile = null; 243 mDeviceProtectedDataDirFile = null; 244 mCredentialProtectedDataDirFile = null; 245 mLibDir = null; 246 mBaseClassLoader = null; 247 mSecurityViolation = false; 248 mIncludeCode = true; 249 mRegisterPackage = false; 250 mResources = Resources.getSystem(); 251 mDefaultClassLoader = ClassLoader.getSystemClassLoader(); 252 mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader); 253 mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader, 254 new ApplicationInfo(mApplicationInfo)); 255 } 256 257 /** 258 * Sets application info about the system package. 259 */ installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader)260 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { 261 assert info.packageName.equals("android"); 262 mApplicationInfo = info; 263 mDefaultClassLoader = classLoader; 264 mAppComponentFactory = createAppFactory(info, mDefaultClassLoader); 265 mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader, 266 new ApplicationInfo(mApplicationInfo)); 267 } 268 createAppFactory(ApplicationInfo appInfo, ClassLoader cl)269 private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) { 270 if (mIncludeCode && appInfo.appComponentFactory != null && cl != null) { 271 try { 272 return (AppComponentFactory) 273 cl.loadClass(appInfo.appComponentFactory).newInstance(); 274 } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { 275 Slog.e(TAG, "Unable to instantiate appComponentFactory", e); 276 } 277 } 278 return AppComponentFactory.DEFAULT; 279 } 280 getAppFactory()281 public AppComponentFactory getAppFactory() { 282 return mAppComponentFactory; 283 } 284 285 @UnsupportedAppUsage getPackageName()286 public String getPackageName() { 287 return mPackageName; 288 } 289 290 @UnsupportedAppUsage getApplicationInfo()291 public ApplicationInfo getApplicationInfo() { 292 return mApplicationInfo; 293 } 294 getTargetSdkVersion()295 public int getTargetSdkVersion() { 296 return mApplicationInfo.targetSdkVersion; 297 } 298 isSecurityViolation()299 public boolean isSecurityViolation() { 300 return mSecurityViolation; 301 } 302 303 @UnsupportedAppUsage(trackingBug = 172409979) getCompatibilityInfo()304 public CompatibilityInfo getCompatibilityInfo() { 305 return mDisplayAdjustments.getCompatibilityInfo(); 306 } 307 setCompatibilityInfo(CompatibilityInfo compatInfo)308 public void setCompatibilityInfo(CompatibilityInfo compatInfo) { 309 mDisplayAdjustments.setCompatibilityInfo(compatInfo); 310 } 311 312 /** 313 * Gets the array of shared libraries that are listed as 314 * used by the given package. 315 * 316 * @param packageName the name of the package (note: not its 317 * file name) 318 * @return null-ok; the array of shared libraries, each one 319 * a fully-qualified path 320 */ getLibrariesFor(String packageName)321 private static String[] getLibrariesFor(String packageName) { 322 ApplicationInfo ai = null; 323 try { 324 ai = ActivityThread.getPackageManager().getApplicationInfo(packageName, 325 PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId()); 326 } catch (RemoteException e) { 327 throw e.rethrowFromSystemServer(); 328 } 329 330 if (ai == null) { 331 return null; 332 } 333 334 return ai.sharedLibraryFiles; 335 } 336 337 /** 338 * Update the ApplicationInfo for an app. If oldPaths is null, all the paths are considered 339 * new. 340 * @param aInfo The new ApplicationInfo to use for this LoadedApk 341 * @param oldPaths The code paths for the old ApplicationInfo object. null means no paths can 342 * be reused. 343 */ updateApplicationInfo(@onNull ApplicationInfo aInfo, @Nullable List<String> oldPaths)344 public void updateApplicationInfo(@NonNull ApplicationInfo aInfo, 345 @Nullable List<String> oldPaths) { 346 setApplicationInfo(aInfo); 347 348 final List<String> newPaths = new ArrayList<>(); 349 makePaths(mActivityThread, aInfo, newPaths); 350 final List<String> addedPaths = new ArrayList<>(newPaths.size()); 351 352 if (oldPaths != null) { 353 for (String path : newPaths) { 354 final String apkName = path.substring(path.lastIndexOf(File.separator)); 355 boolean match = false; 356 for (String oldPath : oldPaths) { 357 final String oldApkName = oldPath.substring(oldPath.lastIndexOf(File.separator)); 358 if (apkName.equals(oldApkName)) { 359 match = true; 360 break; 361 } 362 } 363 if (!match) { 364 addedPaths.add(path); 365 } 366 } 367 } else { 368 addedPaths.addAll(newPaths); 369 } 370 synchronized (mLock) { 371 createOrUpdateClassLoaderLocked(addedPaths); 372 if (mResources != null) { 373 final String[] splitPaths; 374 try { 375 splitPaths = getSplitPaths(null); 376 } catch (NameNotFoundException e) { 377 // This should NEVER fail. 378 throw new AssertionError("null split not found"); 379 } 380 381 mResources = ResourcesManager.getInstance().getResources(null, mResDir, 382 splitPaths, mLegacyOverlayDirs, mOverlayPaths, 383 mApplicationInfo.sharedLibraryFiles, null, null, getCompatibilityInfo(), 384 getClassLoader(), mApplication == null ? null 385 : mApplication.getResources().getLoaders()); 386 } 387 } 388 mAppComponentFactory = createAppFactory(aInfo, mDefaultClassLoader); 389 } 390 setApplicationInfo(ApplicationInfo aInfo)391 private void setApplicationInfo(ApplicationInfo aInfo) { 392 final int myUid = Process.myUid(); 393 aInfo = adjustNativeLibraryPaths(aInfo); 394 mApplicationInfo = aInfo; 395 mAppDir = aInfo.sourceDir; 396 mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir; 397 mLegacyOverlayDirs = aInfo.resourceDirs; 398 mOverlayPaths = aInfo.overlayPaths; 399 mDataDir = aInfo.dataDir; 400 mLibDir = aInfo.nativeLibraryDir; 401 mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir); 402 mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir); 403 mCredentialProtectedDataDirFile = FileUtils.newFileOrNull( 404 aInfo.credentialProtectedDataDir); 405 406 mSplitNames = aInfo.splitNames; 407 mSplitAppDirs = aInfo.splitSourceDirs; 408 mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs; 409 mSplitClassLoaderNames = aInfo.splitClassLoaderNames; 410 411 if (aInfo.requestsIsolatedSplitLoading() && !ArrayUtils.isEmpty(mSplitNames)) { 412 mSplitLoader = new SplitDependencyLoaderImpl(aInfo.splitDependencies); 413 } 414 } 415 setSdkSandboxStorage(@ullable String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage)416 void setSdkSandboxStorage(@Nullable String sdkSandboxClientAppVolumeUuid, 417 String sdkSandboxClientAppPackage) { 418 int userId = UserHandle.myUserId(); 419 mDeviceProtectedDataDirFile = Environment 420 .getDataMiscDeSharedSdkSandboxDirectory(sdkSandboxClientAppVolumeUuid, userId, 421 sdkSandboxClientAppPackage) 422 .getAbsoluteFile(); 423 mCredentialProtectedDataDirFile = Environment 424 .getDataMiscCeSharedSdkSandboxDirectory(sdkSandboxClientAppVolumeUuid, userId, 425 sdkSandboxClientAppPackage) 426 .getAbsoluteFile(); 427 428 if ((mApplicationInfo.privateFlags 429 & ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) != 0 430 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { 431 mDataDirFile = mDeviceProtectedDataDirFile; 432 } else { 433 mDataDirFile = mCredentialProtectedDataDirFile; 434 } 435 mDataDir = mDataDirFile.getAbsolutePath(); 436 } 437 makePaths(ActivityThread activityThread, ApplicationInfo aInfo, List<String> outZipPaths)438 public static void makePaths(ActivityThread activityThread, 439 ApplicationInfo aInfo, 440 List<String> outZipPaths) { 441 makePaths(activityThread, false, aInfo, outZipPaths, null); 442 } 443 appendSharedLibrariesLibPathsIfNeeded( List<SharedLibraryInfo> sharedLibraries, ApplicationInfo aInfo, Set<String> outSeenPaths, List<String> outLibPaths)444 private static void appendSharedLibrariesLibPathsIfNeeded( 445 List<SharedLibraryInfo> sharedLibraries, ApplicationInfo aInfo, 446 Set<String> outSeenPaths, 447 List<String> outLibPaths) { 448 if (sharedLibraries == null) { 449 return; 450 } 451 for (SharedLibraryInfo lib : sharedLibraries) { 452 if (lib.isNative()) { 453 // Native shared lib doesn't contribute to the native lib search path. Its name is 454 // sent to libnativeloader and then the native shared lib is exported from the 455 // default linker namespace. 456 continue; 457 } 458 List<String> paths = lib.getAllCodePaths(); 459 outSeenPaths.addAll(paths); 460 for (String path : paths) { 461 appendApkLibPathIfNeeded(path, aInfo, outLibPaths); 462 } 463 appendSharedLibrariesLibPathsIfNeeded( 464 lib.getDependencies(), aInfo, outSeenPaths, outLibPaths); 465 } 466 } 467 makePaths(ActivityThread activityThread, boolean isBundledApp, ApplicationInfo aInfo, List<String> outZipPaths, List<String> outLibPaths)468 public static void makePaths(ActivityThread activityThread, 469 boolean isBundledApp, 470 ApplicationInfo aInfo, 471 List<String> outZipPaths, 472 List<String> outLibPaths) { 473 final String appDir = aInfo.sourceDir; 474 final String libDir = aInfo.nativeLibraryDir; 475 476 outZipPaths.clear(); 477 outZipPaths.add(appDir); 478 479 // Do not load all available splits if the app requested isolated split loading. 480 if (aInfo.splitSourceDirs != null && !aInfo.requestsIsolatedSplitLoading()) { 481 Collections.addAll(outZipPaths, aInfo.splitSourceDirs); 482 } 483 484 if (outLibPaths != null) { 485 outLibPaths.clear(); 486 } 487 488 /* 489 * The following is a bit of a hack to inject 490 * instrumentation into the system: If the app 491 * being started matches one of the instrumentation names, 492 * then we combine both the "instrumentation" and 493 * "instrumented" app into the path, along with the 494 * concatenation of both apps' shared library lists. 495 */ 496 497 String[] instrumentationLibs = null; 498 // activityThread will be null when called from the WebView zygote; just assume 499 // no instrumentation applies in this case. 500 if (activityThread != null) { 501 String instrumentationPackageName = activityThread.mInstrumentationPackageName; 502 String instrumentationAppDir = activityThread.mInstrumentationAppDir; 503 String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs; 504 String instrumentationLibDir = activityThread.mInstrumentationLibDir; 505 506 String instrumentedAppDir = activityThread.mInstrumentedAppDir; 507 String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs; 508 String instrumentedLibDir = activityThread.mInstrumentedLibDir; 509 510 if (appDir.equals(instrumentationAppDir) 511 || appDir.equals(instrumentedAppDir)) { 512 outZipPaths.clear(); 513 outZipPaths.add(instrumentationAppDir); 514 if (!instrumentationAppDir.equals(instrumentedAppDir)) { 515 outZipPaths.add(instrumentedAppDir); 516 } 517 518 // Only add splits if the app did not request isolated split loading. 519 if (!aInfo.requestsIsolatedSplitLoading()) { 520 if (instrumentationSplitAppDirs != null) { 521 Collections.addAll(outZipPaths, instrumentationSplitAppDirs); 522 } 523 524 if (!instrumentationAppDir.equals(instrumentedAppDir)) { 525 if (instrumentedSplitAppDirs != null) { 526 Collections.addAll(outZipPaths, instrumentedSplitAppDirs); 527 } 528 } 529 } 530 531 if (outLibPaths != null) { 532 outLibPaths.add(instrumentationLibDir); 533 if (!instrumentationLibDir.equals(instrumentedLibDir)) { 534 outLibPaths.add(instrumentedLibDir); 535 } 536 } 537 538 if (!instrumentedAppDir.equals(instrumentationAppDir)) { 539 instrumentationLibs = getLibrariesFor(instrumentationPackageName); 540 } 541 } 542 } 543 544 if (outLibPaths != null) { 545 if (outLibPaths.isEmpty()) { 546 outLibPaths.add(libDir); 547 } 548 549 // Add path to libraries in apk for current abi. Do this now because more entries 550 // will be added to zipPaths that shouldn't be part of the library path. 551 if (aInfo.primaryCpuAbi != null) { 552 // Add fake libs into the library search path if we target prior to N. 553 if (aInfo.targetSdkVersion < Build.VERSION_CODES.N) { 554 outLibPaths.add("/system/fake-libs" + 555 (VMRuntime.is64BitAbi(aInfo.primaryCpuAbi) ? "64" : "")); 556 } 557 for (String apk : outZipPaths) { 558 outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi); 559 } 560 } 561 562 if (isBundledApp) { 563 // Add path to system libraries to libPaths; 564 // Access to system libs should be limited 565 // to bundled applications; this is why updated 566 // system apps are not included. 567 outLibPaths.add(System.getProperty("java.library.path")); 568 } 569 } 570 571 // Add the shared libraries native paths. The dex files in shared libraries will 572 // be resolved through shared library loaders, which are setup later. 573 Set<String> outSeenPaths = new LinkedHashSet<>(); 574 appendSharedLibrariesLibPathsIfNeeded( 575 aInfo.sharedLibraryInfos, aInfo, outSeenPaths, outLibPaths); 576 577 // ApplicationInfo.sharedLibraryFiles is a public API, so anyone can change it. 578 // We prepend shared libraries that the package manager hasn't seen, maintaining their 579 // original order where possible. 580 if (aInfo.sharedLibraryFiles != null) { 581 int index = 0; 582 for (String lib : aInfo.sharedLibraryFiles) { 583 // sharedLibraryFiles might contain native shared libraries that are not APK paths. 584 if (!lib.endsWith(".apk")) { 585 continue; 586 } 587 if (!outSeenPaths.contains(lib) && !outZipPaths.contains(lib)) { 588 outZipPaths.add(index, lib); 589 index++; 590 appendApkLibPathIfNeeded(lib, aInfo, outLibPaths); 591 } 592 } 593 } 594 595 if (instrumentationLibs != null) { 596 for (String lib : instrumentationLibs) { 597 if (!outZipPaths.contains(lib)) { 598 outZipPaths.add(0, lib); 599 appendApkLibPathIfNeeded(lib, aInfo, outLibPaths); 600 } 601 } 602 } 603 } 604 605 /** 606 * This method appends a path to the appropriate native library folder of a 607 * library if this library is hosted in an APK. This allows support for native 608 * shared libraries. The library API is determined based on the application 609 * ABI. 610 * 611 * @param path Path to the library. 612 * @param applicationInfo The application depending on the library. 613 * @param outLibPaths List to which to add the native lib path if needed. 614 */ appendApkLibPathIfNeeded(@onNull String path, @NonNull ApplicationInfo applicationInfo, @Nullable List<String> outLibPaths)615 private static void appendApkLibPathIfNeeded(@NonNull String path, 616 @NonNull ApplicationInfo applicationInfo, @Nullable List<String> outLibPaths) { 617 // Looking at the suffix is a little hacky but a safe and simple solution. 618 // We will be revisiting code in the next release and clean this up. 619 if (outLibPaths != null && applicationInfo.primaryCpuAbi != null && path.endsWith(".apk")) { 620 if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O) { 621 outLibPaths.add(path + "!/lib/" + applicationInfo.primaryCpuAbi); 622 } 623 } 624 } 625 626 /* 627 * All indices received by the super class should be shifted by 1 when accessing mSplitNames, 628 * etc. The super class assumes the base APK is index 0, while the PackageManager APIs don't 629 * include the base APK in the list of splits. 630 */ 631 private class SplitDependencyLoaderImpl extends SplitDependencyLoader<NameNotFoundException> { 632 @GuardedBy("mLock") 633 private final String[][] mCachedResourcePaths; 634 @GuardedBy("mLock") 635 private final ClassLoader[] mCachedClassLoaders; 636 SplitDependencyLoaderImpl(@onNull SparseArray<int[]> dependencies)637 SplitDependencyLoaderImpl(@NonNull SparseArray<int[]> dependencies) { 638 super(dependencies); 639 mCachedResourcePaths = new String[mSplitNames.length + 1][]; 640 mCachedClassLoaders = new ClassLoader[mSplitNames.length + 1]; 641 } 642 643 @Override isSplitCached(int splitIdx)644 protected boolean isSplitCached(int splitIdx) { 645 synchronized (mLock) { 646 return mCachedClassLoaders[splitIdx] != null; 647 } 648 } 649 650 @Override constructSplit(int splitIdx, @NonNull int[] configSplitIndices, int parentSplitIdx)651 protected void constructSplit(int splitIdx, @NonNull int[] configSplitIndices, 652 int parentSplitIdx) throws NameNotFoundException { 653 synchronized (mLock) { 654 final ArrayList<String> splitPaths = new ArrayList<>(); 655 if (splitIdx == 0) { 656 createOrUpdateClassLoaderLocked(null); 657 mCachedClassLoaders[0] = mClassLoader; 658 659 // Never add the base resources here, they always get added no matter what. 660 for (int configSplitIdx : configSplitIndices) { 661 splitPaths.add(mSplitResDirs[configSplitIdx - 1]); 662 } 663 mCachedResourcePaths[0] = splitPaths.toArray(new String[splitPaths.size()]); 664 return; 665 } 666 667 // Since we handled the special base case above, parentSplitIdx is always valid. 668 final ClassLoader parent = mCachedClassLoaders[parentSplitIdx]; 669 mCachedClassLoaders[splitIdx] = ApplicationLoaders.getDefault().getClassLoader( 670 mSplitAppDirs[splitIdx - 1], getTargetSdkVersion(), false, null, 671 null, parent, mSplitClassLoaderNames[splitIdx - 1]); 672 673 Collections.addAll(splitPaths, mCachedResourcePaths[parentSplitIdx]); 674 splitPaths.add(mSplitResDirs[splitIdx - 1]); 675 for (int configSplitIdx : configSplitIndices) { 676 splitPaths.add(mSplitResDirs[configSplitIdx - 1]); 677 } 678 mCachedResourcePaths[splitIdx] = splitPaths.toArray(new String[splitPaths.size()]); 679 } 680 } 681 ensureSplitLoaded(String splitName)682 private int ensureSplitLoaded(String splitName) throws NameNotFoundException { 683 int idx = 0; 684 if (splitName != null) { 685 idx = Arrays.binarySearch(mSplitNames, splitName); 686 if (idx < 0) { 687 throw new PackageManager.NameNotFoundException( 688 "Split name '" + splitName + "' is not installed"); 689 } 690 idx += 1; 691 } 692 loadDependenciesForSplit(idx); 693 return idx; 694 } 695 getClassLoaderForSplit(String splitName)696 ClassLoader getClassLoaderForSplit(String splitName) throws NameNotFoundException { 697 final int idx = ensureSplitLoaded(splitName); 698 synchronized (mLock) { 699 return mCachedClassLoaders[idx]; 700 } 701 } 702 getSplitPathsForSplit(String splitName)703 String[] getSplitPathsForSplit(String splitName) throws NameNotFoundException { 704 final int idx = ensureSplitLoaded(splitName); 705 synchronized (mLock) { 706 return mCachedResourcePaths[idx]; 707 } 708 } 709 } 710 711 private SplitDependencyLoaderImpl mSplitLoader; 712 getSplitClassLoader(String splitName)713 ClassLoader getSplitClassLoader(String splitName) throws NameNotFoundException { 714 if (mSplitLoader == null) { 715 return mClassLoader; 716 } 717 return mSplitLoader.getClassLoaderForSplit(splitName); 718 } 719 getSplitPaths(String splitName)720 String[] getSplitPaths(String splitName) throws NameNotFoundException { 721 if (mSplitLoader == null) { 722 return mSplitResDirs; 723 } 724 return mSplitLoader.getSplitPathsForSplit(splitName); 725 } 726 727 /** 728 * Create a class loader for the {@code sharedLibrary}. Shared libraries are canonicalized, 729 * so if we already created a class loader with that shared library, we return it. 730 * 731 * Implementation notes: the canonicalization of shared libraries is something dex2oat 732 * also does. 733 */ createSharedLibraryLoader(SharedLibraryInfo sharedLibrary, boolean isBundledApp, String librarySearchPath, String libraryPermittedPath)734 ClassLoader createSharedLibraryLoader(SharedLibraryInfo sharedLibrary, 735 boolean isBundledApp, String librarySearchPath, String libraryPermittedPath) { 736 List<String> paths = sharedLibrary.getAllCodePaths(); 737 Pair<List<ClassLoader>, List<ClassLoader>> sharedLibraries = createSharedLibrariesLoaders( 738 sharedLibrary.getDependencies(), isBundledApp, librarySearchPath, 739 libraryPermittedPath); 740 final String jars = (paths.size() == 1) ? paths.get(0) : 741 TextUtils.join(File.pathSeparator, paths); 742 743 // Shared libraries get a null parent: this has the side effect of having canonicalized 744 // shared libraries using ApplicationLoaders cache, which is the behavior we want. 745 return ApplicationLoaders.getDefault().getSharedLibraryClassLoaderWithSharedLibraries(jars, 746 mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath, 747 libraryPermittedPath, /* parent */ null, 748 /* classLoaderName */ null, sharedLibraries.first, sharedLibraries.second); 749 } 750 751 /** 752 * 753 * @return a {@link Pair} of List<ClassLoader> where the first is for standard shared libraries 754 * and the second is list for shared libraries that code should be loaded after the dex 755 */ createSharedLibrariesLoaders( List<SharedLibraryInfo> sharedLibraries, boolean isBundledApp, String librarySearchPath, String libraryPermittedPath)756 private Pair<List<ClassLoader>, List<ClassLoader>> createSharedLibrariesLoaders( 757 List<SharedLibraryInfo> sharedLibraries, 758 boolean isBundledApp, String librarySearchPath, String libraryPermittedPath) { 759 if (sharedLibraries == null || sharedLibraries.isEmpty()) { 760 return new Pair<>(null, null); 761 } 762 763 // if configured to do so, shared libs are split into 2 collections: those that are 764 // on the class path before the applications code, which is standard, and those 765 // specified to be loaded after the applications code. 766 HashSet<String> libsToLoadAfter = new HashSet<>(); 767 Resources systemR = Resources.getSystem(); 768 Collections.addAll(libsToLoadAfter, systemR.getStringArray( 769 R.array.config_sharedLibrariesLoadedAfterApp)); 770 771 List<ClassLoader> loaders = new ArrayList<>(); 772 List<ClassLoader> after = new ArrayList<>(); 773 for (SharedLibraryInfo info : sharedLibraries) { 774 if (info.isNative()) { 775 // Native shared lib doesn't contribute to the native lib search path. Its name is 776 // sent to libnativeloader and then the native shared lib is exported from the 777 // default linker namespace. 778 continue; 779 } 780 if (info.isSdk()) { 781 // SDKs are not loaded automatically. 782 continue; 783 } 784 if (libsToLoadAfter.contains(info.getName())) { 785 if (DEBUG) { 786 Slog.v(ActivityThread.TAG, 787 info.getName() + " will be loaded after application code"); 788 } 789 after.add(createSharedLibraryLoader( 790 info, isBundledApp, librarySearchPath, libraryPermittedPath)); 791 } else { 792 loaders.add(createSharedLibraryLoader( 793 info, isBundledApp, librarySearchPath, libraryPermittedPath)); 794 } 795 } 796 return new Pair<>(loaders, after); 797 } 798 allowThreadDiskReads()799 private StrictMode.ThreadPolicy allowThreadDiskReads() { 800 if (mActivityThread == null) { 801 // When LoadedApk is used without an ActivityThread (usually in a 802 // zygote context), don't call into StrictMode, as it initializes 803 // the binder subsystem, which we don't want. 804 return null; 805 } 806 807 return StrictMode.allowThreadDiskReads(); 808 } 809 setThreadPolicy(StrictMode.ThreadPolicy policy)810 private void setThreadPolicy(StrictMode.ThreadPolicy policy) { 811 if (mActivityThread != null && policy != null) { 812 StrictMode.setThreadPolicy(policy); 813 } 814 } 815 allowVmViolations()816 private StrictMode.VmPolicy allowVmViolations() { 817 if (mActivityThread == null) { 818 // When LoadedApk is used without an ActivityThread (usually in a 819 // zygote context), don't call into StrictMode, as it initializes 820 // the binder subsystem, which we don't want. 821 return null; 822 } 823 824 return StrictMode.allowVmViolations(); 825 } 826 setVmPolicy(StrictMode.VmPolicy policy)827 private void setVmPolicy(StrictMode.VmPolicy policy) { 828 if (mActivityThread != null && policy != null) { 829 StrictMode.setVmPolicy(policy); 830 } 831 } 832 833 @GuardedBy("mLock") createOrUpdateClassLoaderLocked(List<String> addedPaths)834 private void createOrUpdateClassLoaderLocked(List<String> addedPaths) { 835 if (mPackageName.equals("android")) { 836 // Note: This branch is taken for system server and we don't need to setup 837 // jit profiling support. 838 if (mClassLoader != null) { 839 // nothing to update 840 return; 841 } 842 843 if (mBaseClassLoader != null) { 844 mDefaultClassLoader = mBaseClassLoader; 845 } else { 846 mDefaultClassLoader = ClassLoader.getSystemClassLoader(); 847 } 848 mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader); 849 mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader, 850 new ApplicationInfo(mApplicationInfo)); 851 return; 852 } 853 854 // Avoid the binder call when the package is the current application package. 855 // The activity manager will perform ensure that dexopt is performed before 856 // spinning up the process. Similarly, don't call into binder when we don't 857 // have an ActivityThread object. 858 if (mActivityThread != null 859 && !Objects.equals(mPackageName, ActivityThread.currentPackageName()) 860 && mIncludeCode) { 861 try { 862 ActivityThread.getPackageManager().notifyPackageUse(mPackageName, 863 PackageManager.NOTIFY_PACKAGE_USE_CROSS_PACKAGE); 864 } catch (RemoteException re) { 865 throw re.rethrowFromSystemServer(); 866 } 867 } 868 869 if (mRegisterPackage) { 870 try { 871 ActivityManager.getService().addPackageDependency(mPackageName); 872 } catch (RemoteException e) { 873 throw e.rethrowFromSystemServer(); 874 } 875 } 876 877 // Lists for the elements of zip/code and native libraries. 878 // 879 // Both lists are usually not empty. We expect on average one APK for the zip component, 880 // but shared libraries and splits are not uncommon. We expect at least three elements 881 // for native libraries (app-based, system, vendor). As such, give both some breathing 882 // space and initialize to a small value (instead of incurring growth code). 883 final List<String> zipPaths = new ArrayList<>(10); 884 final List<String> libPaths = new ArrayList<>(10); 885 886 boolean isBundledApp = mApplicationInfo.isSystemApp() 887 && !mApplicationInfo.isUpdatedSystemApp(); 888 889 // Vendor apks are treated as bundled only when /vendor/lib is in the default search 890 // paths. If not, they are treated as unbundled; access to system libs is limited. 891 // Having /vendor/lib in the default search paths means that all system processes 892 // are allowed to use any vendor library, which in turn means that system is dependent 893 // on vendor partition. In the contrary, not having /vendor/lib in the default search 894 // paths mean that the two partitions are separated and thus we can treat vendor apks 895 // as unbundled. 896 final String defaultSearchPaths = System.getProperty("java.library.path"); 897 final boolean treatVendorApkAsUnbundled = !defaultSearchPaths.contains("/vendor/lib"); 898 if (mApplicationInfo.getCodePath() != null 899 && mApplicationInfo.isVendor() && treatVendorApkAsUnbundled) { 900 isBundledApp = false; 901 } 902 903 // Similar to vendor apks, we should add /product/lib for apks from product partition 904 // when product apps are marked as unbundled. We cannot use the same way from vendor 905 // to check if lib path exists because there is possibility that /product/lib would not 906 // exist from legacy device while product apks are bundled. To make this clear, we use 907 // "ro.product.vndk.version" property. If the property is defined, we regard all product 908 // apks as unbundled. 909 if (mApplicationInfo.getCodePath() != null 910 && mApplicationInfo.isProduct() 911 && VndkProperties.product_vndk_version().isPresent()) { 912 isBundledApp = false; 913 } 914 915 makePaths(mActivityThread, isBundledApp, mApplicationInfo, zipPaths, libPaths); 916 917 // Including an inaccessible dir in libraryPermittedPath would cause SELinux denials 918 // when the loader attempts to canonicalise the path. so we don't. 919 String libraryPermittedPath = canAccessDataDir() ? mDataDir : ""; 920 921 if (isBundledApp) { 922 // For bundled apps, add the base directory of the app (e.g., 923 // /system/app/Foo/) to the permitted paths so that it can load libraries 924 // embedded in module apks under the directory. For now, GmsCore is relying 925 // on this, but this isn't specific to the app. Also note that, we don't 926 // need to do this for unbundled apps as entire /data is already set to 927 // the permitted paths for them. 928 libraryPermittedPath += File.pathSeparator 929 + Paths.get(getAppDir()).getParent().toString(); 930 931 // This is necessary to grant bundled apps access to 932 // libraries located in subdirectories of /system/lib 933 libraryPermittedPath += File.pathSeparator + defaultSearchPaths; 934 } 935 936 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths); 937 938 if (mActivityThread != null) { 939 final String gpuDebugApp = mActivityThread.getStringCoreSetting( 940 Settings.Global.GPU_DEBUG_APP, ""); 941 if (!gpuDebugApp.isEmpty() && mPackageName.equals(gpuDebugApp)) { 942 943 // The current application is used to debug, attempt to get the debug layers. 944 try { 945 // Get the ApplicationInfo from PackageManager so that metadata fields present. 946 final ApplicationInfo ai = ActivityThread.getPackageManager() 947 .getApplicationInfo(mPackageName, PackageManager.GET_META_DATA, 948 UserHandle.myUserId()); 949 final String debugLayerPath = GraphicsEnvironment.getInstance() 950 .getDebugLayerPathsFromSettings(mActivityThread.getCoreSettings(), 951 ActivityThread.getPackageManager(), mPackageName, ai); 952 if (debugLayerPath != null) { 953 libraryPermittedPath += File.pathSeparator + debugLayerPath; 954 } 955 } catch (RemoteException e) { 956 // Unlikely to fail for applications, but in case of failure, something is wrong 957 // inside the system server, hence just skip. 958 Slog.e(ActivityThread.TAG, 959 "RemoteException when fetching debug layer paths for: " + mPackageName); 960 } 961 } 962 } 963 964 // If we're not asked to include code, we construct a classloader that has 965 // no code path included. We still need to set up the library search paths 966 // and permitted path because NativeActivity relies on it (it attempts to 967 // call System.loadLibrary() on a classloader from a LoadedApk with 968 // mIncludeCode == false). 969 if (!mIncludeCode) { 970 if (mDefaultClassLoader == null) { 971 StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads(); 972 mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoader( 973 "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp, 974 librarySearchPath, libraryPermittedPath, mBaseClassLoader, 975 null /* classLoaderName */); 976 setThreadPolicy(oldPolicy); 977 mAppComponentFactory = AppComponentFactory.DEFAULT; 978 } 979 980 if (mClassLoader == null) { 981 mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader, 982 new ApplicationInfo(mApplicationInfo)); 983 } 984 985 return; 986 } 987 988 /* 989 * With all the combination done (if necessary, actually create the java class 990 * loader and set up JIT profiling support if necessary. 991 * 992 * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils. 993 */ 994 final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) : 995 TextUtils.join(File.pathSeparator, zipPaths); 996 997 if (DEBUG) Slog.v(ActivityThread.TAG, "Class path: " + zip + 998 ", JNI path: " + librarySearchPath); 999 1000 boolean registerAppInfoToArt = false; 1001 if (mDefaultClassLoader == null) { 1002 // Setup the dex reporter to notify package manager 1003 // of any relevant dex loads. The idle maintenance job will use the information 1004 // reported to optimize the loaded dex files. 1005 // Note that we only need one global reporter per app. 1006 // Make sure we do this before creating the main app classloader for the first time 1007 // so that we can capture the complete application startup. 1008 // 1009 // We should not do this in a zygote context (where mActivityThread will be null), 1010 // thus we'll guard against it. 1011 // Also, the system server reporter (SystemServerDexLoadReporter) is already registered 1012 // when system server starts, so we don't need to do it here again. 1013 if (mActivityThread != null && !ActivityThread.isSystem()) { 1014 BaseDexClassLoader.setReporter(DexLoadReporter.getInstance()); 1015 } 1016 1017 // Temporarily disable logging of disk reads on the Looper thread 1018 // as this is early and necessary. 1019 StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads(); 1020 1021 Pair<List<ClassLoader>, List<ClassLoader>> sharedLibraries = 1022 createSharedLibrariesLoaders(mApplicationInfo.sharedLibraryInfos, isBundledApp, 1023 librarySearchPath, libraryPermittedPath); 1024 1025 List<String> nativeSharedLibraries = new ArrayList<>(); 1026 if (mApplicationInfo.sharedLibraryInfos != null) { 1027 for (SharedLibraryInfo info : mApplicationInfo.sharedLibraryInfos) { 1028 if (info.isNative()) { 1029 nativeSharedLibraries.add(info.getName()); 1030 } 1031 } 1032 } 1033 1034 mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries( 1035 zip, mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath, 1036 libraryPermittedPath, mBaseClassLoader, 1037 mApplicationInfo.classLoaderName, sharedLibraries.first, nativeSharedLibraries, 1038 sharedLibraries.second); 1039 mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader); 1040 1041 setThreadPolicy(oldPolicy); 1042 // Setup the class loader paths for profiling. 1043 registerAppInfoToArt = true; 1044 } 1045 1046 if (!libPaths.isEmpty()) { 1047 // Temporarily disable logging of disk reads on the Looper thread as this is necessary 1048 StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads(); 1049 try { 1050 ApplicationLoaders.getDefault().addNative(mDefaultClassLoader, libPaths); 1051 } finally { 1052 setThreadPolicy(oldPolicy); 1053 } 1054 } 1055 1056 if (addedPaths != null && addedPaths.size() > 0) { 1057 final String add = TextUtils.join(File.pathSeparator, addedPaths); 1058 ApplicationLoaders.getDefault().addPath(mDefaultClassLoader, add); 1059 // Setup the new code paths for profiling. 1060 registerAppInfoToArt = true; 1061 } 1062 1063 // Setup jit profile support. 1064 // 1065 // It is ok to call this multiple times if the application gets updated with new splits. 1066 // The runtime only keeps track of unique code paths and can handle re-registration of 1067 // the same code path. There's no need to pass `addedPaths` since any new code paths 1068 // are already in `mApplicationInfo`. 1069 // 1070 // It is NOT ok to call this function from the system_server (for any of the packages it 1071 // loads code from) so we explicitly disallow it there. 1072 // 1073 // It is not ok to call this in a zygote context where mActivityThread is null. 1074 if (registerAppInfoToArt && !ActivityThread.isSystem() && mActivityThread != null) { 1075 registerAppInfoToArt(); 1076 } 1077 1078 // Call AppComponentFactory to select/create the main class loader of this app. 1079 // Since this may call code in the app, mDefaultClassLoader must be fully set up 1080 // before invoking the factory. 1081 // Invoke with a copy of ApplicationInfo to protect against the app changing it. 1082 if (mClassLoader == null) { 1083 mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader, 1084 new ApplicationInfo(mApplicationInfo)); 1085 } 1086 } 1087 1088 /** 1089 * Return whether we can access the package's private data directory in order to be able to 1090 * load code from it. 1091 */ canAccessDataDir()1092 private boolean canAccessDataDir() { 1093 // In a zygote context where mActivityThread is null we can't access the app data dir. 1094 if (mActivityThread == null) { 1095 return false; 1096 } 1097 1098 // A package can access its own data directory (the common case, so short-circuit it). 1099 if (Objects.equals(mPackageName, ActivityThread.currentPackageName())) { 1100 return true; 1101 } 1102 1103 // Temporarily disable logging of disk reads on the Looper thread as this is necessary - 1104 // and the loader will access the directory anyway if we don't check it. 1105 StrictMode.ThreadPolicy oldThreadPolicy = allowThreadDiskReads(); 1106 1107 // Also disable logging of access to /data/user before CE storage is unlocked. The check 1108 // below will return false (because the directory name we pass will not match the 1109 // encrypted one), but that's correct. 1110 StrictMode.VmPolicy oldVmPolicy = allowVmViolations(); 1111 1112 try { 1113 // We are constructing a classloader for a different package. It is likely, 1114 // but not certain, that we can't acccess its app data dir - so check. 1115 return new File(mDataDir).canExecute(); 1116 } finally { 1117 setThreadPolicy(oldThreadPolicy); 1118 setVmPolicy(oldVmPolicy); 1119 } 1120 } 1121 1122 @UnsupportedAppUsage getClassLoader()1123 public ClassLoader getClassLoader() { 1124 synchronized (mLock) { 1125 if (mClassLoader == null) { 1126 createOrUpdateClassLoaderLocked(null /*addedPaths*/); 1127 } 1128 return mClassLoader; 1129 } 1130 } 1131 registerAppInfoToArt()1132 private void registerAppInfoToArt() { 1133 // Only set up profile support if the loaded apk has the same uid as the 1134 // current process. 1135 // Currently, we do not support profiling across different apps. 1136 // (e.g. application's uid might be different when the code is 1137 // loaded by another app via createApplicationContext) 1138 if (mApplicationInfo.uid != Process.myUid()) { 1139 return; 1140 } 1141 1142 final List<String> codePaths = new ArrayList<>(); 1143 if ((mApplicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) { 1144 codePaths.add(mApplicationInfo.sourceDir); 1145 } 1146 if (mApplicationInfo.splitSourceDirs != null) { 1147 Collections.addAll(codePaths, mApplicationInfo.splitSourceDirs); 1148 } 1149 1150 if (codePaths.isEmpty()) { 1151 // If there are no code paths there's no need to setup a profile file and register with 1152 // the runtime, 1153 return; 1154 } 1155 1156 for (int i = codePaths.size() - 1; i >= 0; i--) { 1157 String splitName = i == 0 ? null : mApplicationInfo.splitNames[i - 1]; 1158 String curProfileFile = ArtManager.getCurrentProfilePath( 1159 mPackageName, UserHandle.myUserId(), splitName); 1160 String refProfileFile = ArtManager.getReferenceProfilePath( 1161 mPackageName, UserHandle.myUserId(), splitName); 1162 int codePathType = codePaths.get(i).equals(mApplicationInfo.sourceDir) 1163 ? VMRuntime.CODE_PATH_TYPE_PRIMARY_APK 1164 : VMRuntime.CODE_PATH_TYPE_SPLIT_APK; 1165 VMRuntime.registerAppInfo( 1166 mPackageName, 1167 curProfileFile, 1168 refProfileFile, 1169 new String[] {codePaths.get(i)}, 1170 codePathType); 1171 } 1172 1173 // Register the app data directory with the reporter. It will 1174 // help deciding whether or not a dex file is the primary apk or a 1175 // secondary dex. 1176 DexLoadReporter.getInstance().registerAppDataDir(mPackageName, mDataDir); 1177 } 1178 1179 /** 1180 * Setup value for Thread.getContextClassLoader(). If the 1181 * package will not run in in a VM with other packages, we set 1182 * the Java context ClassLoader to the 1183 * PackageInfo.getClassLoader value. However, if this VM can 1184 * contain multiple packages, we intead set the Java context 1185 * ClassLoader to a proxy that will warn about the use of Java 1186 * context ClassLoaders and then fall through to use the 1187 * system ClassLoader. 1188 * 1189 * <p> Note that this is similar to but not the same as the 1190 * android.content.Context.getClassLoader(). While both 1191 * context class loaders are typically set to the 1192 * PathClassLoader used to load the package archive in the 1193 * single application per VM case, a single Android process 1194 * may contain several Contexts executing on one thread with 1195 * their own logical ClassLoaders while the Java context 1196 * ClassLoader is a thread local. This is why in the case when 1197 * we have multiple packages per VM we do not set the Java 1198 * context ClassLoader to an arbitrary but instead warn the 1199 * user to set their own if we detect that they are using a 1200 * Java library that expects it to be set. 1201 */ initializeJavaContextClassLoader()1202 private void initializeJavaContextClassLoader() { 1203 IPackageManager pm = ActivityThread.getPackageManager(); 1204 android.content.pm.PackageInfo pi = 1205 PackageManager.getPackageInfoAsUserCached( 1206 mPackageName, 1207 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 1208 UserHandle.myUserId()); 1209 if (pi == null) { 1210 throw new IllegalStateException("Unable to get package info for " 1211 + mPackageName + "; is package not installed?"); 1212 } 1213 /* 1214 * Two possible indications that this package could be 1215 * sharing its virtual machine with other packages: 1216 * 1217 * 1.) the sharedUserId attribute is set in the manifest, 1218 * indicating a request to share a VM with other 1219 * packages with the same sharedUserId. 1220 * 1221 * 2.) the application element of the manifest has an 1222 * attribute specifying a non-default process name, 1223 * indicating the desire to run in another packages VM. 1224 */ 1225 boolean sharedUserIdSet = (pi.sharedUserId != null); 1226 boolean processNameNotDefault = 1227 (pi.applicationInfo != null && 1228 !mPackageName.equals(pi.applicationInfo.processName)); 1229 boolean sharable = (sharedUserIdSet || processNameNotDefault); 1230 ClassLoader contextClassLoader = 1231 (sharable) 1232 ? new WarningContextClassLoader() 1233 : mClassLoader; 1234 Thread.currentThread().setContextClassLoader(contextClassLoader); 1235 } 1236 1237 private static class WarningContextClassLoader extends ClassLoader { 1238 1239 private static boolean warned = false; 1240 warn(String methodName)1241 private void warn(String methodName) { 1242 if (warned) { 1243 return; 1244 } 1245 warned = true; 1246 Thread.currentThread().setContextClassLoader(getParent()); 1247 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " + 1248 "The class loader returned by " + 1249 "Thread.getContextClassLoader() may fail for processes " + 1250 "that host multiple applications. You should explicitly " + 1251 "specify a context class loader. For example: " + 1252 "Thread.setContextClassLoader(getClass().getClassLoader());"); 1253 } 1254 getResource(String resName)1255 @Override public URL getResource(String resName) { 1256 warn("getResource"); 1257 return getParent().getResource(resName); 1258 } 1259 getResources(String resName)1260 @Override public Enumeration<URL> getResources(String resName) throws IOException { 1261 warn("getResources"); 1262 return getParent().getResources(resName); 1263 } 1264 getResourceAsStream(String resName)1265 @Override public InputStream getResourceAsStream(String resName) { 1266 warn("getResourceAsStream"); 1267 return getParent().getResourceAsStream(resName); 1268 } 1269 loadClass(String className)1270 @Override public Class<?> loadClass(String className) throws ClassNotFoundException { 1271 warn("loadClass"); 1272 return getParent().loadClass(className); 1273 } 1274 setClassAssertionStatus(String cname, boolean enable)1275 @Override public void setClassAssertionStatus(String cname, boolean enable) { 1276 warn("setClassAssertionStatus"); 1277 getParent().setClassAssertionStatus(cname, enable); 1278 } 1279 setPackageAssertionStatus(String pname, boolean enable)1280 @Override public void setPackageAssertionStatus(String pname, boolean enable) { 1281 warn("setPackageAssertionStatus"); 1282 getParent().setPackageAssertionStatus(pname, enable); 1283 } 1284 setDefaultAssertionStatus(boolean enable)1285 @Override public void setDefaultAssertionStatus(boolean enable) { 1286 warn("setDefaultAssertionStatus"); 1287 getParent().setDefaultAssertionStatus(enable); 1288 } 1289 clearAssertionStatus()1290 @Override public void clearAssertionStatus() { 1291 warn("clearAssertionStatus"); 1292 getParent().clearAssertionStatus(); 1293 } 1294 } 1295 1296 @UnsupportedAppUsage getAppDir()1297 public String getAppDir() { 1298 return mAppDir; 1299 } 1300 getLibDir()1301 public String getLibDir() { 1302 return mLibDir; 1303 } 1304 1305 @UnsupportedAppUsage getResDir()1306 public String getResDir() { 1307 return mResDir; 1308 } 1309 getSplitAppDirs()1310 public String[] getSplitAppDirs() { 1311 return mSplitAppDirs; 1312 } 1313 1314 @UnsupportedAppUsage getSplitResDirs()1315 public String[] getSplitResDirs() { 1316 return mSplitResDirs; 1317 } 1318 1319 /** 1320 * Corresponds to {@link ApplicationInfo#resourceDirs}. 1321 */ 1322 @UnsupportedAppUsage getOverlayDirs()1323 public String[] getOverlayDirs() { 1324 return mLegacyOverlayDirs; 1325 } 1326 1327 /** 1328 * Corresponds to {@link ApplicationInfo#overlayPaths}. 1329 */ getOverlayPaths()1330 public String[] getOverlayPaths() { 1331 return mOverlayPaths; 1332 } 1333 getDataDir()1334 public String getDataDir() { 1335 return mDataDir; 1336 } 1337 1338 @UnsupportedAppUsage getDataDirFile()1339 public File getDataDirFile() { 1340 return mDataDirFile; 1341 } 1342 getDeviceProtectedDataDirFile()1343 public File getDeviceProtectedDataDirFile() { 1344 return mDeviceProtectedDataDirFile; 1345 } 1346 getCredentialProtectedDataDirFile()1347 public File getCredentialProtectedDataDirFile() { 1348 return mCredentialProtectedDataDirFile; 1349 } 1350 1351 @UnsupportedAppUsage getAssets()1352 public AssetManager getAssets() { 1353 return getResources().getAssets(); 1354 } 1355 1356 @UnsupportedAppUsage getResources()1357 public Resources getResources() { 1358 if (mResources == null) { 1359 final String[] splitPaths; 1360 try { 1361 splitPaths = getSplitPaths(null); 1362 } catch (NameNotFoundException e) { 1363 // This should never fail. 1364 throw new AssertionError("null split not found"); 1365 } 1366 1367 if (Process.myUid() == mApplicationInfo.uid) { 1368 ResourcesManager.getInstance().initializeApplicationPaths(mResDir, splitPaths); 1369 } 1370 1371 mResources = ResourcesManager.getInstance().getResources(null, mResDir, 1372 splitPaths, mLegacyOverlayDirs, mOverlayPaths, 1373 mApplicationInfo.sharedLibraryFiles, null, null, getCompatibilityInfo(), 1374 getClassLoader(), null); 1375 } 1376 return mResources; 1377 } 1378 1379 /** 1380 * This is for 3p apps accessing this hidden API directly... in which case, we don't return 1381 * the cached Application instance. 1382 */ 1383 @UnsupportedAppUsage makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation)1384 public Application makeApplication(boolean forceDefaultAppClass, 1385 Instrumentation instrumentation) { 1386 return makeApplicationInner(forceDefaultAppClass, instrumentation, 1387 /* allowDuplicateInstances= */ true); 1388 } 1389 1390 /** 1391 * This is for all the (internal) callers, for which we do return the cached instance. 1392 */ makeApplicationInner(boolean forceDefaultAppClass, Instrumentation instrumentation)1393 public Application makeApplicationInner(boolean forceDefaultAppClass, 1394 Instrumentation instrumentation) { 1395 return makeApplicationInner(forceDefaultAppClass, instrumentation, 1396 /* allowDuplicateInstances= */ false); 1397 } 1398 makeApplicationInner(boolean forceDefaultAppClass, Instrumentation instrumentation, boolean allowDuplicateInstances)1399 private Application makeApplicationInner(boolean forceDefaultAppClass, 1400 Instrumentation instrumentation, boolean allowDuplicateInstances) { 1401 if (mApplication != null) { 1402 return mApplication; 1403 } 1404 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication"); 1405 1406 synchronized (sApplications) { 1407 final Application cached = sApplications.get(mPackageName); 1408 if (cached != null) { 1409 // Looks like this is always happening for the system server, because 1410 // the LoadedApk created in systemMain() -> attach() isn't cached properly? 1411 if (!"android".equals(mPackageName)) { 1412 Slog.wtfStack(TAG, "App instance already created for package=" + mPackageName 1413 + " instance=" + cached); 1414 } 1415 if (!allowDuplicateInstances) { 1416 mApplication = cached; 1417 return cached; 1418 } 1419 // Some apps intentionally call makeApplication() to create a new Application 1420 // instance... Sigh... 1421 } 1422 } 1423 1424 Application app = null; 1425 1426 final String myProcessName = Process.myProcessName(); 1427 String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess( 1428 myProcessName); 1429 if (forceDefaultAppClass || (appClass == null)) { 1430 appClass = "android.app.Application"; 1431 } 1432 1433 try { 1434 final java.lang.ClassLoader cl = getClassLoader(); 1435 if (!mPackageName.equals("android")) { 1436 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 1437 "initializeJavaContextClassLoader"); 1438 initializeJavaContextClassLoader(); 1439 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1440 } 1441 1442 // Rewrite the R 'constants' for all library apks. 1443 SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers( 1444 false, false); 1445 for (int i = 0, n = packageIdentifiers.size(); i < n; i++) { 1446 final int id = packageIdentifiers.keyAt(i); 1447 if (id == 0x01 || id == 0x7f) { 1448 continue; 1449 } 1450 1451 rewriteRValues(cl, packageIdentifiers.valueAt(i), id); 1452 } 1453 1454 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); 1455 // The network security config needs to be aware of multiple 1456 // applications in the same process to handle discrepancies 1457 NetworkSecurityConfigProvider.handleNewApplication(appContext); 1458 app = mActivityThread.mInstrumentation.newApplication( 1459 cl, appClass, appContext); 1460 appContext.setOuterContext(app); 1461 } catch (Exception e) { 1462 if (!mActivityThread.mInstrumentation.onException(app, e)) { 1463 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1464 throw new RuntimeException( 1465 "Unable to instantiate application " + appClass 1466 + " package " + mPackageName + ": " + e.toString(), e); 1467 } 1468 } 1469 mActivityThread.mAllApplications.add(app); 1470 mApplication = app; 1471 if (!allowDuplicateInstances) { 1472 synchronized (sApplications) { 1473 sApplications.put(mPackageName, app); 1474 } 1475 } 1476 1477 if (instrumentation != null) { 1478 try { 1479 instrumentation.callApplicationOnCreate(app); 1480 } catch (Exception e) { 1481 if (!instrumentation.onException(app, e)) { 1482 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1483 throw new RuntimeException( 1484 "Unable to create application " + app.getClass().getName() 1485 + ": " + e.toString(), e); 1486 } 1487 } 1488 } 1489 1490 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1491 1492 return app; 1493 } 1494 1495 @UnsupportedAppUsage rewriteRValues(ClassLoader cl, String packageName, int id)1496 private void rewriteRValues(ClassLoader cl, String packageName, int id) { 1497 final Class<?> rClazz; 1498 try { 1499 rClazz = cl.loadClass(packageName + ".R"); 1500 } catch (ClassNotFoundException e) { 1501 // This is not necessarily an error, as some packages do not ship with resources 1502 // (or they do not need rewriting). 1503 Log.i(TAG, "No resource references to update in package " + packageName); 1504 return; 1505 } 1506 1507 final Method callback; 1508 try { 1509 callback = rClazz.getMethod("onResourcesLoaded", int.class); 1510 } catch (NoSuchMethodException e) { 1511 // No rewriting to be done. 1512 return; 1513 } 1514 1515 Throwable cause; 1516 try { 1517 callback.invoke(null, id); 1518 return; 1519 } catch (IllegalAccessException e) { 1520 cause = e; 1521 } catch (InvocationTargetException e) { 1522 cause = e.getCause(); 1523 } 1524 1525 throw new RuntimeException("Failed to rewrite resource references for " + packageName, 1526 cause); 1527 } 1528 removeContextRegistrations(Context context, String who, String what)1529 public void removeContextRegistrations(Context context, 1530 String who, String what) { 1531 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled(); 1532 synchronized (mReceivers) { 1533 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap = 1534 mReceivers.remove(context); 1535 if (rmap != null) { 1536 for (int i = 0; i < rmap.size(); i++) { 1537 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i); 1538 IntentReceiverLeaked leak = new IntentReceiverLeaked( 1539 what + " " + who + " has leaked IntentReceiver " 1540 + rd.getIntentReceiver() + " that was " + 1541 "originally registered here. Are you missing a " + 1542 "call to unregisterReceiver()?"); 1543 leak.setStackTrace(rd.getLocation().getStackTrace()); 1544 Slog.e(ActivityThread.TAG, leak.getMessage(), leak); 1545 if (reportRegistrationLeaks) { 1546 StrictMode.onIntentReceiverLeaked(leak); 1547 } 1548 try { 1549 ActivityManager.getService().unregisterReceiver( 1550 rd.getIIntentReceiver()); 1551 } catch (RemoteException e) { 1552 throw e.rethrowFromSystemServer(); 1553 } 1554 } 1555 } 1556 mUnregisteredReceivers.remove(context); 1557 } 1558 1559 synchronized (mServices) { 1560 //Slog.i(TAG, "Receiver registrations: " + mReceivers); 1561 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap = 1562 mServices.remove(context); 1563 if (smap != null) { 1564 for (int i = 0; i < smap.size(); i++) { 1565 LoadedApk.ServiceDispatcher sd = smap.valueAt(i); 1566 ServiceConnectionLeaked leak = new ServiceConnectionLeaked( 1567 what + " " + who + " has leaked ServiceConnection " 1568 + sd.getServiceConnection() + " that was originally bound here"); 1569 leak.setStackTrace(sd.getLocation().getStackTrace()); 1570 Slog.e(ActivityThread.TAG, leak.getMessage(), leak); 1571 if (reportRegistrationLeaks) { 1572 StrictMode.onServiceConnectionLeaked(leak); 1573 } 1574 try { 1575 ActivityManager.getService().unbindService( 1576 sd.getIServiceConnection()); 1577 } catch (RemoteException e) { 1578 throw e.rethrowFromSystemServer(); 1579 } 1580 sd.doForget(); 1581 } 1582 } 1583 mUnboundServices.remove(context); 1584 //Slog.i(TAG, "Service registrations: " + mServices); 1585 } 1586 } 1587 getReceiverDispatcher(BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered)1588 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r, 1589 Context context, Handler handler, 1590 Instrumentation instrumentation, boolean registered) { 1591 synchronized (mReceivers) { 1592 LoadedApk.ReceiverDispatcher rd = null; 1593 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null; 1594 if (registered) { 1595 map = mReceivers.get(context); 1596 if (map != null) { 1597 rd = map.get(r); 1598 } 1599 } 1600 if (rd == null) { 1601 rd = new ReceiverDispatcher(r, context, handler, 1602 instrumentation, registered); 1603 if (registered) { 1604 if (map == null) { 1605 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); 1606 mReceivers.put(context, map); 1607 } 1608 map.put(r, rd); 1609 } 1610 } else { 1611 rd.validate(context, handler); 1612 } 1613 rd.mForgotten = false; 1614 return rd.getIIntentReceiver(); 1615 } 1616 } 1617 forgetReceiverDispatcher(Context context, BroadcastReceiver r)1618 public IIntentReceiver forgetReceiverDispatcher(Context context, 1619 BroadcastReceiver r) { 1620 synchronized (mReceivers) { 1621 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context); 1622 LoadedApk.ReceiverDispatcher rd = null; 1623 if (map != null) { 1624 rd = map.get(r); 1625 if (rd != null) { 1626 map.remove(r); 1627 if (map.size() == 0) { 1628 mReceivers.remove(context); 1629 } 1630 if (r.getDebugUnregister()) { 1631 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder 1632 = mUnregisteredReceivers.get(context); 1633 if (holder == null) { 1634 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); 1635 mUnregisteredReceivers.put(context, holder); 1636 } 1637 RuntimeException ex = new IllegalArgumentException( 1638 "Originally unregistered here:"); 1639 ex.fillInStackTrace(); 1640 rd.setUnregisterLocation(ex); 1641 holder.put(r, rd); 1642 } 1643 rd.mForgotten = true; 1644 return rd.getIIntentReceiver(); 1645 } 1646 } 1647 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder 1648 = mUnregisteredReceivers.get(context); 1649 if (holder != null) { 1650 rd = holder.get(r); 1651 if (rd != null) { 1652 RuntimeException ex = rd.getUnregisterLocation(); 1653 throw new IllegalArgumentException( 1654 "Unregistering Receiver " + r 1655 + " that was already unregistered", ex); 1656 } 1657 } 1658 if (context == null) { 1659 throw new IllegalStateException("Unbinding Receiver " + r 1660 + " from Context that is no longer in use: " + context); 1661 } else { 1662 throw new IllegalArgumentException("Receiver not registered: " + r); 1663 } 1664 1665 } 1666 } 1667 1668 static final class ReceiverDispatcher { 1669 1670 final static class InnerReceiver extends IIntentReceiver.Stub { 1671 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher; 1672 final LoadedApk.ReceiverDispatcher mStrongRef; 1673 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong)1674 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { 1675 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); 1676 mStrongRef = strong ? rd : null; 1677 } 1678 1679 @Override performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)1680 public void performReceive(Intent intent, int resultCode, String data, 1681 Bundle extras, boolean ordered, boolean sticky, int sendingUser) { 1682 final LoadedApk.ReceiverDispatcher rd; 1683 if (intent == null) { 1684 Log.wtf(TAG, "Null intent received"); 1685 rd = null; 1686 } else { 1687 rd = mDispatcher.get(); 1688 } 1689 if (ActivityThread.DEBUG_BROADCAST) { 1690 int seq = intent.getIntExtra("seq", -1); 1691 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() 1692 + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null)); 1693 } 1694 if (rd != null) { 1695 rd.performReceive(intent, resultCode, data, extras, 1696 ordered, sticky, sendingUser); 1697 } else { 1698 // The activity manager dispatched a broadcast to a registered 1699 // receiver in this process, but before it could be delivered the 1700 // receiver was unregistered. Acknowledge the broadcast on its 1701 // behalf so that the system's broadcast sequence can continue. 1702 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1703 "Finishing broadcast to unregistered receiver"); 1704 IActivityManager mgr = ActivityManager.getService(); 1705 try { 1706 if (extras != null) { 1707 extras.setAllowFds(false); 1708 } 1709 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags()); 1710 } catch (RemoteException e) { 1711 throw e.rethrowFromSystemServer(); 1712 } 1713 } 1714 } 1715 } 1716 1717 final IIntentReceiver.Stub mIIntentReceiver; 1718 @UnsupportedAppUsage 1719 final BroadcastReceiver mReceiver; 1720 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 1721 final Context mContext; 1722 final Handler mActivityThread; 1723 final Instrumentation mInstrumentation; 1724 final boolean mRegistered; 1725 final IntentReceiverLeaked mLocation; 1726 RuntimeException mUnregisterLocation; 1727 boolean mForgotten; 1728 1729 final class Args extends BroadcastReceiver.PendingResult { 1730 private Intent mCurIntent; 1731 private final boolean mOrdered; 1732 private boolean mDispatched; 1733 private boolean mRunCalled; 1734 Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser)1735 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, 1736 boolean ordered, boolean sticky, int sendingUser) { 1737 super(resultCode, resultData, resultExtras, 1738 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered, 1739 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags()); 1740 mCurIntent = intent; 1741 mOrdered = ordered; 1742 } 1743 getRunnable()1744 public final Runnable getRunnable() { 1745 return () -> { 1746 final BroadcastReceiver receiver = mReceiver; 1747 final boolean ordered = mOrdered; 1748 1749 if (ActivityThread.DEBUG_BROADCAST) { 1750 int seq = mCurIntent.getIntExtra("seq", -1); 1751 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction() 1752 + " seq=" + seq + " to " + mReceiver); 1753 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered 1754 + " mOrderedHint=" + ordered); 1755 } 1756 1757 final IActivityManager mgr = ActivityManager.getService(); 1758 final Intent intent = mCurIntent; 1759 if (intent == null) { 1760 Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched 1761 + (mRunCalled ? ", run() has already been called" : "")); 1762 } 1763 1764 mCurIntent = null; 1765 mDispatched = true; 1766 mRunCalled = true; 1767 if (receiver == null || intent == null || mForgotten) { 1768 if (mRegistered && ordered) { 1769 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1770 "Finishing null broadcast to " + mReceiver); 1771 sendFinished(mgr); 1772 } 1773 return; 1774 } 1775 1776 if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { 1777 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 1778 "broadcastReceiveReg: " + intent.getAction()); 1779 } 1780 1781 try { 1782 ClassLoader cl = mReceiver.getClass().getClassLoader(); 1783 intent.setExtrasClassLoader(cl); 1784 // TODO: determine at registration time if caller is 1785 // protecting themselves with signature permission 1786 intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent), 1787 mContext.getAttributionSource()); 1788 setExtrasClassLoader(cl); 1789 receiver.setPendingResult(this); 1790 receiver.onReceive(mContext, intent); 1791 } catch (Exception e) { 1792 if (mRegistered && ordered) { 1793 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1794 "Finishing failed broadcast to " + mReceiver); 1795 sendFinished(mgr); 1796 } 1797 if (mInstrumentation == null || 1798 !mInstrumentation.onException(mReceiver, e)) { 1799 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1800 throw new RuntimeException( 1801 "Error receiving broadcast " + intent 1802 + " in " + mReceiver, e); 1803 } 1804 } 1805 1806 if (receiver.getPendingResult() != null) { 1807 finish(); 1808 } 1809 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1810 }; 1811 } 1812 } 1813 ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered)1814 ReceiverDispatcher(BroadcastReceiver receiver, Context context, 1815 Handler activityThread, Instrumentation instrumentation, 1816 boolean registered) { 1817 if (activityThread == null) { 1818 throw new NullPointerException("Handler must not be null"); 1819 } 1820 1821 mIIntentReceiver = new InnerReceiver(this, !registered); 1822 mReceiver = receiver; 1823 mContext = context; 1824 mActivityThread = activityThread; 1825 mInstrumentation = instrumentation; 1826 mRegistered = registered; 1827 mLocation = new IntentReceiverLeaked(null); 1828 mLocation.fillInStackTrace(); 1829 } 1830 validate(Context context, Handler activityThread)1831 void validate(Context context, Handler activityThread) { 1832 if (mContext != context) { 1833 throw new IllegalStateException( 1834 "Receiver " + mReceiver + 1835 " registered with differing Context (was " + 1836 mContext + " now " + context + ")"); 1837 } 1838 if (mActivityThread != activityThread) { 1839 throw new IllegalStateException( 1840 "Receiver " + mReceiver + 1841 " registered with differing handler (was " + 1842 mActivityThread + " now " + activityThread + ")"); 1843 } 1844 } 1845 getLocation()1846 IntentReceiverLeaked getLocation() { 1847 return mLocation; 1848 } 1849 1850 @UnsupportedAppUsage getIntentReceiver()1851 BroadcastReceiver getIntentReceiver() { 1852 return mReceiver; 1853 } 1854 1855 @UnsupportedAppUsage getIIntentReceiver()1856 IIntentReceiver getIIntentReceiver() { 1857 return mIIntentReceiver; 1858 } 1859 setUnregisterLocation(RuntimeException ex)1860 void setUnregisterLocation(RuntimeException ex) { 1861 mUnregisterLocation = ex; 1862 } 1863 getUnregisterLocation()1864 RuntimeException getUnregisterLocation() { 1865 return mUnregisterLocation; 1866 } 1867 performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)1868 public void performReceive(Intent intent, int resultCode, String data, 1869 Bundle extras, boolean ordered, boolean sticky, int sendingUser) { 1870 final Args args = new Args(intent, resultCode, data, extras, ordered, 1871 sticky, sendingUser); 1872 if (intent == null) { 1873 Log.wtf(TAG, "Null intent received"); 1874 } else { 1875 if (ActivityThread.DEBUG_BROADCAST) { 1876 int seq = intent.getIntExtra("seq", -1); 1877 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() 1878 + " seq=" + seq + " to " + mReceiver); 1879 } 1880 } 1881 if (intent == null || !mActivityThread.post(args.getRunnable())) { 1882 if (mRegistered && ordered) { 1883 IActivityManager mgr = ActivityManager.getService(); 1884 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1885 "Finishing sync broadcast to " + mReceiver); 1886 args.sendFinished(mgr); 1887 } 1888 } 1889 } 1890 1891 } 1892 1893 @UnsupportedAppUsage getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags)1894 public final IServiceConnection getServiceDispatcher(ServiceConnection c, 1895 Context context, Handler handler, int flags) { 1896 return getServiceDispatcherCommon(c, context, handler, null, flags); 1897 } 1898 getServiceDispatcher(ServiceConnection c, Context context, Executor executor, int flags)1899 public final IServiceConnection getServiceDispatcher(ServiceConnection c, 1900 Context context, Executor executor, int flags) { 1901 return getServiceDispatcherCommon(c, context, null, executor, flags); 1902 } 1903 getServiceDispatcherCommon(ServiceConnection c, Context context, Handler handler, Executor executor, int flags)1904 private IServiceConnection getServiceDispatcherCommon(ServiceConnection c, 1905 Context context, Handler handler, Executor executor, int flags) { 1906 synchronized (mServices) { 1907 LoadedApk.ServiceDispatcher sd = null; 1908 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); 1909 if (map != null) { 1910 if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c); 1911 sd = map.get(c); 1912 } 1913 if (sd == null) { 1914 if (executor != null) { 1915 sd = new ServiceDispatcher(c, context, executor, flags); 1916 } else { 1917 sd = new ServiceDispatcher(c, context, handler, flags); 1918 } 1919 if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c); 1920 if (map == null) { 1921 map = new ArrayMap<>(); 1922 mServices.put(context, map); 1923 } 1924 map.put(c, sd); 1925 } else { 1926 sd.validate(context, handler, executor); 1927 } 1928 return sd.getIServiceConnection(); 1929 } 1930 } 1931 1932 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) lookupServiceDispatcher(ServiceConnection c, Context context)1933 public IServiceConnection lookupServiceDispatcher(ServiceConnection c, 1934 Context context) { 1935 synchronized (mServices) { 1936 LoadedApk.ServiceDispatcher sd = null; 1937 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); 1938 if (map != null) { 1939 sd = map.get(c); 1940 } 1941 return sd != null ? sd.getIServiceConnection() : null; 1942 } 1943 } 1944 forgetServiceDispatcher(Context context, ServiceConnection c)1945 public final IServiceConnection forgetServiceDispatcher(Context context, 1946 ServiceConnection c) { 1947 synchronized (mServices) { 1948 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map 1949 = mServices.get(context); 1950 LoadedApk.ServiceDispatcher sd = null; 1951 if (map != null) { 1952 sd = map.get(c); 1953 if (sd != null) { 1954 if (DEBUG) Slog.d(TAG, "Removing dispatcher " + sd + " for conn " + c); 1955 map.remove(c); 1956 sd.doForget(); 1957 if (map.size() == 0) { 1958 mServices.remove(context); 1959 } 1960 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) { 1961 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder 1962 = mUnboundServices.get(context); 1963 if (holder == null) { 1964 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); 1965 mUnboundServices.put(context, holder); 1966 } 1967 RuntimeException ex = new IllegalArgumentException( 1968 "Originally unbound here:"); 1969 ex.fillInStackTrace(); 1970 sd.setUnbindLocation(ex); 1971 holder.put(c, sd); 1972 } 1973 return sd.getIServiceConnection(); 1974 } 1975 } 1976 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder 1977 = mUnboundServices.get(context); 1978 if (holder != null) { 1979 sd = holder.get(c); 1980 if (sd != null) { 1981 RuntimeException ex = sd.getUnbindLocation(); 1982 throw new IllegalArgumentException( 1983 "Unbinding Service " + c 1984 + " that was already unbound", ex); 1985 } 1986 } 1987 if (context == null) { 1988 throw new IllegalStateException("Unbinding Service " + c 1989 + " from Context that is no longer in use: " + context); 1990 } else { 1991 throw new IllegalArgumentException("Service not registered: " + c); 1992 } 1993 } 1994 } 1995 1996 static final class ServiceDispatcher { 1997 private final ServiceDispatcher.InnerConnection mIServiceConnection; 1998 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1999 private final ServiceConnection mConnection; 2000 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 2001 private final Context mContext; 2002 private final Handler mActivityThread; 2003 private final Executor mActivityExecutor; 2004 private final ServiceConnectionLeaked mLocation; 2005 private final int mFlags; 2006 2007 private RuntimeException mUnbindLocation; 2008 2009 private boolean mForgotten; 2010 2011 private static class ConnectionInfo { 2012 IBinder binder; 2013 IBinder.DeathRecipient deathMonitor; 2014 } 2015 2016 private static class InnerConnection extends IServiceConnection.Stub { 2017 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 2018 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; 2019 InnerConnection(LoadedApk.ServiceDispatcher sd)2020 InnerConnection(LoadedApk.ServiceDispatcher sd) { 2021 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); 2022 } 2023 connected(ComponentName name, IBinder service, boolean dead)2024 public void connected(ComponentName name, IBinder service, boolean dead) 2025 throws RemoteException { 2026 LoadedApk.ServiceDispatcher sd = mDispatcher.get(); 2027 if (sd != null) { 2028 sd.connected(name, service, dead); 2029 } 2030 } 2031 } 2032 2033 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections 2034 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>(); 2035 2036 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) ServiceDispatcher(ServiceConnection conn, Context context, Handler activityThread, int flags)2037 ServiceDispatcher(ServiceConnection conn, 2038 Context context, Handler activityThread, int flags) { 2039 mIServiceConnection = new InnerConnection(this); 2040 mConnection = conn; 2041 mContext = context; 2042 mActivityThread = activityThread; 2043 mActivityExecutor = null; 2044 mLocation = new ServiceConnectionLeaked(null); 2045 mLocation.fillInStackTrace(); 2046 mFlags = flags; 2047 } 2048 ServiceDispatcher(ServiceConnection conn, Context context, Executor activityExecutor, int flags)2049 ServiceDispatcher(ServiceConnection conn, 2050 Context context, Executor activityExecutor, int flags) { 2051 mIServiceConnection = new InnerConnection(this); 2052 mConnection = conn; 2053 mContext = context; 2054 mActivityThread = null; 2055 mActivityExecutor = activityExecutor; 2056 mLocation = new ServiceConnectionLeaked(null); 2057 mLocation.fillInStackTrace(); 2058 mFlags = flags; 2059 } 2060 validate(Context context, Handler activityThread, Executor activityExecutor)2061 void validate(Context context, Handler activityThread, Executor activityExecutor) { 2062 if (mContext != context) { 2063 throw new RuntimeException( 2064 "ServiceConnection " + mConnection + 2065 " registered with differing Context (was " + 2066 mContext + " now " + context + ")"); 2067 } 2068 if (mActivityThread != activityThread) { 2069 throw new RuntimeException( 2070 "ServiceConnection " + mConnection + 2071 " registered with differing handler (was " + 2072 mActivityThread + " now " + activityThread + ")"); 2073 } 2074 if (mActivityExecutor != activityExecutor) { 2075 throw new RuntimeException( 2076 "ServiceConnection " + mConnection + 2077 " registered with differing executor (was " + 2078 mActivityExecutor + " now " + activityExecutor + ")"); 2079 } 2080 } 2081 doForget()2082 void doForget() { 2083 synchronized(this) { 2084 for (int i=0; i<mActiveConnections.size(); i++) { 2085 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i); 2086 ci.binder.unlinkToDeath(ci.deathMonitor, 0); 2087 } 2088 mActiveConnections.clear(); 2089 mForgotten = true; 2090 } 2091 } 2092 getLocation()2093 ServiceConnectionLeaked getLocation() { 2094 return mLocation; 2095 } 2096 getServiceConnection()2097 ServiceConnection getServiceConnection() { 2098 return mConnection; 2099 } 2100 2101 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getIServiceConnection()2102 IServiceConnection getIServiceConnection() { 2103 return mIServiceConnection; 2104 } 2105 getFlags()2106 int getFlags() { 2107 return mFlags; 2108 } 2109 setUnbindLocation(RuntimeException ex)2110 void setUnbindLocation(RuntimeException ex) { 2111 mUnbindLocation = ex; 2112 } 2113 getUnbindLocation()2114 RuntimeException getUnbindLocation() { 2115 return mUnbindLocation; 2116 } 2117 connected(ComponentName name, IBinder service, boolean dead)2118 public void connected(ComponentName name, IBinder service, boolean dead) { 2119 if (mActivityExecutor != null) { 2120 mActivityExecutor.execute(new RunConnection(name, service, 0, dead)); 2121 } else if (mActivityThread != null) { 2122 mActivityThread.post(new RunConnection(name, service, 0, dead)); 2123 } else { 2124 doConnected(name, service, dead); 2125 } 2126 } 2127 death(ComponentName name, IBinder service)2128 public void death(ComponentName name, IBinder service) { 2129 if (mActivityExecutor != null) { 2130 mActivityExecutor.execute(new RunConnection(name, service, 1, false)); 2131 } else if (mActivityThread != null) { 2132 mActivityThread.post(new RunConnection(name, service, 1, false)); 2133 } else { 2134 doDeath(name, service); 2135 } 2136 } 2137 doConnected(ComponentName name, IBinder service, boolean dead)2138 public void doConnected(ComponentName name, IBinder service, boolean dead) { 2139 ServiceDispatcher.ConnectionInfo old; 2140 ServiceDispatcher.ConnectionInfo info; 2141 2142 synchronized (this) { 2143 if (mForgotten) { 2144 // We unbound before receiving the connection; ignore 2145 // any connection received. 2146 return; 2147 } 2148 old = mActiveConnections.get(name); 2149 if (old != null && old.binder == service) { 2150 // Huh, already have this one. Oh well! 2151 return; 2152 } 2153 2154 if (service != null) { 2155 // A new service is being connected... set it all up. 2156 info = new ConnectionInfo(); 2157 info.binder = service; 2158 info.deathMonitor = new DeathMonitor(name, service); 2159 try { 2160 service.linkToDeath(info.deathMonitor, 0); 2161 mActiveConnections.put(name, info); 2162 } catch (RemoteException e) { 2163 // This service was dead before we got it... just 2164 // don't do anything with it. 2165 mActiveConnections.remove(name); 2166 return; 2167 } 2168 2169 } else { 2170 // The named service is being disconnected... clean up. 2171 mActiveConnections.remove(name); 2172 } 2173 2174 if (old != null) { 2175 old.binder.unlinkToDeath(old.deathMonitor, 0); 2176 } 2177 } 2178 2179 // If there was an old service, it is now disconnected. 2180 if (old != null) { 2181 mConnection.onServiceDisconnected(name); 2182 } 2183 if (dead) { 2184 mConnection.onBindingDied(name); 2185 } else { 2186 // If there is a new viable service, it is now connected. 2187 if (service != null) { 2188 mConnection.onServiceConnected(name, service); 2189 } else { 2190 // The binding machinery worked, but the remote returned null from onBind(). 2191 mConnection.onNullBinding(name); 2192 } 2193 } 2194 } 2195 doDeath(ComponentName name, IBinder service)2196 public void doDeath(ComponentName name, IBinder service) { 2197 synchronized (this) { 2198 ConnectionInfo old = mActiveConnections.get(name); 2199 if (old == null || old.binder != service) { 2200 // Death for someone different than who we last 2201 // reported... just ignore it. 2202 return; 2203 } 2204 mActiveConnections.remove(name); 2205 old.binder.unlinkToDeath(old.deathMonitor, 0); 2206 } 2207 2208 mConnection.onServiceDisconnected(name); 2209 } 2210 2211 private final class RunConnection implements Runnable { RunConnection(ComponentName name, IBinder service, int command, boolean dead)2212 RunConnection(ComponentName name, IBinder service, int command, boolean dead) { 2213 mName = name; 2214 mService = service; 2215 mCommand = command; 2216 mDead = dead; 2217 } 2218 run()2219 public void run() { 2220 if (mCommand == 0) { 2221 doConnected(mName, mService, mDead); 2222 } else if (mCommand == 1) { 2223 doDeath(mName, mService); 2224 } 2225 } 2226 2227 final ComponentName mName; 2228 final IBinder mService; 2229 final int mCommand; 2230 final boolean mDead; 2231 } 2232 2233 private final class DeathMonitor implements IBinder.DeathRecipient 2234 { DeathMonitor(ComponentName name, IBinder service)2235 DeathMonitor(ComponentName name, IBinder service) { 2236 mName = name; 2237 mService = service; 2238 } 2239 binderDied()2240 public void binderDied() { 2241 death(mName, mService); 2242 } 2243 2244 final ComponentName mName; 2245 final IBinder mService; 2246 } 2247 } 2248 2249 /** 2250 * Check if the Apk paths in the cache are correct, and update them if they are not. 2251 * @hide 2252 */ checkAndUpdateApkPaths(ApplicationInfo expectedAppInfo)2253 public static void checkAndUpdateApkPaths(ApplicationInfo expectedAppInfo) { 2254 // Get the LoadedApk from the cache 2255 ActivityThread activityThread = ActivityThread.currentActivityThread(); 2256 if (activityThread == null) { 2257 Log.e(TAG, "Cannot find activity thread"); 2258 return; 2259 } 2260 checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ true); 2261 checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ false); 2262 } 2263 checkAndUpdateApkPaths(ActivityThread activityThread, ApplicationInfo expectedAppInfo, boolean cacheWithCode)2264 private static void checkAndUpdateApkPaths(ActivityThread activityThread, 2265 ApplicationInfo expectedAppInfo, boolean cacheWithCode) { 2266 String expectedCodePath = expectedAppInfo.getCodePath(); 2267 LoadedApk loadedApk = activityThread.peekPackageInfo( 2268 expectedAppInfo.packageName, /* includeCode= */ cacheWithCode); 2269 // If there is load apk cached, or if the cache is valid, don't do anything. 2270 if (loadedApk == null || loadedApk.getApplicationInfo() == null 2271 || loadedApk.getApplicationInfo().getCodePath().equals(expectedCodePath)) { 2272 return; 2273 } 2274 // Duplicate framework logic 2275 List<String> oldPaths = new ArrayList<>(); 2276 LoadedApk.makePaths(activityThread, expectedAppInfo, oldPaths); 2277 2278 // Force update the LoadedApk instance, which should update the reference in the cache 2279 loadedApk.updateApplicationInfo(expectedAppInfo, oldPaths); 2280 } 2281 2282 } 2283