blob: b65faa98cdca64d2167bb6d54525b364d2704462 [file] [log] [blame]
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -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
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070019import android.text.TextUtils;
Dianne Hackbornadd005c2013-07-17 18:43:12 -070020import android.util.ArrayMap;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070021import android.content.BroadcastReceiver;
22import android.content.ComponentName;
23import android.content.Context;
24import android.content.IIntentReceiver;
25import android.content.Intent;
26import android.content.ServiceConnection;
27import android.content.pm.ApplicationInfo;
28import android.content.pm.IPackageManager;
29import android.content.pm.PackageManager;
30import android.content.res.AssetManager;
31import android.content.res.CompatibilityInfo;
32import android.content.res.Resources;
33import android.os.Bundle;
Jeff Sharkey15447792015-11-05 16:18:51 -080034import android.os.FileUtils;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070035import android.os.Handler;
36import android.os.IBinder;
37import android.os.Process;
38import android.os.RemoteException;
Brad Fitzpatrick624d50f2010-11-09 14:25:12 -080039import android.os.StrictMode;
Dianne Hackborn1ded0b12012-04-26 14:14:50 -070040import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070041import android.os.UserHandle;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070042import android.util.AndroidRuntimeException;
Adam Lesinski2cb761e2014-08-15 13:59:02 -070043import android.util.Log;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070044import android.util.Slog;
Adam Lesinskide898ff2014-01-29 18:20:45 -080045import android.util.SparseArray;
Craig Mautner48d0d182013-06-11 07:53:06 -070046import android.view.DisplayAdjustments;
Jeff Browna492c3a2012-08-23 19:48:44 -070047import android.view.Display;
jgu214741cd92014-12-17 17:23:29 -050048import android.os.SystemProperties;
Jeff Sharkeyb9f36742015-04-08 21:02:14 -070049
Narayan Kamath7dba6eb2014-07-16 08:53:30 +010050import dalvik.system.VMRuntime;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070051
52import java.io.File;
53import java.io.IOException;
54import java.io.InputStream;
55import java.lang.ref.WeakReference;
Adam Lesinski1e4663852014-08-15 14:47:28 -070056import java.lang.reflect.InvocationTargetException;
57import java.lang.reflect.Method;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070058import java.net.URL;
Dmitriy Ivanove56b3f62015-06-05 22:00:13 -070059import java.util.List;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070060import java.util.ArrayList;
61import java.util.Collections;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070062import java.util.Enumeration;
Narayan Kamath20531682014-07-14 13:18:43 +010063import java.util.Objects;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070064
65final class IntentReceiverLeaked extends AndroidRuntimeException {
66 public IntentReceiverLeaked(String msg) {
67 super(msg);
68 }
69}
70
71final class ServiceConnectionLeaked extends AndroidRuntimeException {
72 public ServiceConnectionLeaked(String msg) {
73 super(msg);
74 }
75}
76
77/**
78 * Local state maintained about a currently loaded .apk.
79 * @hide
80 */
Dianne Hackborn5fd21692011-06-07 14:09:47 -070081public final class LoadedApk {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070082
Amith Yamasani742a6712011-05-04 14:49:28 -070083 private static final String TAG = "LoadedApk";
84
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070085 private final ActivityThread mActivityThread;
Jeff Browndefd4a62014-03-10 21:24:37 -070086 private ApplicationInfo mApplicationInfo;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070087 final String mPackageName;
88 private final String mAppDir;
89 private final String mResDir;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070090 private final String[] mSplitAppDirs;
91 private final String[] mSplitResDirs;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +010092 private final String[] mOverlayDirs;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070093 private final String[] mSharedLibraries;
94 private final String mDataDir;
Kenny Root85387d72010-08-26 10:13:11 -070095 private final String mLibDir;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070096 private final File mDataDirFile;
Jeff Sharkey15447792015-11-05 16:18:51 -080097 private final File mDeviceEncryptedDataDirFile;
98 private final File mCredentialEncryptedDataDirFile;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070099 private final ClassLoader mBaseClassLoader;
100 private final boolean mSecurityViolation;
101 private final boolean mIncludeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700102 private final boolean mRegisterPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700103 private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700104 Resources mResources;
105 private ClassLoader mClassLoader;
106 private Application mApplication;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700107
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700108 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
109 = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
110 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
111 = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
112 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
113 = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
114 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
115 = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700116
117 int mClientCount = 0;
118
119 Application getApplication() {
120 return mApplication;
121 }
122
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700123 /**
124 * Create information about a new .apk
125 *
126 * NOTE: This constructor is called with ActivityThread's lock held,
127 * so MUST NOT call back out to the activity manager.
128 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700129 public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
Jeff Browndefd4a62014-03-10 21:24:37 -0700130 CompatibilityInfo compatInfo, ClassLoader baseLoader,
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700131 boolean securityViolation, boolean includeCode, boolean registerPackage) {
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700132 final int myUid = Process.myUid();
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100133 aInfo = adjustNativeLibraryPaths(aInfo);
134
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700135 mActivityThread = activityThread;
136 mApplicationInfo = aInfo;
137 mPackageName = aInfo.packageName;
138 mAppDir = aInfo.sourceDir;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700139 mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
140 mSplitAppDirs = aInfo.splitSourceDirs;
141 mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100142 mOverlayDirs = aInfo.resourceDirs;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700143 mSharedLibraries = aInfo.sharedLibraryFiles;
144 mDataDir = aInfo.dataDir;
Jeff Sharkey15447792015-11-05 16:18:51 -0800145 mDataDirFile = FileUtils.newFileOrNull(mDataDir);
146 mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
147 mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
Kenny Root85387d72010-08-26 10:13:11 -0700148 mLibDir = aInfo.nativeLibraryDir;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700149 mBaseClassLoader = baseLoader;
150 mSecurityViolation = securityViolation;
151 mIncludeCode = includeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700152 mRegisterPackage = registerPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700153 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700154 }
155
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100156 private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) {
157 // If we're dealing with a multi-arch application that has both
158 // 32 and 64 bit shared libraries, we might need to choose the secondary
159 // depending on what the current runtime's instruction set is.
160 if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
161 final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
jgu214741cd92014-12-17 17:23:29 -0500162
163 // Get the instruction set that the libraries of secondary Abi is supported.
164 // In presence of a native bridge this might be different than the one secondary Abi used.
165 String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
166 final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
167 secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100168
169 // If the runtimeIsa is the same as the primary isa, then we do nothing.
170 // Everything will be set up correctly because info.nativeLibraryDir will
171 // correspond to the right ISA.
172 if (runtimeIsa.equals(secondaryIsa)) {
173 final ApplicationInfo modified = new ApplicationInfo(info);
174 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
Dmitriy Ivanove56b3f62015-06-05 22:00:13 -0700175 modified.primaryCpuAbi = modified.secondaryCpuAbi;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100176 return modified;
177 }
178 }
179
180 return info;
181 }
182
Jeff Browndefd4a62014-03-10 21:24:37 -0700183 /**
184 * Create information about the system package.
185 * Must call {@link #installSystemApplicationInfo} later.
186 */
187 LoadedApk(ActivityThread activityThread) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700188 mActivityThread = activityThread;
Jeff Browndefd4a62014-03-10 21:24:37 -0700189 mApplicationInfo = new ApplicationInfo();
190 mApplicationInfo.packageName = "android";
191 mPackageName = "android";
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700192 mAppDir = null;
193 mResDir = null;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700194 mSplitAppDirs = null;
195 mSplitResDirs = null;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100196 mOverlayDirs = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700197 mSharedLibraries = null;
198 mDataDir = null;
199 mDataDirFile = null;
Jeff Sharkey15447792015-11-05 16:18:51 -0800200 mDeviceEncryptedDataDirFile = null;
201 mCredentialEncryptedDataDirFile = null;
Kenny Root85387d72010-08-26 10:13:11 -0700202 mLibDir = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700203 mBaseClassLoader = null;
204 mSecurityViolation = false;
205 mIncludeCode = true;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700206 mRegisterPackage = false;
Jeff Browndefd4a62014-03-10 21:24:37 -0700207 mClassLoader = ClassLoader.getSystemClassLoader();
208 mResources = Resources.getSystem();
209 }
210
211 /**
212 * Sets application info about the system package.
213 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100214 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
Jeff Browndefd4a62014-03-10 21:24:37 -0700215 assert info.packageName.equals("android");
216 mApplicationInfo = info;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100217 mClassLoader = classLoader;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700218 }
219
220 public String getPackageName() {
221 return mPackageName;
222 }
223
224 public ApplicationInfo getApplicationInfo() {
225 return mApplicationInfo;
226 }
227
Jeff Sharkey369f5092016-02-29 11:16:21 -0700228 public int getTargetSdkVersion() {
229 return mApplicationInfo.targetSdkVersion;
230 }
231
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700232 public boolean isSecurityViolation() {
233 return mSecurityViolation;
234 }
235
Craig Mautner48d0d182013-06-11 07:53:06 -0700236 public CompatibilityInfo getCompatibilityInfo() {
237 return mDisplayAdjustments.getCompatibilityInfo();
238 }
239
240 public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
241 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
242 }
243
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700244 /**
245 * Gets the array of shared libraries that are listed as
246 * used by the given package.
247 *
248 * @param packageName the name of the package (note: not its
249 * file name)
250 * @return null-ok; the array of shared libraries, each one
251 * a fully-qualified path
252 */
253 private static String[] getLibrariesFor(String packageName) {
254 ApplicationInfo ai = null;
255 try {
256 ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700257 PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700258 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700259 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700260 }
261
262 if (ai == null) {
263 return null;
264 }
265
266 return ai.sharedLibraryFiles;
267 }
268
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700269 public ClassLoader getClassLoader() {
270 synchronized (this) {
271 if (mClassLoader != null) {
272 return mClassLoader;
273 }
274
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800275 if (mPackageName.equals("android")) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700276 if (mBaseClassLoader == null) {
277 mClassLoader = ClassLoader.getSystemClassLoader();
278 } else {
279 mClassLoader = mBaseClassLoader;
280 }
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800281 return mClassLoader;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700282 }
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800283
284 // Avoid the binder call when the package is the current application package.
285 // The activity manager will perform ensure that dexopt is performed before
286 // spinning up the process.
287 if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
288 final String isa = VMRuntime.getRuntime().vmInstructionSet();
289 try {
290 ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
291 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700292 throw re.rethrowFromSystemServer();
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800293 }
294 }
295
296 final List<String> zipPaths = new ArrayList<>();
297 final List<String> apkPaths = new ArrayList<>();
298 final List<String> libPaths = new ArrayList<>();
299
300 if (mRegisterPackage) {
301 try {
302 ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
303 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700304 throw e.rethrowFromSystemServer();
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800305 }
306 }
307
308 zipPaths.add(mAppDir);
309 if (mSplitAppDirs != null) {
310 Collections.addAll(zipPaths, mSplitAppDirs);
311 }
312
313 libPaths.add(mLibDir);
314
315 /*
316 * The following is a bit of a hack to inject
317 * instrumentation into the system: If the app
318 * being started matches one of the instrumentation names,
319 * then we combine both the "instrumentation" and
320 * "instrumented" app into the path, along with the
321 * concatenation of both apps' shared library lists.
322 */
323
324 String instrumentationPackageName = mActivityThread.mInstrumentationPackageName;
325 String instrumentationAppDir = mActivityThread.mInstrumentationAppDir;
326 String[] instrumentationSplitAppDirs = mActivityThread.mInstrumentationSplitAppDirs;
327 String instrumentationLibDir = mActivityThread.mInstrumentationLibDir;
328
329 String instrumentedAppDir = mActivityThread.mInstrumentedAppDir;
330 String[] instrumentedSplitAppDirs = mActivityThread.mInstrumentedSplitAppDirs;
331 String instrumentedLibDir = mActivityThread.mInstrumentedLibDir;
332 String[] instrumentationLibs = null;
333
334 if (mAppDir.equals(instrumentationAppDir)
335 || mAppDir.equals(instrumentedAppDir)) {
336 zipPaths.clear();
337 zipPaths.add(instrumentationAppDir);
338 if (instrumentationSplitAppDirs != null) {
339 Collections.addAll(zipPaths, instrumentationSplitAppDirs);
340 }
341 zipPaths.add(instrumentedAppDir);
342 if (instrumentedSplitAppDirs != null) {
343 Collections.addAll(zipPaths, instrumentedSplitAppDirs);
344 }
345
346 libPaths.clear();
347 libPaths.add(instrumentationLibDir);
348 libPaths.add(instrumentedLibDir);
349
350 if (!instrumentedAppDir.equals(instrumentationAppDir)) {
351 instrumentationLibs = getLibrariesFor(instrumentationPackageName);
352 }
353 }
354
355 apkPaths.addAll(zipPaths);
356
357 if (mSharedLibraries != null) {
358 for (String lib : mSharedLibraries) {
359 if (!zipPaths.contains(lib)) {
360 zipPaths.add(0, lib);
361 }
362 }
363 }
364
365 if (instrumentationLibs != null) {
366 for (String lib : instrumentationLibs) {
367 if (!zipPaths.contains(lib)) {
368 zipPaths.add(0, lib);
369 }
370 }
371 }
372
373 final String zip = mIncludeCode ? TextUtils.join(File.pathSeparator, zipPaths) : "";
374
375 // Add path to libraries in apk for current abi
376 if (mApplicationInfo.primaryCpuAbi != null) {
377 for (String apk : apkPaths) {
378 libPaths.add(apk + "!/lib/" + mApplicationInfo.primaryCpuAbi);
379 }
380 }
381
382 String libraryPermittedPath = mDataDir;
383 boolean isBundledApp = false;
384
Dimitry Ivanovb2b8c3c2016-02-29 15:40:40 -0800385 if (mApplicationInfo.isSystemApp() && !mApplicationInfo.isUpdatedSystemApp()) {
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800386 isBundledApp = true;
387 // Add path to system libraries to libPaths;
388 // Access to system libs should be limited
389 // to bundled applications; this is why updated
390 // system apps are not included.
391 libPaths.add(System.getProperty("java.library.path"));
392
393 // This is necessary to grant bundled apps access to
394 // libraries located in subdirectories of /system/lib
395 libraryPermittedPath += File.pathSeparator +
396 System.getProperty("java.library.path");
397 }
398 // DO NOT SHIP: this is a workaround for apps loading native libraries
399 // provided by 3rd party apps using absolute path instead of corresponding
400 // classloader; see http://b/26954419 for example.
401 if (mApplicationInfo.targetSdkVersion <= 23) {
402 libraryPermittedPath += File.pathSeparator + "/data/app";
403 }
404 // -----------------------------------------------------------------------------
405
406 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
407
408 /*
409 * With all the combination done (if necessary, actually
410 * create the class loader.
411 */
412
413 if (ActivityThread.localLOGV)
414 Slog.v(ActivityThread.TAG, "Class path: " + zip +
415 ", JNI path: " + librarySearchPath);
416
417 // Temporarily disable logging of disk reads on the Looper thread
418 // as this is early and necessary.
419 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
420
Dimitry Ivanova55c7f12016-02-23 14:25:50 -0800421 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
422 mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
423 libraryPermittedPath, mBaseClassLoader);
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800424
425 StrictMode.setThreadPolicy(oldPolicy);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700426 return mClassLoader;
427 }
428 }
429
430 /**
431 * Setup value for Thread.getContextClassLoader(). If the
432 * package will not run in in a VM with other packages, we set
433 * the Java context ClassLoader to the
434 * PackageInfo.getClassLoader value. However, if this VM can
435 * contain multiple packages, we intead set the Java context
436 * ClassLoader to a proxy that will warn about the use of Java
437 * context ClassLoaders and then fall through to use the
438 * system ClassLoader.
439 *
440 * <p> Note that this is similar to but not the same as the
441 * android.content.Context.getClassLoader(). While both
442 * context class loaders are typically set to the
443 * PathClassLoader used to load the package archive in the
444 * single application per VM case, a single Android process
445 * may contain several Contexts executing on one thread with
446 * their own logical ClassLoaders while the Java context
447 * ClassLoader is a thread local. This is why in the case when
448 * we have multiple packages per VM we do not set the Java
449 * context ClassLoader to an arbitrary but instead warn the
450 * user to set their own if we detect that they are using a
451 * Java library that expects it to be set.
452 */
453 private void initializeJavaContextClassLoader() {
454 IPackageManager pm = ActivityThread.getPackageManager();
455 android.content.pm.PackageInfo pi;
456 try {
Jeff Sharkeyc7bacab2016-02-09 15:56:11 -0700457 pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
458 UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700459 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700460 throw e.rethrowFromSystemServer();
Dianne Hackborn208d9372013-02-25 13:17:54 -0800461 }
462 if (pi == null) {
463 throw new IllegalStateException("Unable to get package info for "
464 + mPackageName + "; is package not installed?");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700465 }
466 /*
467 * Two possible indications that this package could be
468 * sharing its virtual machine with other packages:
469 *
470 * 1.) the sharedUserId attribute is set in the manifest,
471 * indicating a request to share a VM with other
472 * packages with the same sharedUserId.
473 *
474 * 2.) the application element of the manifest has an
475 * attribute specifying a non-default process name,
476 * indicating the desire to run in another packages VM.
477 */
478 boolean sharedUserIdSet = (pi.sharedUserId != null);
479 boolean processNameNotDefault =
480 (pi.applicationInfo != null &&
481 !mPackageName.equals(pi.applicationInfo.processName));
482 boolean sharable = (sharedUserIdSet || processNameNotDefault);
483 ClassLoader contextClassLoader =
484 (sharable)
485 ? new WarningContextClassLoader()
486 : mClassLoader;
487 Thread.currentThread().setContextClassLoader(contextClassLoader);
488 }
489
490 private static class WarningContextClassLoader extends ClassLoader {
491
492 private static boolean warned = false;
493
494 private void warn(String methodName) {
495 if (warned) {
496 return;
497 }
498 warned = true;
499 Thread.currentThread().setContextClassLoader(getParent());
500 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
501 "The class loader returned by " +
502 "Thread.getContextClassLoader() may fail for processes " +
503 "that host multiple applications. You should explicitly " +
504 "specify a context class loader. For example: " +
505 "Thread.setContextClassLoader(getClass().getClassLoader());");
506 }
507
508 @Override public URL getResource(String resName) {
509 warn("getResource");
510 return getParent().getResource(resName);
511 }
512
513 @Override public Enumeration<URL> getResources(String resName) throws IOException {
514 warn("getResources");
515 return getParent().getResources(resName);
516 }
517
518 @Override public InputStream getResourceAsStream(String resName) {
519 warn("getResourceAsStream");
520 return getParent().getResourceAsStream(resName);
521 }
522
523 @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
524 warn("loadClass");
525 return getParent().loadClass(className);
526 }
527
528 @Override public void setClassAssertionStatus(String cname, boolean enable) {
529 warn("setClassAssertionStatus");
530 getParent().setClassAssertionStatus(cname, enable);
531 }
532
533 @Override public void setPackageAssertionStatus(String pname, boolean enable) {
534 warn("setPackageAssertionStatus");
535 getParent().setPackageAssertionStatus(pname, enable);
536 }
537
538 @Override public void setDefaultAssertionStatus(boolean enable) {
539 warn("setDefaultAssertionStatus");
540 getParent().setDefaultAssertionStatus(enable);
541 }
542
543 @Override public void clearAssertionStatus() {
544 warn("clearAssertionStatus");
545 getParent().clearAssertionStatus();
546 }
547 }
548
549 public String getAppDir() {
550 return mAppDir;
551 }
552
Brian Carlstromd893a892012-04-01 21:30:26 -0700553 public String getLibDir() {
554 return mLibDir;
555 }
556
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700557 public String getResDir() {
558 return mResDir;
559 }
560
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700561 public String[] getSplitAppDirs() {
562 return mSplitAppDirs;
563 }
564
565 public String[] getSplitResDirs() {
566 return mSplitResDirs;
567 }
568
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100569 public String[] getOverlayDirs() {
570 return mOverlayDirs;
571 }
572
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700573 public String getDataDir() {
574 return mDataDir;
575 }
576
577 public File getDataDirFile() {
578 return mDataDirFile;
579 }
580
Jeff Sharkey15447792015-11-05 16:18:51 -0800581 public File getDeviceEncryptedDataDirFile() {
582 return mDeviceEncryptedDataDirFile;
583 }
584
585 public File getCredentialEncryptedDataDirFile() {
586 return mCredentialEncryptedDataDirFile;
587 }
588
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700589 public AssetManager getAssets(ActivityThread mainThread) {
590 return getResources(mainThread).getAssets();
591 }
592
593 public Resources getResources(ActivityThread mainThread) {
594 if (mResources == null) {
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700595 mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
Adam Lesinskide898ff2014-01-29 18:20:45 -0800596 mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700597 }
598 return mResources;
599 }
600
601 public Application makeApplication(boolean forceDefaultAppClass,
602 Instrumentation instrumentation) {
603 if (mApplication != null) {
604 return mApplication;
605 }
606
607 Application app = null;
608
609 String appClass = mApplicationInfo.className;
610 if (forceDefaultAppClass || (appClass == null)) {
611 appClass = "android.app.Application";
612 }
613
614 try {
615 java.lang.ClassLoader cl = getClassLoader();
Narayan Kamath8091edb2014-10-15 11:38:44 +0100616 if (!mPackageName.equals("android")) {
617 initializeJavaContextClassLoader();
618 }
Jeff Browndefd4a62014-03-10 21:24:37 -0700619 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700620 app = mActivityThread.mInstrumentation.newApplication(
621 cl, appClass, appContext);
622 appContext.setOuterContext(app);
623 } catch (Exception e) {
624 if (!mActivityThread.mInstrumentation.onException(app, e)) {
625 throw new RuntimeException(
626 "Unable to instantiate application " + appClass
627 + ": " + e.toString(), e);
628 }
629 }
630 mActivityThread.mAllApplications.add(app);
631 mApplication = app;
632
633 if (instrumentation != null) {
634 try {
635 instrumentation.callApplicationOnCreate(app);
636 } catch (Exception e) {
637 if (!instrumentation.onException(app, e)) {
638 throw new RuntimeException(
639 "Unable to create application " + app.getClass().getName()
640 + ": " + e.toString(), e);
641 }
642 }
643 }
Adam Lesinskide898ff2014-01-29 18:20:45 -0800644
645 // Rewrite the R 'constants' for all library apks.
646 SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
647 .getAssignedPackageIdentifiers();
648 final int N = packageIdentifiers.size();
649 for (int i = 0; i < N; i++) {
650 final int id = packageIdentifiers.keyAt(i);
651 if (id == 0x01 || id == 0x7f) {
652 continue;
653 }
654
655 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
656 }
657
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700658 return app;
659 }
660
Adam Lesinskide898ff2014-01-29 18:20:45 -0800661 private void rewriteRValues(ClassLoader cl, String packageName, int id) {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700662 final Class<?> rClazz;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800663 try {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700664 rClazz = cl.loadClass(packageName + ".R");
665 } catch (ClassNotFoundException e) {
666 // This is not necessarily an error, as some packages do not ship with resources
667 // (or they do not need rewriting).
Adam Lesinski1e4663852014-08-15 14:47:28 -0700668 Log.i(TAG, "No resource references to update in package " + packageName);
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700669 return;
670 }
671
Adam Lesinski1e4663852014-08-15 14:47:28 -0700672 final Method callback;
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700673 try {
Adam Lesinski1e4663852014-08-15 14:47:28 -0700674 callback = rClazz.getMethod("onResourcesLoaded", int.class);
675 } catch (NoSuchMethodException e) {
676 // No rewriting to be done.
677 return;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800678 }
Adam Lesinski1e4663852014-08-15 14:47:28 -0700679
680 Throwable cause;
681 try {
682 callback.invoke(null, id);
683 return;
684 } catch (IllegalAccessException e) {
685 cause = e;
686 } catch (InvocationTargetException e) {
687 cause = e.getCause();
688 }
689
690 throw new RuntimeException("Failed to rewrite resource references for " + packageName,
691 cause);
Adam Lesinskide898ff2014-01-29 18:20:45 -0800692 }
693
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700694 public void removeContextRegistrations(Context context,
695 String who, String what) {
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800696 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800697 synchronized (mReceivers) {
698 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
699 mReceivers.remove(context);
700 if (rmap != null) {
701 for (int i = 0; i < rmap.size(); i++) {
702 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
703 IntentReceiverLeaked leak = new IntentReceiverLeaked(
704 what + " " + who + " has leaked IntentReceiver "
705 + rd.getIntentReceiver() + " that was " +
706 "originally registered here. Are you missing a " +
707 "call to unregisterReceiver()?");
708 leak.setStackTrace(rd.getLocation().getStackTrace());
709 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
710 if (reportRegistrationLeaks) {
711 StrictMode.onIntentReceiverLeaked(leak);
712 }
713 try {
714 ActivityManagerNative.getDefault().unregisterReceiver(
715 rd.getIIntentReceiver());
716 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700717 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800718 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700719 }
720 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800721 mUnregisteredReceivers.remove(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700722 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800723
724 synchronized (mServices) {
725 //Slog.i(TAG, "Receiver registrations: " + mReceivers);
726 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
727 mServices.remove(context);
728 if (smap != null) {
729 for (int i = 0; i < smap.size(); i++) {
730 LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
731 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
732 what + " " + who + " has leaked ServiceConnection "
733 + sd.getServiceConnection() + " that was originally bound here");
734 leak.setStackTrace(sd.getLocation().getStackTrace());
735 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
736 if (reportRegistrationLeaks) {
737 StrictMode.onServiceConnectionLeaked(leak);
738 }
739 try {
740 ActivityManagerNative.getDefault().unbindService(
741 sd.getIServiceConnection());
742 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700743 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800744 }
745 sd.doForget();
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800746 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700747 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800748 mUnboundServices.remove(context);
749 //Slog.i(TAG, "Service registrations: " + mServices);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700750 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700751 }
752
753 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
754 Context context, Handler handler,
755 Instrumentation instrumentation, boolean registered) {
756 synchronized (mReceivers) {
757 LoadedApk.ReceiverDispatcher rd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700758 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700759 if (registered) {
760 map = mReceivers.get(context);
761 if (map != null) {
762 rd = map.get(r);
763 }
764 }
765 if (rd == null) {
766 rd = new ReceiverDispatcher(r, context, handler,
767 instrumentation, registered);
768 if (registered) {
769 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700770 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700771 mReceivers.put(context, map);
772 }
773 map.put(r, rd);
774 }
775 } else {
776 rd.validate(context, handler);
777 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800778 rd.mForgotten = false;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700779 return rd.getIIntentReceiver();
780 }
781 }
782
783 public IIntentReceiver forgetReceiverDispatcher(Context context,
784 BroadcastReceiver r) {
785 synchronized (mReceivers) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700786 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700787 LoadedApk.ReceiverDispatcher rd = null;
788 if (map != null) {
789 rd = map.get(r);
790 if (rd != null) {
791 map.remove(r);
792 if (map.size() == 0) {
793 mReceivers.remove(context);
794 }
795 if (r.getDebugUnregister()) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700796 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700797 = mUnregisteredReceivers.get(context);
798 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700799 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700800 mUnregisteredReceivers.put(context, holder);
801 }
802 RuntimeException ex = new IllegalArgumentException(
803 "Originally unregistered here:");
804 ex.fillInStackTrace();
805 rd.setUnregisterLocation(ex);
806 holder.put(r, rd);
807 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800808 rd.mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700809 return rd.getIIntentReceiver();
810 }
811 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700812 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700813 = mUnregisteredReceivers.get(context);
814 if (holder != null) {
815 rd = holder.get(r);
816 if (rd != null) {
817 RuntimeException ex = rd.getUnregisterLocation();
818 throw new IllegalArgumentException(
819 "Unregistering Receiver " + r
820 + " that was already unregistered", ex);
821 }
822 }
823 if (context == null) {
824 throw new IllegalStateException("Unbinding Receiver " + r
825 + " from Context that is no longer in use: " + context);
826 } else {
827 throw new IllegalArgumentException("Receiver not registered: " + r);
828 }
829
830 }
831 }
832
833 static final class ReceiverDispatcher {
834
835 final static class InnerReceiver extends IIntentReceiver.Stub {
836 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
837 final LoadedApk.ReceiverDispatcher mStrongRef;
838
839 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
840 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
841 mStrongRef = strong ? rd : null;
842 }
Dianne Hackborn20e80982012-08-31 19:00:44 -0700843 public void performReceive(Intent intent, int resultCode, String data,
844 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700845 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
846 if (ActivityThread.DEBUG_BROADCAST) {
847 int seq = intent.getIntExtra("seq", -1);
848 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
849 + " to " + (rd != null ? rd.mReceiver : null));
850 }
851 if (rd != null) {
852 rd.performReceive(intent, resultCode, data, extras,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700853 ordered, sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700854 } else {
855 // The activity manager dispatched a broadcast to a registered
856 // receiver in this process, but before it could be delivered the
857 // receiver was unregistered. Acknowledge the broadcast on its
858 // behalf so that the system's broadcast sequence can continue.
859 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
860 "Finishing broadcast to unregistered receiver");
861 IActivityManager mgr = ActivityManagerNative.getDefault();
862 try {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -0400863 if (extras != null) {
864 extras.setAllowFds(false);
865 }
riddle_hsu1f5ac4d2015-01-03 15:38:21 +0800866 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700867 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700868 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700869 }
870 }
871 }
872 }
873
874 final IIntentReceiver.Stub mIIntentReceiver;
875 final BroadcastReceiver mReceiver;
876 final Context mContext;
877 final Handler mActivityThread;
878 final Instrumentation mInstrumentation;
879 final boolean mRegistered;
880 final IntentReceiverLeaked mLocation;
881 RuntimeException mUnregisterLocation;
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800882 boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700883
Dianne Hackborne829fef2010-10-26 17:44:01 -0700884 final class Args extends BroadcastReceiver.PendingResult implements Runnable {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700885 private Intent mCurIntent;
Dianne Hackborne829fef2010-10-26 17:44:01 -0700886 private final boolean mOrdered;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700887
Dianne Hackborne829fef2010-10-26 17:44:01 -0700888 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700889 boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700890 super(resultCode, resultData, resultExtras,
riddle_hsu1f5ac4d2015-01-03 15:38:21 +0800891 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
892 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
Dianne Hackborne829fef2010-10-26 17:44:01 -0700893 mCurIntent = intent;
894 mOrdered = ordered;
895 }
896
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700897 public void run() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700898 final BroadcastReceiver receiver = mReceiver;
899 final boolean ordered = mOrdered;
900
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700901 if (ActivityThread.DEBUG_BROADCAST) {
902 int seq = mCurIntent.getIntExtra("seq", -1);
903 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
904 + " seq=" + seq + " to " + mReceiver);
905 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
Dianne Hackborne829fef2010-10-26 17:44:01 -0700906 + " mOrderedHint=" + ordered);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700907 }
908
Dianne Hackborne829fef2010-10-26 17:44:01 -0700909 final IActivityManager mgr = ActivityManagerNative.getDefault();
910 final Intent intent = mCurIntent;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700911 mCurIntent = null;
912
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800913 if (receiver == null || mForgotten) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700914 if (mRegistered && ordered) {
915 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
916 "Finishing null broadcast to " + mReceiver);
917 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700918 }
919 return;
920 }
921
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700922 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700923 try {
924 ClassLoader cl = mReceiver.getClass().getClassLoader();
925 intent.setExtrasClassLoader(cl);
Dianne Hackborne829fef2010-10-26 17:44:01 -0700926 setExtrasClassLoader(cl);
927 receiver.setPendingResult(this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700928 receiver.onReceive(mContext, intent);
929 } catch (Exception e) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700930 if (mRegistered && ordered) {
931 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
932 "Finishing failed broadcast to " + mReceiver);
933 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700934 }
935 if (mInstrumentation == null ||
936 !mInstrumentation.onException(mReceiver, e)) {
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700937 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700938 throw new RuntimeException(
939 "Error receiving broadcast " + intent
940 + " in " + mReceiver, e);
941 }
942 }
Dianne Hackborne829fef2010-10-26 17:44:01 -0700943
944 if (receiver.getPendingResult() != null) {
945 finish();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700946 }
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700947 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700948 }
949 }
950
951 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
952 Handler activityThread, Instrumentation instrumentation,
953 boolean registered) {
954 if (activityThread == null) {
955 throw new NullPointerException("Handler must not be null");
956 }
957
958 mIIntentReceiver = new InnerReceiver(this, !registered);
959 mReceiver = receiver;
960 mContext = context;
961 mActivityThread = activityThread;
962 mInstrumentation = instrumentation;
963 mRegistered = registered;
964 mLocation = new IntentReceiverLeaked(null);
965 mLocation.fillInStackTrace();
966 }
967
968 void validate(Context context, Handler activityThread) {
969 if (mContext != context) {
970 throw new IllegalStateException(
971 "Receiver " + mReceiver +
972 " registered with differing Context (was " +
973 mContext + " now " + context + ")");
974 }
975 if (mActivityThread != activityThread) {
976 throw new IllegalStateException(
977 "Receiver " + mReceiver +
978 " registered with differing handler (was " +
979 mActivityThread + " now " + activityThread + ")");
980 }
981 }
982
983 IntentReceiverLeaked getLocation() {
984 return mLocation;
985 }
986
987 BroadcastReceiver getIntentReceiver() {
988 return mReceiver;
989 }
990
991 IIntentReceiver getIIntentReceiver() {
992 return mIIntentReceiver;
993 }
994
995 void setUnregisterLocation(RuntimeException ex) {
996 mUnregisterLocation = ex;
997 }
998
999 RuntimeException getUnregisterLocation() {
1000 return mUnregisterLocation;
1001 }
1002
Dianne Hackborn20e80982012-08-31 19:00:44 -07001003 public void performReceive(Intent intent, int resultCode, String data,
1004 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001005 if (ActivityThread.DEBUG_BROADCAST) {
1006 int seq = intent.getIntExtra("seq", -1);
1007 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
1008 + " to " + mReceiver);
1009 }
Dianne Hackborn20e80982012-08-31 19:00:44 -07001010 Args args = new Args(intent, resultCode, data, extras, ordered,
1011 sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001012 if (!mActivityThread.post(args)) {
1013 if (mRegistered && ordered) {
1014 IActivityManager mgr = ActivityManagerNative.getDefault();
Dianne Hackborne829fef2010-10-26 17:44:01 -07001015 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1016 "Finishing sync broadcast to " + mReceiver);
1017 args.sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001018 }
1019 }
1020 }
1021
1022 }
1023
1024 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1025 Context context, Handler handler, int flags) {
1026 synchronized (mServices) {
1027 LoadedApk.ServiceDispatcher sd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001028 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001029 if (map != null) {
1030 sd = map.get(c);
1031 }
1032 if (sd == null) {
1033 sd = new ServiceDispatcher(c, context, handler, flags);
1034 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001035 map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001036 mServices.put(context, map);
1037 }
1038 map.put(c, sd);
1039 } else {
1040 sd.validate(context, handler);
1041 }
1042 return sd.getIServiceConnection();
1043 }
1044 }
1045
1046 public final IServiceConnection forgetServiceDispatcher(Context context,
1047 ServiceConnection c) {
1048 synchronized (mServices) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001049 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001050 = mServices.get(context);
1051 LoadedApk.ServiceDispatcher sd = null;
1052 if (map != null) {
1053 sd = map.get(c);
1054 if (sd != null) {
1055 map.remove(c);
1056 sd.doForget();
1057 if (map.size() == 0) {
1058 mServices.remove(context);
1059 }
1060 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001061 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001062 = mUnboundServices.get(context);
1063 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001064 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001065 mUnboundServices.put(context, holder);
1066 }
1067 RuntimeException ex = new IllegalArgumentException(
1068 "Originally unbound here:");
1069 ex.fillInStackTrace();
1070 sd.setUnbindLocation(ex);
1071 holder.put(c, sd);
1072 }
1073 return sd.getIServiceConnection();
1074 }
1075 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001076 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001077 = mUnboundServices.get(context);
1078 if (holder != null) {
1079 sd = holder.get(c);
1080 if (sd != null) {
1081 RuntimeException ex = sd.getUnbindLocation();
1082 throw new IllegalArgumentException(
1083 "Unbinding Service " + c
1084 + " that was already unbound", ex);
1085 }
1086 }
1087 if (context == null) {
1088 throw new IllegalStateException("Unbinding Service " + c
1089 + " from Context that is no longer in use: " + context);
1090 } else {
1091 throw new IllegalArgumentException("Service not registered: " + c);
1092 }
1093 }
1094 }
1095
1096 static final class ServiceDispatcher {
1097 private final ServiceDispatcher.InnerConnection mIServiceConnection;
1098 private final ServiceConnection mConnection;
1099 private final Context mContext;
1100 private final Handler mActivityThread;
1101 private final ServiceConnectionLeaked mLocation;
1102 private final int mFlags;
1103
1104 private RuntimeException mUnbindLocation;
1105
1106 private boolean mDied;
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001107 private boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001108
1109 private static class ConnectionInfo {
1110 IBinder binder;
1111 IBinder.DeathRecipient deathMonitor;
1112 }
1113
1114 private static class InnerConnection extends IServiceConnection.Stub {
1115 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1116
1117 InnerConnection(LoadedApk.ServiceDispatcher sd) {
1118 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1119 }
1120
1121 public void connected(ComponentName name, IBinder service) throws RemoteException {
1122 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1123 if (sd != null) {
1124 sd.connected(name, service);
1125 }
1126 }
1127 }
1128
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001129 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1130 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001131
1132 ServiceDispatcher(ServiceConnection conn,
1133 Context context, Handler activityThread, int flags) {
1134 mIServiceConnection = new InnerConnection(this);
1135 mConnection = conn;
1136 mContext = context;
1137 mActivityThread = activityThread;
1138 mLocation = new ServiceConnectionLeaked(null);
1139 mLocation.fillInStackTrace();
1140 mFlags = flags;
1141 }
1142
1143 void validate(Context context, Handler activityThread) {
1144 if (mContext != context) {
1145 throw new RuntimeException(
1146 "ServiceConnection " + mConnection +
1147 " registered with differing Context (was " +
1148 mContext + " now " + context + ")");
1149 }
1150 if (mActivityThread != activityThread) {
1151 throw new RuntimeException(
1152 "ServiceConnection " + mConnection +
1153 " registered with differing handler (was " +
1154 mActivityThread + " now " + activityThread + ")");
1155 }
1156 }
1157
1158 void doForget() {
1159 synchronized(this) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001160 for (int i=0; i<mActiveConnections.size(); i++) {
1161 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001162 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1163 }
1164 mActiveConnections.clear();
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001165 mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001166 }
1167 }
1168
1169 ServiceConnectionLeaked getLocation() {
1170 return mLocation;
1171 }
1172
1173 ServiceConnection getServiceConnection() {
1174 return mConnection;
1175 }
1176
1177 IServiceConnection getIServiceConnection() {
1178 return mIServiceConnection;
1179 }
1180
1181 int getFlags() {
1182 return mFlags;
1183 }
1184
1185 void setUnbindLocation(RuntimeException ex) {
1186 mUnbindLocation = ex;
1187 }
1188
1189 RuntimeException getUnbindLocation() {
1190 return mUnbindLocation;
1191 }
1192
1193 public void connected(ComponentName name, IBinder service) {
1194 if (mActivityThread != null) {
1195 mActivityThread.post(new RunConnection(name, service, 0));
1196 } else {
1197 doConnected(name, service);
1198 }
1199 }
1200
1201 public void death(ComponentName name, IBinder service) {
1202 ServiceDispatcher.ConnectionInfo old;
1203
1204 synchronized (this) {
1205 mDied = true;
1206 old = mActiveConnections.remove(name);
1207 if (old == null || old.binder != service) {
1208 // Death for someone different than who we last
1209 // reported... just ignore it.
1210 return;
1211 }
1212 old.binder.unlinkToDeath(old.deathMonitor, 0);
1213 }
1214
1215 if (mActivityThread != null) {
1216 mActivityThread.post(new RunConnection(name, service, 1));
1217 } else {
1218 doDeath(name, service);
1219 }
1220 }
1221
1222 public void doConnected(ComponentName name, IBinder service) {
1223 ServiceDispatcher.ConnectionInfo old;
1224 ServiceDispatcher.ConnectionInfo info;
1225
1226 synchronized (this) {
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001227 if (mForgotten) {
1228 // We unbound before receiving the connection; ignore
1229 // any connection received.
1230 return;
1231 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001232 old = mActiveConnections.get(name);
1233 if (old != null && old.binder == service) {
1234 // Huh, already have this one. Oh well!
1235 return;
1236 }
1237
1238 if (service != null) {
1239 // A new service is being connected... set it all up.
1240 mDied = false;
1241 info = new ConnectionInfo();
1242 info.binder = service;
1243 info.deathMonitor = new DeathMonitor(name, service);
1244 try {
1245 service.linkToDeath(info.deathMonitor, 0);
1246 mActiveConnections.put(name, info);
1247 } catch (RemoteException e) {
1248 // This service was dead before we got it... just
1249 // don't do anything with it.
1250 mActiveConnections.remove(name);
1251 return;
1252 }
1253
1254 } else {
1255 // The named service is being disconnected... clean up.
1256 mActiveConnections.remove(name);
1257 }
1258
1259 if (old != null) {
1260 old.binder.unlinkToDeath(old.deathMonitor, 0);
1261 }
1262 }
1263
1264 // If there was an old service, it is not disconnected.
1265 if (old != null) {
1266 mConnection.onServiceDisconnected(name);
1267 }
1268 // If there is a new service, it is now connected.
1269 if (service != null) {
1270 mConnection.onServiceConnected(name, service);
1271 }
1272 }
1273
1274 public void doDeath(ComponentName name, IBinder service) {
1275 mConnection.onServiceDisconnected(name);
1276 }
1277
1278 private final class RunConnection implements Runnable {
1279 RunConnection(ComponentName name, IBinder service, int command) {
1280 mName = name;
1281 mService = service;
1282 mCommand = command;
1283 }
1284
1285 public void run() {
1286 if (mCommand == 0) {
1287 doConnected(mName, mService);
1288 } else if (mCommand == 1) {
1289 doDeath(mName, mService);
1290 }
1291 }
1292
1293 final ComponentName mName;
1294 final IBinder mService;
1295 final int mCommand;
1296 }
1297
1298 private final class DeathMonitor implements IBinder.DeathRecipient
1299 {
1300 DeathMonitor(ComponentName name, IBinder service) {
1301 mName = name;
1302 mService = service;
1303 }
1304
1305 public void binderDied() {
1306 death(mName, mService);
1307 }
1308
1309 final ComponentName mName;
1310 final IBinder mService;
1311 }
1312 }
1313}