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