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