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