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