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