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 String libraryPermittedPath = mDataDir; 806 if (mActivityThread == null) { 807 // In a zygote context where mActivityThread is null we can't access the app data dir 808 // and including this in libraryPermittedPath would cause SELinux denials. 809 libraryPermittedPath = ""; 810 } 811 812 if (isBundledApp) { 813 // For bundled apps, add the base directory of the app (e.g., 814 // /system/app/Foo/) to the permitted paths so that it can load libraries 815 // embedded in module apks under the directory. For now, GmsCore is relying 816 // on this, but this isn't specific to the app. Also note that, we don't 817 // need to do this for unbundled apps as entire /data is already set to 818 // the permitted paths for them. 819 libraryPermittedPath += File.pathSeparator 820 + Paths.get(getAppDir()).getParent().toString(); 821 822 // This is necessary to grant bundled apps access to 823 // libraries located in subdirectories of /system/lib 824 libraryPermittedPath += File.pathSeparator + defaultSearchPaths; 825 } 826 827 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths); 828 829 if (mActivityThread != null) { 830 final String gpuDebugApp = mActivityThread.getStringCoreSetting( 831 Settings.Global.GPU_DEBUG_APP, ""); 832 if (!gpuDebugApp.isEmpty() && mPackageName.equals(gpuDebugApp)) { 833 834 // The current application is used to debug, attempt to get the debug layers. 835 try { 836 // Get the ApplicationInfo from PackageManager so that metadata fields present. 837 final ApplicationInfo ai = ActivityThread.getPackageManager() 838 .getApplicationInfo(mPackageName, PackageManager.GET_META_DATA, 839 UserHandle.myUserId()); 840 final String debugLayerPath = GraphicsEnvironment.getInstance() 841 .getDebugLayerPathsFromSettings(mActivityThread.getCoreSettings(), 842 ActivityThread.getPackageManager(), mPackageName, ai); 843 if (debugLayerPath != null) { 844 libraryPermittedPath += File.pathSeparator + debugLayerPath; 845 } 846 } catch (RemoteException e) { 847 // Unlikely to fail for applications, but in case of failure, something is wrong 848 // inside the system server, hence just skip. 849 Slog.e(ActivityThread.TAG, 850 "RemoteException when fetching debug layer paths for: " + mPackageName); 851 } 852 } 853 } 854 855 // If we're not asked to include code, we construct a classloader that has 856 // no code path included. We still need to set up the library search paths 857 // and permitted path because NativeActivity relies on it (it attempts to 858 // call System.loadLibrary() on a classloader from a LoadedApk with 859 // mIncludeCode == false). 860 if (!mIncludeCode) { 861 if (mDefaultClassLoader == null) { 862 StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads(); 863 mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoader( 864 "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp, 865 librarySearchPath, libraryPermittedPath, mBaseClassLoader, 866 null /* classLoaderName */); 867 setThreadPolicy(oldPolicy); 868 mAppComponentFactory = AppComponentFactory.DEFAULT; 869 } 870 871 if (mClassLoader == null) { 872 mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader, 873 new ApplicationInfo(mApplicationInfo)); 874 } 875 876 return; 877 } 878 879 /* 880 * With all the combination done (if necessary, actually create the java class 881 * loader and set up JIT profiling support if necessary. 882 * 883 * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils. 884 */ 885 final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) : 886 TextUtils.join(File.pathSeparator, zipPaths); 887 888 if (DEBUG) Slog.v(ActivityThread.TAG, "Class path: " + zip + 889 ", JNI path: " + librarySearchPath); 890 891 boolean needToSetupJitProfiles = false; 892 if (mDefaultClassLoader == null) { 893 // Temporarily disable logging of disk reads on the Looper thread 894 // as this is early and necessary. 895 StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads(); 896 897 List<ClassLoader> sharedLibraries = createSharedLibrariesLoaders( 898 mApplicationInfo.sharedLibraryInfos, isBundledApp, librarySearchPath, 899 libraryPermittedPath); 900 901 mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries( 902 zip, mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath, 903 libraryPermittedPath, mBaseClassLoader, 904 mApplicationInfo.classLoaderName, sharedLibraries); 905 mAppComponentFactory = createAppFactory(mApplicationInfo, mDefaultClassLoader); 906 907 setThreadPolicy(oldPolicy); 908 // Setup the class loader paths for profiling. 909 needToSetupJitProfiles = true; 910 } 911 912 if (!libPaths.isEmpty() && SystemProperties.getBoolean(PROPERTY_NAME_APPEND_NATIVE, true)) { 913 // Temporarily disable logging of disk reads on the Looper thread as this is necessary 914 StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads(); 915 try { 916 ApplicationLoaders.getDefault().addNative(mDefaultClassLoader, libPaths); 917 } finally { 918 setThreadPolicy(oldPolicy); 919 } 920 } 921 922 if (addedPaths != null && addedPaths.size() > 0) { 923 final String add = TextUtils.join(File.pathSeparator, addedPaths); 924 ApplicationLoaders.getDefault().addPath(mDefaultClassLoader, add); 925 // Setup the new code paths for profiling. 926 needToSetupJitProfiles = true; 927 } 928 929 // Setup jit profile support. 930 // 931 // It is ok to call this multiple times if the application gets updated with new splits. 932 // The runtime only keeps track of unique code paths and can handle re-registration of 933 // the same code path. There's no need to pass `addedPaths` since any new code paths 934 // are already in `mApplicationInfo`. 935 // 936 // It is NOT ok to call this function from the system_server (for any of the packages it 937 // loads code from) so we explicitly disallow it there. 938 // 939 // It is not ok to call this in a zygote context where mActivityThread is null. 940 if (needToSetupJitProfiles && !ActivityThread.isSystem() && mActivityThread != null) { 941 setupJitProfileSupport(); 942 } 943 944 // Call AppComponentFactory to select/create the main class loader of this app. 945 // Since this may call code in the app, mDefaultClassLoader must be fully set up 946 // before invoking the factory. 947 // Invoke with a copy of ApplicationInfo to protect against the app changing it. 948 if (mClassLoader == null) { 949 mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader, 950 new ApplicationInfo(mApplicationInfo)); 951 } 952 } 953 954 @UnsupportedAppUsage getClassLoader()955 public ClassLoader getClassLoader() { 956 synchronized (this) { 957 if (mClassLoader == null) { 958 createOrUpdateClassLoaderLocked(null /*addedPaths*/); 959 } 960 return mClassLoader; 961 } 962 } 963 setupJitProfileSupport()964 private void setupJitProfileSupport() { 965 if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) { 966 return; 967 } 968 969 // If we use profiles, setup the dex reporter to notify package manager 970 // of any relevant dex loads. The idle maintenance job will use the information 971 // reported to optimize the loaded dex files. 972 // Note that we only need one global reporter per app. 973 // Make sure we do this before invoking app code for the first time so that we 974 // can capture the complete application startup. 975 BaseDexClassLoader.setReporter(DexLoadReporter.getInstance()); 976 977 // Only set up profile support if the loaded apk has the same uid as the 978 // current process. 979 // Currently, we do not support profiling across different apps. 980 // (e.g. application's uid might be different when the code is 981 // loaded by another app via createApplicationContext) 982 if (mApplicationInfo.uid != Process.myUid()) { 983 return; 984 } 985 986 final List<String> codePaths = new ArrayList<>(); 987 if ((mApplicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) { 988 codePaths.add(mApplicationInfo.sourceDir); 989 } 990 if (mApplicationInfo.splitSourceDirs != null) { 991 Collections.addAll(codePaths, mApplicationInfo.splitSourceDirs); 992 } 993 994 if (codePaths.isEmpty()) { 995 // If there are no code paths there's no need to setup a profile file and register with 996 // the runtime, 997 return; 998 } 999 1000 for (int i = codePaths.size() - 1; i >= 0; i--) { 1001 String splitName = i == 0 ? null : mApplicationInfo.splitNames[i - 1]; 1002 String profileFile = ArtManager.getCurrentProfilePath( 1003 mPackageName, UserHandle.myUserId(), splitName); 1004 VMRuntime.registerAppInfo(profileFile, new String[] {codePaths.get(i)}); 1005 } 1006 1007 // Register the app data directory with the reporter. It will 1008 // help deciding whether or not a dex file is the primary apk or a 1009 // secondary dex. 1010 DexLoadReporter.getInstance().registerAppDataDir(mPackageName, mDataDir); 1011 } 1012 1013 /** 1014 * Setup value for Thread.getContextClassLoader(). If the 1015 * package will not run in in a VM with other packages, we set 1016 * the Java context ClassLoader to the 1017 * PackageInfo.getClassLoader value. However, if this VM can 1018 * contain multiple packages, we intead set the Java context 1019 * ClassLoader to a proxy that will warn about the use of Java 1020 * context ClassLoaders and then fall through to use the 1021 * system ClassLoader. 1022 * 1023 * <p> Note that this is similar to but not the same as the 1024 * android.content.Context.getClassLoader(). While both 1025 * context class loaders are typically set to the 1026 * PathClassLoader used to load the package archive in the 1027 * single application per VM case, a single Android process 1028 * may contain several Contexts executing on one thread with 1029 * their own logical ClassLoaders while the Java context 1030 * ClassLoader is a thread local. This is why in the case when 1031 * we have multiple packages per VM we do not set the Java 1032 * context ClassLoader to an arbitrary but instead warn the 1033 * user to set their own if we detect that they are using a 1034 * Java library that expects it to be set. 1035 */ initializeJavaContextClassLoader()1036 private void initializeJavaContextClassLoader() { 1037 IPackageManager pm = ActivityThread.getPackageManager(); 1038 android.content.pm.PackageInfo pi = 1039 PackageManager.getPackageInfoAsUserCached( 1040 mPackageName, 1041 PackageManager.MATCH_DEBUG_TRIAGED_MISSING, 1042 UserHandle.myUserId()); 1043 /* 1044 * Two possible indications that this package could be 1045 * sharing its virtual machine with other packages: 1046 * 1047 * 1.) the sharedUserId attribute is set in the manifest, 1048 * indicating a request to share a VM with other 1049 * packages with the same sharedUserId. 1050 * 1051 * 2.) the application element of the manifest has an 1052 * attribute specifying a non-default process name, 1053 * indicating the desire to run in another packages VM. 1054 */ 1055 boolean sharedUserIdSet = (pi.sharedUserId != null); 1056 boolean processNameNotDefault = 1057 (pi.applicationInfo != null && 1058 !mPackageName.equals(pi.applicationInfo.processName)); 1059 boolean sharable = (sharedUserIdSet || processNameNotDefault); 1060 ClassLoader contextClassLoader = 1061 (sharable) 1062 ? new WarningContextClassLoader() 1063 : mClassLoader; 1064 Thread.currentThread().setContextClassLoader(contextClassLoader); 1065 } 1066 1067 private static class WarningContextClassLoader extends ClassLoader { 1068 1069 private static boolean warned = false; 1070 warn(String methodName)1071 private void warn(String methodName) { 1072 if (warned) { 1073 return; 1074 } 1075 warned = true; 1076 Thread.currentThread().setContextClassLoader(getParent()); 1077 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " + 1078 "The class loader returned by " + 1079 "Thread.getContextClassLoader() may fail for processes " + 1080 "that host multiple applications. You should explicitly " + 1081 "specify a context class loader. For example: " + 1082 "Thread.setContextClassLoader(getClass().getClassLoader());"); 1083 } 1084 getResource(String resName)1085 @Override public URL getResource(String resName) { 1086 warn("getResource"); 1087 return getParent().getResource(resName); 1088 } 1089 getResources(String resName)1090 @Override public Enumeration<URL> getResources(String resName) throws IOException { 1091 warn("getResources"); 1092 return getParent().getResources(resName); 1093 } 1094 getResourceAsStream(String resName)1095 @Override public InputStream getResourceAsStream(String resName) { 1096 warn("getResourceAsStream"); 1097 return getParent().getResourceAsStream(resName); 1098 } 1099 loadClass(String className)1100 @Override public Class<?> loadClass(String className) throws ClassNotFoundException { 1101 warn("loadClass"); 1102 return getParent().loadClass(className); 1103 } 1104 setClassAssertionStatus(String cname, boolean enable)1105 @Override public void setClassAssertionStatus(String cname, boolean enable) { 1106 warn("setClassAssertionStatus"); 1107 getParent().setClassAssertionStatus(cname, enable); 1108 } 1109 setPackageAssertionStatus(String pname, boolean enable)1110 @Override public void setPackageAssertionStatus(String pname, boolean enable) { 1111 warn("setPackageAssertionStatus"); 1112 getParent().setPackageAssertionStatus(pname, enable); 1113 } 1114 setDefaultAssertionStatus(boolean enable)1115 @Override public void setDefaultAssertionStatus(boolean enable) { 1116 warn("setDefaultAssertionStatus"); 1117 getParent().setDefaultAssertionStatus(enable); 1118 } 1119 clearAssertionStatus()1120 @Override public void clearAssertionStatus() { 1121 warn("clearAssertionStatus"); 1122 getParent().clearAssertionStatus(); 1123 } 1124 } 1125 1126 @UnsupportedAppUsage getAppDir()1127 public String getAppDir() { 1128 return mAppDir; 1129 } 1130 getLibDir()1131 public String getLibDir() { 1132 return mLibDir; 1133 } 1134 1135 @UnsupportedAppUsage getResDir()1136 public String getResDir() { 1137 return mResDir; 1138 } 1139 getSplitAppDirs()1140 public String[] getSplitAppDirs() { 1141 return mSplitAppDirs; 1142 } 1143 1144 @UnsupportedAppUsage getSplitResDirs()1145 public String[] getSplitResDirs() { 1146 return mSplitResDirs; 1147 } 1148 1149 @UnsupportedAppUsage getOverlayDirs()1150 public String[] getOverlayDirs() { 1151 return mOverlayDirs; 1152 } 1153 getDataDir()1154 public String getDataDir() { 1155 return mDataDir; 1156 } 1157 1158 @UnsupportedAppUsage getDataDirFile()1159 public File getDataDirFile() { 1160 return mDataDirFile; 1161 } 1162 getDeviceProtectedDataDirFile()1163 public File getDeviceProtectedDataDirFile() { 1164 return mDeviceProtectedDataDirFile; 1165 } 1166 getCredentialProtectedDataDirFile()1167 public File getCredentialProtectedDataDirFile() { 1168 return mCredentialProtectedDataDirFile; 1169 } 1170 1171 @UnsupportedAppUsage getAssets()1172 public AssetManager getAssets() { 1173 return getResources().getAssets(); 1174 } 1175 1176 @UnsupportedAppUsage getResources()1177 public Resources getResources() { 1178 if (mResources == null) { 1179 final String[] splitPaths; 1180 try { 1181 splitPaths = getSplitPaths(null); 1182 } catch (NameNotFoundException e) { 1183 // This should never fail. 1184 throw new AssertionError("null split not found"); 1185 } 1186 1187 mResources = ResourcesManager.getInstance().getResources(null, mResDir, 1188 splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles, 1189 Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(), 1190 getClassLoader(), null); 1191 } 1192 return mResources; 1193 } 1194 1195 @UnsupportedAppUsage makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation)1196 public Application makeApplication(boolean forceDefaultAppClass, 1197 Instrumentation instrumentation) { 1198 if (mApplication != null) { 1199 return mApplication; 1200 } 1201 1202 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication"); 1203 1204 Application app = null; 1205 1206 String appClass = mApplicationInfo.className; 1207 if (forceDefaultAppClass || (appClass == null)) { 1208 appClass = "android.app.Application"; 1209 } 1210 1211 try { 1212 final java.lang.ClassLoader cl = getClassLoader(); 1213 if (!mPackageName.equals("android")) { 1214 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 1215 "initializeJavaContextClassLoader"); 1216 initializeJavaContextClassLoader(); 1217 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1218 } 1219 1220 // Rewrite the R 'constants' for all library apks. 1221 SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers( 1222 false, false); 1223 for (int i = 0, n = packageIdentifiers.size(); i < n; i++) { 1224 final int id = packageIdentifiers.keyAt(i); 1225 if (id == 0x01 || id == 0x7f) { 1226 continue; 1227 } 1228 1229 rewriteRValues(cl, packageIdentifiers.valueAt(i), id); 1230 } 1231 1232 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); 1233 // The network security config needs to be aware of multiple 1234 // applications in the same process to handle discrepancies 1235 NetworkSecurityConfigProvider.handleNewApplication(appContext); 1236 app = mActivityThread.mInstrumentation.newApplication( 1237 cl, appClass, appContext); 1238 appContext.setOuterContext(app); 1239 } catch (Exception e) { 1240 if (!mActivityThread.mInstrumentation.onException(app, e)) { 1241 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1242 throw new RuntimeException( 1243 "Unable to instantiate application " + appClass 1244 + ": " + e.toString(), e); 1245 } 1246 } 1247 mActivityThread.mAllApplications.add(app); 1248 mApplication = app; 1249 1250 if (instrumentation != null) { 1251 try { 1252 instrumentation.callApplicationOnCreate(app); 1253 } catch (Exception e) { 1254 if (!instrumentation.onException(app, e)) { 1255 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1256 throw new RuntimeException( 1257 "Unable to create application " + app.getClass().getName() 1258 + ": " + e.toString(), e); 1259 } 1260 } 1261 } 1262 1263 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1264 1265 return app; 1266 } 1267 1268 @UnsupportedAppUsage rewriteRValues(ClassLoader cl, String packageName, int id)1269 private void rewriteRValues(ClassLoader cl, String packageName, int id) { 1270 final Class<?> rClazz; 1271 try { 1272 rClazz = cl.loadClass(packageName + ".R"); 1273 } catch (ClassNotFoundException e) { 1274 // This is not necessarily an error, as some packages do not ship with resources 1275 // (or they do not need rewriting). 1276 Log.i(TAG, "No resource references to update in package " + packageName); 1277 return; 1278 } 1279 1280 final Method callback; 1281 try { 1282 callback = rClazz.getMethod("onResourcesLoaded", int.class); 1283 } catch (NoSuchMethodException e) { 1284 // No rewriting to be done. 1285 return; 1286 } 1287 1288 Throwable cause; 1289 try { 1290 callback.invoke(null, id); 1291 return; 1292 } catch (IllegalAccessException e) { 1293 cause = e; 1294 } catch (InvocationTargetException e) { 1295 cause = e.getCause(); 1296 } 1297 1298 throw new RuntimeException("Failed to rewrite resource references for " + packageName, 1299 cause); 1300 } 1301 removeContextRegistrations(Context context, String who, String what)1302 public void removeContextRegistrations(Context context, 1303 String who, String what) { 1304 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled(); 1305 synchronized (mReceivers) { 1306 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap = 1307 mReceivers.remove(context); 1308 if (rmap != null) { 1309 for (int i = 0; i < rmap.size(); i++) { 1310 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i); 1311 IntentReceiverLeaked leak = new IntentReceiverLeaked( 1312 what + " " + who + " has leaked IntentReceiver " 1313 + rd.getIntentReceiver() + " that was " + 1314 "originally registered here. Are you missing a " + 1315 "call to unregisterReceiver()?"); 1316 leak.setStackTrace(rd.getLocation().getStackTrace()); 1317 Slog.e(ActivityThread.TAG, leak.getMessage(), leak); 1318 if (reportRegistrationLeaks) { 1319 StrictMode.onIntentReceiverLeaked(leak); 1320 } 1321 try { 1322 ActivityManager.getService().unregisterReceiver( 1323 rd.getIIntentReceiver()); 1324 } catch (RemoteException e) { 1325 throw e.rethrowFromSystemServer(); 1326 } 1327 } 1328 } 1329 mUnregisteredReceivers.remove(context); 1330 } 1331 1332 synchronized (mServices) { 1333 //Slog.i(TAG, "Receiver registrations: " + mReceivers); 1334 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap = 1335 mServices.remove(context); 1336 if (smap != null) { 1337 for (int i = 0; i < smap.size(); i++) { 1338 LoadedApk.ServiceDispatcher sd = smap.valueAt(i); 1339 ServiceConnectionLeaked leak = new ServiceConnectionLeaked( 1340 what + " " + who + " has leaked ServiceConnection " 1341 + sd.getServiceConnection() + " that was originally bound here"); 1342 leak.setStackTrace(sd.getLocation().getStackTrace()); 1343 Slog.e(ActivityThread.TAG, leak.getMessage(), leak); 1344 if (reportRegistrationLeaks) { 1345 StrictMode.onServiceConnectionLeaked(leak); 1346 } 1347 try { 1348 ActivityManager.getService().unbindService( 1349 sd.getIServiceConnection()); 1350 } catch (RemoteException e) { 1351 throw e.rethrowFromSystemServer(); 1352 } 1353 sd.doForget(); 1354 } 1355 } 1356 mUnboundServices.remove(context); 1357 //Slog.i(TAG, "Service registrations: " + mServices); 1358 } 1359 } 1360 getReceiverDispatcher(BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered)1361 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r, 1362 Context context, Handler handler, 1363 Instrumentation instrumentation, boolean registered) { 1364 synchronized (mReceivers) { 1365 LoadedApk.ReceiverDispatcher rd = null; 1366 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null; 1367 if (registered) { 1368 map = mReceivers.get(context); 1369 if (map != null) { 1370 rd = map.get(r); 1371 } 1372 } 1373 if (rd == null) { 1374 rd = new ReceiverDispatcher(r, context, handler, 1375 instrumentation, registered); 1376 if (registered) { 1377 if (map == null) { 1378 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); 1379 mReceivers.put(context, map); 1380 } 1381 map.put(r, rd); 1382 } 1383 } else { 1384 rd.validate(context, handler); 1385 } 1386 rd.mForgotten = false; 1387 return rd.getIIntentReceiver(); 1388 } 1389 } 1390 forgetReceiverDispatcher(Context context, BroadcastReceiver r)1391 public IIntentReceiver forgetReceiverDispatcher(Context context, 1392 BroadcastReceiver r) { 1393 synchronized (mReceivers) { 1394 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context); 1395 LoadedApk.ReceiverDispatcher rd = null; 1396 if (map != null) { 1397 rd = map.get(r); 1398 if (rd != null) { 1399 map.remove(r); 1400 if (map.size() == 0) { 1401 mReceivers.remove(context); 1402 } 1403 if (r.getDebugUnregister()) { 1404 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder 1405 = mUnregisteredReceivers.get(context); 1406 if (holder == null) { 1407 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); 1408 mUnregisteredReceivers.put(context, holder); 1409 } 1410 RuntimeException ex = new IllegalArgumentException( 1411 "Originally unregistered here:"); 1412 ex.fillInStackTrace(); 1413 rd.setUnregisterLocation(ex); 1414 holder.put(r, rd); 1415 } 1416 rd.mForgotten = true; 1417 return rd.getIIntentReceiver(); 1418 } 1419 } 1420 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder 1421 = mUnregisteredReceivers.get(context); 1422 if (holder != null) { 1423 rd = holder.get(r); 1424 if (rd != null) { 1425 RuntimeException ex = rd.getUnregisterLocation(); 1426 throw new IllegalArgumentException( 1427 "Unregistering Receiver " + r 1428 + " that was already unregistered", ex); 1429 } 1430 } 1431 if (context == null) { 1432 throw new IllegalStateException("Unbinding Receiver " + r 1433 + " from Context that is no longer in use: " + context); 1434 } else { 1435 throw new IllegalArgumentException("Receiver not registered: " + r); 1436 } 1437 1438 } 1439 } 1440 1441 static final class ReceiverDispatcher { 1442 1443 final static class InnerReceiver extends IIntentReceiver.Stub { 1444 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher; 1445 final LoadedApk.ReceiverDispatcher mStrongRef; 1446 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong)1447 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { 1448 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); 1449 mStrongRef = strong ? rd : null; 1450 } 1451 1452 @Override performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)1453 public void performReceive(Intent intent, int resultCode, String data, 1454 Bundle extras, boolean ordered, boolean sticky, int sendingUser) { 1455 final LoadedApk.ReceiverDispatcher rd; 1456 if (intent == null) { 1457 Log.wtf(TAG, "Null intent received"); 1458 rd = null; 1459 } else { 1460 rd = mDispatcher.get(); 1461 } 1462 if (ActivityThread.DEBUG_BROADCAST) { 1463 int seq = intent.getIntExtra("seq", -1); 1464 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() 1465 + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null)); 1466 } 1467 if (rd != null) { 1468 rd.performReceive(intent, resultCode, data, extras, 1469 ordered, sticky, sendingUser); 1470 } else { 1471 // The activity manager dispatched a broadcast to a registered 1472 // receiver in this process, but before it could be delivered the 1473 // receiver was unregistered. Acknowledge the broadcast on its 1474 // behalf so that the system's broadcast sequence can continue. 1475 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1476 "Finishing broadcast to unregistered receiver"); 1477 IActivityManager mgr = ActivityManager.getService(); 1478 try { 1479 if (extras != null) { 1480 extras.setAllowFds(false); 1481 } 1482 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags()); 1483 } catch (RemoteException e) { 1484 throw e.rethrowFromSystemServer(); 1485 } 1486 } 1487 } 1488 } 1489 1490 final IIntentReceiver.Stub mIIntentReceiver; 1491 @UnsupportedAppUsage 1492 final BroadcastReceiver mReceiver; 1493 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 1494 final Context mContext; 1495 final Handler mActivityThread; 1496 final Instrumentation mInstrumentation; 1497 final boolean mRegistered; 1498 final IntentReceiverLeaked mLocation; 1499 RuntimeException mUnregisterLocation; 1500 boolean mForgotten; 1501 1502 final class Args extends BroadcastReceiver.PendingResult { 1503 private Intent mCurIntent; 1504 private final boolean mOrdered; 1505 private boolean mDispatched; 1506 private boolean mRunCalled; 1507 Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser)1508 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, 1509 boolean ordered, boolean sticky, int sendingUser) { 1510 super(resultCode, resultData, resultExtras, 1511 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered, 1512 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags()); 1513 mCurIntent = intent; 1514 mOrdered = ordered; 1515 } 1516 getRunnable()1517 public final Runnable getRunnable() { 1518 return () -> { 1519 final BroadcastReceiver receiver = mReceiver; 1520 final boolean ordered = mOrdered; 1521 1522 if (ActivityThread.DEBUG_BROADCAST) { 1523 int seq = mCurIntent.getIntExtra("seq", -1); 1524 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction() 1525 + " seq=" + seq + " to " + mReceiver); 1526 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered 1527 + " mOrderedHint=" + ordered); 1528 } 1529 1530 final IActivityManager mgr = ActivityManager.getService(); 1531 final Intent intent = mCurIntent; 1532 if (intent == null) { 1533 Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched 1534 + (mRunCalled ? ", run() has already been called" : "")); 1535 } 1536 1537 mCurIntent = null; 1538 mDispatched = true; 1539 mRunCalled = true; 1540 if (receiver == null || intent == null || mForgotten) { 1541 if (mRegistered && ordered) { 1542 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1543 "Finishing null broadcast to " + mReceiver); 1544 sendFinished(mgr); 1545 } 1546 return; 1547 } 1548 1549 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg"); 1550 try { 1551 ClassLoader cl = mReceiver.getClass().getClassLoader(); 1552 intent.setExtrasClassLoader(cl); 1553 intent.prepareToEnterProcess(); 1554 setExtrasClassLoader(cl); 1555 receiver.setPendingResult(this); 1556 receiver.onReceive(mContext, intent); 1557 } catch (Exception e) { 1558 if (mRegistered && ordered) { 1559 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1560 "Finishing failed broadcast to " + mReceiver); 1561 sendFinished(mgr); 1562 } 1563 if (mInstrumentation == null || 1564 !mInstrumentation.onException(mReceiver, e)) { 1565 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1566 throw new RuntimeException( 1567 "Error receiving broadcast " + intent 1568 + " in " + mReceiver, e); 1569 } 1570 } 1571 1572 if (receiver.getPendingResult() != null) { 1573 finish(); 1574 } 1575 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1576 }; 1577 } 1578 } 1579 ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered)1580 ReceiverDispatcher(BroadcastReceiver receiver, Context context, 1581 Handler activityThread, Instrumentation instrumentation, 1582 boolean registered) { 1583 if (activityThread == null) { 1584 throw new NullPointerException("Handler must not be null"); 1585 } 1586 1587 mIIntentReceiver = new InnerReceiver(this, !registered); 1588 mReceiver = receiver; 1589 mContext = context; 1590 mActivityThread = activityThread; 1591 mInstrumentation = instrumentation; 1592 mRegistered = registered; 1593 mLocation = new IntentReceiverLeaked(null); 1594 mLocation.fillInStackTrace(); 1595 } 1596 validate(Context context, Handler activityThread)1597 void validate(Context context, Handler activityThread) { 1598 if (mContext != context) { 1599 throw new IllegalStateException( 1600 "Receiver " + mReceiver + 1601 " registered with differing Context (was " + 1602 mContext + " now " + context + ")"); 1603 } 1604 if (mActivityThread != activityThread) { 1605 throw new IllegalStateException( 1606 "Receiver " + mReceiver + 1607 " registered with differing handler (was " + 1608 mActivityThread + " now " + activityThread + ")"); 1609 } 1610 } 1611 getLocation()1612 IntentReceiverLeaked getLocation() { 1613 return mLocation; 1614 } 1615 1616 @UnsupportedAppUsage getIntentReceiver()1617 BroadcastReceiver getIntentReceiver() { 1618 return mReceiver; 1619 } 1620 1621 @UnsupportedAppUsage getIIntentReceiver()1622 IIntentReceiver getIIntentReceiver() { 1623 return mIIntentReceiver; 1624 } 1625 setUnregisterLocation(RuntimeException ex)1626 void setUnregisterLocation(RuntimeException ex) { 1627 mUnregisterLocation = ex; 1628 } 1629 getUnregisterLocation()1630 RuntimeException getUnregisterLocation() { 1631 return mUnregisterLocation; 1632 } 1633 performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)1634 public void performReceive(Intent intent, int resultCode, String data, 1635 Bundle extras, boolean ordered, boolean sticky, int sendingUser) { 1636 final Args args = new Args(intent, resultCode, data, extras, ordered, 1637 sticky, sendingUser); 1638 if (intent == null) { 1639 Log.wtf(TAG, "Null intent received"); 1640 } else { 1641 if (ActivityThread.DEBUG_BROADCAST) { 1642 int seq = intent.getIntExtra("seq", -1); 1643 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() 1644 + " seq=" + seq + " to " + mReceiver); 1645 } 1646 } 1647 if (intent == null || !mActivityThread.post(args.getRunnable())) { 1648 if (mRegistered && ordered) { 1649 IActivityManager mgr = ActivityManager.getService(); 1650 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, 1651 "Finishing sync broadcast to " + mReceiver); 1652 args.sendFinished(mgr); 1653 } 1654 } 1655 } 1656 1657 } 1658 1659 @UnsupportedAppUsage getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags)1660 public final IServiceConnection getServiceDispatcher(ServiceConnection c, 1661 Context context, Handler handler, int flags) { 1662 return getServiceDispatcherCommon(c, context, handler, null, flags); 1663 } 1664 getServiceDispatcher(ServiceConnection c, Context context, Executor executor, int flags)1665 public final IServiceConnection getServiceDispatcher(ServiceConnection c, 1666 Context context, Executor executor, int flags) { 1667 return getServiceDispatcherCommon(c, context, null, executor, flags); 1668 } 1669 getServiceDispatcherCommon(ServiceConnection c, Context context, Handler handler, Executor executor, int flags)1670 private IServiceConnection getServiceDispatcherCommon(ServiceConnection c, 1671 Context context, Handler handler, Executor executor, int flags) { 1672 synchronized (mServices) { 1673 LoadedApk.ServiceDispatcher sd = null; 1674 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); 1675 if (map != null) { 1676 if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c); 1677 sd = map.get(c); 1678 } 1679 if (sd == null) { 1680 if (executor != null) { 1681 sd = new ServiceDispatcher(c, context, executor, flags); 1682 } else { 1683 sd = new ServiceDispatcher(c, context, handler, flags); 1684 } 1685 if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c); 1686 if (map == null) { 1687 map = new ArrayMap<>(); 1688 mServices.put(context, map); 1689 } 1690 map.put(c, sd); 1691 } else { 1692 sd.validate(context, handler, executor); 1693 } 1694 return sd.getIServiceConnection(); 1695 } 1696 } 1697 1698 @UnsupportedAppUsage lookupServiceDispatcher(ServiceConnection c, Context context)1699 public IServiceConnection lookupServiceDispatcher(ServiceConnection c, 1700 Context context) { 1701 synchronized (mServices) { 1702 LoadedApk.ServiceDispatcher sd = null; 1703 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); 1704 if (map != null) { 1705 sd = map.get(c); 1706 } 1707 return sd != null ? sd.getIServiceConnection() : null; 1708 } 1709 } 1710 forgetServiceDispatcher(Context context, ServiceConnection c)1711 public final IServiceConnection forgetServiceDispatcher(Context context, 1712 ServiceConnection c) { 1713 synchronized (mServices) { 1714 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map 1715 = mServices.get(context); 1716 LoadedApk.ServiceDispatcher sd = null; 1717 if (map != null) { 1718 sd = map.get(c); 1719 if (sd != null) { 1720 if (DEBUG) Slog.d(TAG, "Removing dispatcher " + sd + " for conn " + c); 1721 map.remove(c); 1722 sd.doForget(); 1723 if (map.size() == 0) { 1724 mServices.remove(context); 1725 } 1726 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) { 1727 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder 1728 = mUnboundServices.get(context); 1729 if (holder == null) { 1730 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); 1731 mUnboundServices.put(context, holder); 1732 } 1733 RuntimeException ex = new IllegalArgumentException( 1734 "Originally unbound here:"); 1735 ex.fillInStackTrace(); 1736 sd.setUnbindLocation(ex); 1737 holder.put(c, sd); 1738 } 1739 return sd.getIServiceConnection(); 1740 } 1741 } 1742 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder 1743 = mUnboundServices.get(context); 1744 if (holder != null) { 1745 sd = holder.get(c); 1746 if (sd != null) { 1747 RuntimeException ex = sd.getUnbindLocation(); 1748 throw new IllegalArgumentException( 1749 "Unbinding Service " + c 1750 + " that was already unbound", ex); 1751 } 1752 } 1753 if (context == null) { 1754 throw new IllegalStateException("Unbinding Service " + c 1755 + " from Context that is no longer in use: " + context); 1756 } else { 1757 throw new IllegalArgumentException("Service not registered: " + c); 1758 } 1759 } 1760 } 1761 1762 static final class ServiceDispatcher { 1763 private final ServiceDispatcher.InnerConnection mIServiceConnection; 1764 @UnsupportedAppUsage 1765 private final ServiceConnection mConnection; 1766 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 1767 private final Context mContext; 1768 private final Handler mActivityThread; 1769 private final Executor mActivityExecutor; 1770 private final ServiceConnectionLeaked mLocation; 1771 private final int mFlags; 1772 1773 private RuntimeException mUnbindLocation; 1774 1775 private boolean mForgotten; 1776 1777 private static class ConnectionInfo { 1778 IBinder binder; 1779 IBinder.DeathRecipient deathMonitor; 1780 } 1781 1782 private static class InnerConnection extends IServiceConnection.Stub { 1783 @UnsupportedAppUsage 1784 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; 1785 InnerConnection(LoadedApk.ServiceDispatcher sd)1786 InnerConnection(LoadedApk.ServiceDispatcher sd) { 1787 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); 1788 } 1789 connected(ComponentName name, IBinder service, boolean dead)1790 public void connected(ComponentName name, IBinder service, boolean dead) 1791 throws RemoteException { 1792 LoadedApk.ServiceDispatcher sd = mDispatcher.get(); 1793 if (sd != null) { 1794 sd.connected(name, service, dead); 1795 } 1796 } 1797 } 1798 1799 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections 1800 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>(); 1801 1802 @UnsupportedAppUsage ServiceDispatcher(ServiceConnection conn, Context context, Handler activityThread, int flags)1803 ServiceDispatcher(ServiceConnection conn, 1804 Context context, Handler activityThread, int flags) { 1805 mIServiceConnection = new InnerConnection(this); 1806 mConnection = conn; 1807 mContext = context; 1808 mActivityThread = activityThread; 1809 mActivityExecutor = null; 1810 mLocation = new ServiceConnectionLeaked(null); 1811 mLocation.fillInStackTrace(); 1812 mFlags = flags; 1813 } 1814 ServiceDispatcher(ServiceConnection conn, Context context, Executor activityExecutor, int flags)1815 ServiceDispatcher(ServiceConnection conn, 1816 Context context, Executor activityExecutor, int flags) { 1817 mIServiceConnection = new InnerConnection(this); 1818 mConnection = conn; 1819 mContext = context; 1820 mActivityThread = null; 1821 mActivityExecutor = activityExecutor; 1822 mLocation = new ServiceConnectionLeaked(null); 1823 mLocation.fillInStackTrace(); 1824 mFlags = flags; 1825 } 1826 validate(Context context, Handler activityThread, Executor activityExecutor)1827 void validate(Context context, Handler activityThread, Executor activityExecutor) { 1828 if (mContext != context) { 1829 throw new RuntimeException( 1830 "ServiceConnection " + mConnection + 1831 " registered with differing Context (was " + 1832 mContext + " now " + context + ")"); 1833 } 1834 if (mActivityThread != activityThread) { 1835 throw new RuntimeException( 1836 "ServiceConnection " + mConnection + 1837 " registered with differing handler (was " + 1838 mActivityThread + " now " + activityThread + ")"); 1839 } 1840 if (mActivityExecutor != activityExecutor) { 1841 throw new RuntimeException( 1842 "ServiceConnection " + mConnection + 1843 " registered with differing executor (was " + 1844 mActivityExecutor + " now " + activityExecutor + ")"); 1845 } 1846 } 1847 doForget()1848 void doForget() { 1849 synchronized(this) { 1850 for (int i=0; i<mActiveConnections.size(); i++) { 1851 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i); 1852 ci.binder.unlinkToDeath(ci.deathMonitor, 0); 1853 } 1854 mActiveConnections.clear(); 1855 mForgotten = true; 1856 } 1857 } 1858 getLocation()1859 ServiceConnectionLeaked getLocation() { 1860 return mLocation; 1861 } 1862 getServiceConnection()1863 ServiceConnection getServiceConnection() { 1864 return mConnection; 1865 } 1866 1867 @UnsupportedAppUsage getIServiceConnection()1868 IServiceConnection getIServiceConnection() { 1869 return mIServiceConnection; 1870 } 1871 getFlags()1872 int getFlags() { 1873 return mFlags; 1874 } 1875 setUnbindLocation(RuntimeException ex)1876 void setUnbindLocation(RuntimeException ex) { 1877 mUnbindLocation = ex; 1878 } 1879 getUnbindLocation()1880 RuntimeException getUnbindLocation() { 1881 return mUnbindLocation; 1882 } 1883 connected(ComponentName name, IBinder service, boolean dead)1884 public void connected(ComponentName name, IBinder service, boolean dead) { 1885 if (mActivityExecutor != null) { 1886 mActivityExecutor.execute(new RunConnection(name, service, 0, dead)); 1887 } else if (mActivityThread != null) { 1888 mActivityThread.post(new RunConnection(name, service, 0, dead)); 1889 } else { 1890 doConnected(name, service, dead); 1891 } 1892 } 1893 death(ComponentName name, IBinder service)1894 public void death(ComponentName name, IBinder service) { 1895 if (mActivityExecutor != null) { 1896 mActivityExecutor.execute(new RunConnection(name, service, 1, false)); 1897 } else if (mActivityThread != null) { 1898 mActivityThread.post(new RunConnection(name, service, 1, false)); 1899 } else { 1900 doDeath(name, service); 1901 } 1902 } 1903 doConnected(ComponentName name, IBinder service, boolean dead)1904 public void doConnected(ComponentName name, IBinder service, boolean dead) { 1905 ServiceDispatcher.ConnectionInfo old; 1906 ServiceDispatcher.ConnectionInfo info; 1907 1908 synchronized (this) { 1909 if (mForgotten) { 1910 // We unbound before receiving the connection; ignore 1911 // any connection received. 1912 return; 1913 } 1914 old = mActiveConnections.get(name); 1915 if (old != null && old.binder == service) { 1916 // Huh, already have this one. Oh well! 1917 return; 1918 } 1919 1920 if (service != null) { 1921 // A new service is being connected... set it all up. 1922 info = new ConnectionInfo(); 1923 info.binder = service; 1924 info.deathMonitor = new DeathMonitor(name, service); 1925 try { 1926 service.linkToDeath(info.deathMonitor, 0); 1927 mActiveConnections.put(name, info); 1928 } catch (RemoteException e) { 1929 // This service was dead before we got it... just 1930 // don't do anything with it. 1931 mActiveConnections.remove(name); 1932 return; 1933 } 1934 1935 } else { 1936 // The named service is being disconnected... clean up. 1937 mActiveConnections.remove(name); 1938 } 1939 1940 if (old != null) { 1941 old.binder.unlinkToDeath(old.deathMonitor, 0); 1942 } 1943 } 1944 1945 // If there was an old service, it is now disconnected. 1946 if (old != null) { 1947 mConnection.onServiceDisconnected(name); 1948 } 1949 if (dead) { 1950 mConnection.onBindingDied(name); 1951 } 1952 // If there is a new viable service, it is now connected. 1953 if (service != null) { 1954 mConnection.onServiceConnected(name, service); 1955 } else { 1956 // The binding machinery worked, but the remote returned null from onBind(). 1957 mConnection.onNullBinding(name); 1958 } 1959 } 1960 doDeath(ComponentName name, IBinder service)1961 public void doDeath(ComponentName name, IBinder service) { 1962 synchronized (this) { 1963 ConnectionInfo old = mActiveConnections.get(name); 1964 if (old == null || old.binder != service) { 1965 // Death for someone different than who we last 1966 // reported... just ignore it. 1967 return; 1968 } 1969 mActiveConnections.remove(name); 1970 old.binder.unlinkToDeath(old.deathMonitor, 0); 1971 } 1972 1973 mConnection.onServiceDisconnected(name); 1974 } 1975 1976 private final class RunConnection implements Runnable { RunConnection(ComponentName name, IBinder service, int command, boolean dead)1977 RunConnection(ComponentName name, IBinder service, int command, boolean dead) { 1978 mName = name; 1979 mService = service; 1980 mCommand = command; 1981 mDead = dead; 1982 } 1983 run()1984 public void run() { 1985 if (mCommand == 0) { 1986 doConnected(mName, mService, mDead); 1987 } else if (mCommand == 1) { 1988 doDeath(mName, mService); 1989 } 1990 } 1991 1992 final ComponentName mName; 1993 final IBinder mService; 1994 final int mCommand; 1995 final boolean mDead; 1996 } 1997 1998 private final class DeathMonitor implements IBinder.DeathRecipient 1999 { DeathMonitor(ComponentName name, IBinder service)2000 DeathMonitor(ComponentName name, IBinder service) { 2001 mName = name; 2002 mService = service; 2003 } 2004 binderDied()2005 public void binderDied() { 2006 death(mName, mService); 2007 } 2008 2009 final ComponentName mName; 2010 final IBinder mService; 2011 } 2012 } 2013 } 2014