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