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