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