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 83 public IntentReceiverLeaked(String msg) { 84 super(msg); 85 } 86 } 87 88 final class ServiceConnectionLeaked extends AndroidRuntimeException { 89 @UnsupportedAppUsage 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 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 */ 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 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 */ 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 */ 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 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 264 public AppComponentFactory getAppFactory() { 265 return mAppComponentFactory; 266 } 267 268 @UnsupportedAppUsage 269 public String getPackageName() { 270 return mPackageName; 271 } 272 273 @UnsupportedAppUsage 274 public ApplicationInfo getApplicationInfo() { 275 return mApplicationInfo; 276 } 277 278 public int getTargetSdkVersion() { 279 return mApplicationInfo.targetSdkVersion; 280 } 281 282 public boolean isSecurityViolation() { 283 return mSecurityViolation; 284 } 285 286 @UnsupportedAppUsage 287 public CompatibilityInfo getCompatibilityInfo() { 288 return mDisplayAdjustments.getCompatibilityInfo(); 289 } 290 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 */ 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 */ 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 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 396 public static void makePaths(ActivityThread activityThread, 397 ApplicationInfo aInfo, 398 List<String> outZipPaths) { 399 makePaths(activityThread, false, aInfo, outZipPaths, null); 400 } 401 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 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 */ 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 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 588 protected boolean isSplitCached(int splitIdx) { 589 return mCachedClassLoaders[splitIdx] != null; 590 } 591 592 @Override 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 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 636 ClassLoader getClassLoaderForSplit(String splitName) throws NameNotFoundException { 637 return mCachedClassLoaders[ensureSplitLoaded(splitName)]; 638 } 639 640 String[] getSplitPathsForSplit(String splitName) throws NameNotFoundException { 641 return mCachedResourcePaths[ensureSplitLoaded(splitName)]; 642 } 643 } 644 645 private SplitDependencyLoaderImpl mSplitLoader; 646 647 ClassLoader getSplitClassLoader(String splitName) throws NameNotFoundException { 648 if (mSplitLoader == null) { 649 return mClassLoader; 650 } 651 return mSplitLoader.getClassLoaderForSplit(splitName); 652 } 653 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 */ 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 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 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 709 private void setThreadPolicy(StrictMode.ThreadPolicy policy) { 710 if (mActivityThread != null && policy != null) { 711 StrictMode.setThreadPolicy(policy); 712 } 713 } 714 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 947 public ClassLoader getClassLoader() { 948 synchronized (this) { 949 if (mClassLoader == null) { 950 createOrUpdateClassLoaderLocked(null /*addedPaths*/); 951 } 952 return mClassLoader; 953 } 954 } 955 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 */ 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 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 1083 @Override public URL getResource(String resName) { 1084 warn("getResource"); 1085 return getParent().getResource(resName); 1086 } 1087 1088 @Override public Enumeration<URL> getResources(String resName) throws IOException { 1089 warn("getResources"); 1090 return getParent().getResources(resName); 1091 } 1092 1093 @Override public InputStream getResourceAsStream(String resName) { 1094 warn("getResourceAsStream"); 1095 return getParent().getResourceAsStream(resName); 1096 } 1097 1098 @Override public Class<?> loadClass(String className) throws ClassNotFoundException { 1099 warn("loadClass"); 1100 return getParent().loadClass(className); 1101 } 1102 1103 @Override public void setClassAssertionStatus(String cname, boolean enable) { 1104 warn("setClassAssertionStatus"); 1105 getParent().setClassAssertionStatus(cname, enable); 1106 } 1107 1108 @Override public void setPackageAssertionStatus(String pname, boolean enable) { 1109 warn("setPackageAssertionStatus"); 1110 getParent().setPackageAssertionStatus(pname, enable); 1111 } 1112 1113 @Override public void setDefaultAssertionStatus(boolean enable) { 1114 warn("setDefaultAssertionStatus"); 1115 getParent().setDefaultAssertionStatus(enable); 1116 } 1117 1118 @Override public void clearAssertionStatus() { 1119 warn("clearAssertionStatus"); 1120 getParent().clearAssertionStatus(); 1121 } 1122 } 1123 1124 @UnsupportedAppUsage 1125 public String getAppDir() { 1126 return mAppDir; 1127 } 1128 1129 public String getLibDir() { 1130 return mLibDir; 1131 } 1132 1133 @UnsupportedAppUsage 1134 public String getResDir() { 1135 return mResDir; 1136 } 1137 1138 public String[] getSplitAppDirs() { 1139 return mSplitAppDirs; 1140 } 1141 1142 @UnsupportedAppUsage 1143 public String[] getSplitResDirs() { 1144 return mSplitResDirs; 1145 } 1146 1147 @UnsupportedAppUsage 1148 public String[] getOverlayDirs() { 1149 return mOverlayDirs; 1150 } 1151 1152 public String getDataDir() { 1153 return mDataDir; 1154 } 1155 1156 @UnsupportedAppUsage 1157 public File getDataDirFile() { 1158 return mDataDirFile; 1159 } 1160 1161 public File getDeviceProtectedDataDirFile() { 1162 return mDeviceProtectedDataDirFile; 1163 } 1164 1165 public File getCredentialProtectedDataDirFile() { 1166 return mCredentialProtectedDataDirFile; 1167 } 1168 1169 @UnsupportedAppUsage 1170 public AssetManager getAssets() { 1171 return getResources().getAssets(); 1172 } 1173 1174 @UnsupportedAppUsage 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 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 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 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 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 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 1441 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { 1442 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); 1443 mStrongRef = strong ? rd : null; 1444 } 1445 1446 @Override 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 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 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 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 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 1606 IntentReceiverLeaked getLocation() { 1607 return mLocation; 1608 } 1609 1610 @UnsupportedAppUsage 1611 BroadcastReceiver getIntentReceiver() { 1612 return mReceiver; 1613 } 1614 1615 @UnsupportedAppUsage 1616 IIntentReceiver getIIntentReceiver() { 1617 return mIIntentReceiver; 1618 } 1619 1620 void setUnregisterLocation(RuntimeException ex) { 1621 mUnregisterLocation = ex; 1622 } 1623 1624 RuntimeException getUnregisterLocation() { 1625 return mUnregisterLocation; 1626 } 1627 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 1654 public final IServiceConnection getServiceDispatcher(ServiceConnection c, 1655 Context context, Handler handler, int flags) { 1656 return getServiceDispatcherCommon(c, context, handler, null, flags); 1657 } 1658 1659 public final IServiceConnection getServiceDispatcher(ServiceConnection c, 1660 Context context, Executor executor, int flags) { 1661 return getServiceDispatcherCommon(c, context, null, executor, flags); 1662 } 1663 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 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 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 1780 InnerConnection(LoadedApk.ServiceDispatcher sd) { 1781 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); 1782 } 1783 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 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 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 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 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 1853 ServiceConnectionLeaked getLocation() { 1854 return mLocation; 1855 } 1856 1857 ServiceConnection getServiceConnection() { 1858 return mConnection; 1859 } 1860 1861 @UnsupportedAppUsage 1862 IServiceConnection getIServiceConnection() { 1863 return mIServiceConnection; 1864 } 1865 1866 int getFlags() { 1867 return mFlags; 1868 } 1869 1870 void setUnbindLocation(RuntimeException ex) { 1871 mUnbindLocation = ex; 1872 } 1873 1874 RuntimeException getUnbindLocation() { 1875 return mUnbindLocation; 1876 } 1877 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 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 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 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 { 1971 RunConnection(ComponentName name, IBinder service, int command, boolean dead) { 1972 mName = name; 1973 mService = service; 1974 mCommand = command; 1975 mDead = dead; 1976 } 1977 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 { 1994 DeathMonitor(ComponentName name, IBinder service) { 1995 mName = name; 1996 mService = service; 1997 } 1998 1999 public void binderDied() { 2000 death(mName, mService); 2001 } 2002 2003 final ComponentName mName; 2004 final IBinder mService; 2005 } 2006 } 2007 } 2008