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