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