blob: 837ceb6cc252889d07476fa6eff26623c1fdfdee [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
228 public boolean isSecurityViolation() {
229 return mSecurityViolation;
230 }
231
Craig Mautner48d0d182013-06-11 07:53:06 -0700232 public CompatibilityInfo getCompatibilityInfo() {
233 return mDisplayAdjustments.getCompatibilityInfo();
234 }
235
236 public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
237 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
238 }
239
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700240 /**
241 * Gets the array of shared libraries that are listed as
242 * used by the given package.
243 *
244 * @param packageName the name of the package (note: not its
245 * file name)
246 * @return null-ok; the array of shared libraries, each one
247 * a fully-qualified path
248 */
249 private static String[] getLibrariesFor(String packageName) {
250 ApplicationInfo ai = null;
251 try {
252 ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700253 PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700254 } catch (RemoteException e) {
255 throw new AssertionError(e);
256 }
257
258 if (ai == null) {
259 return null;
260 }
261
262 return ai.sharedLibraryFiles;
263 }
264
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700265 public ClassLoader getClassLoader() {
266 synchronized (this) {
267 if (mClassLoader != null) {
268 return mClassLoader;
269 }
270
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800271 if (mPackageName.equals("android")) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700272 if (mBaseClassLoader == null) {
273 mClassLoader = ClassLoader.getSystemClassLoader();
274 } else {
275 mClassLoader = mBaseClassLoader;
276 }
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800277 return mClassLoader;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700278 }
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800279
280 // Avoid the binder call when the package is the current application package.
281 // The activity manager will perform ensure that dexopt is performed before
282 // spinning up the process.
283 if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
284 final String isa = VMRuntime.getRuntime().vmInstructionSet();
285 try {
286 ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
287 } catch (RemoteException re) {
288 // Ignored.
289 }
290 }
291
292 final List<String> zipPaths = new ArrayList<>();
293 final List<String> apkPaths = new ArrayList<>();
294 final List<String> libPaths = new ArrayList<>();
295
296 if (mRegisterPackage) {
297 try {
298 ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
299 } catch (RemoteException e) {
300 }
301 }
302
303 zipPaths.add(mAppDir);
304 if (mSplitAppDirs != null) {
305 Collections.addAll(zipPaths, mSplitAppDirs);
306 }
307
308 libPaths.add(mLibDir);
309
310 /*
311 * The following is a bit of a hack to inject
312 * instrumentation into the system: If the app
313 * being started matches one of the instrumentation names,
314 * then we combine both the "instrumentation" and
315 * "instrumented" app into the path, along with the
316 * concatenation of both apps' shared library lists.
317 */
318
319 String instrumentationPackageName = mActivityThread.mInstrumentationPackageName;
320 String instrumentationAppDir = mActivityThread.mInstrumentationAppDir;
321 String[] instrumentationSplitAppDirs = mActivityThread.mInstrumentationSplitAppDirs;
322 String instrumentationLibDir = mActivityThread.mInstrumentationLibDir;
323
324 String instrumentedAppDir = mActivityThread.mInstrumentedAppDir;
325 String[] instrumentedSplitAppDirs = mActivityThread.mInstrumentedSplitAppDirs;
326 String instrumentedLibDir = mActivityThread.mInstrumentedLibDir;
327 String[] instrumentationLibs = null;
328
329 if (mAppDir.equals(instrumentationAppDir)
330 || mAppDir.equals(instrumentedAppDir)) {
331 zipPaths.clear();
332 zipPaths.add(instrumentationAppDir);
333 if (instrumentationSplitAppDirs != null) {
334 Collections.addAll(zipPaths, instrumentationSplitAppDirs);
335 }
336 zipPaths.add(instrumentedAppDir);
337 if (instrumentedSplitAppDirs != null) {
338 Collections.addAll(zipPaths, instrumentedSplitAppDirs);
339 }
340
341 libPaths.clear();
342 libPaths.add(instrumentationLibDir);
343 libPaths.add(instrumentedLibDir);
344
345 if (!instrumentedAppDir.equals(instrumentationAppDir)) {
346 instrumentationLibs = getLibrariesFor(instrumentationPackageName);
347 }
348 }
349
350 apkPaths.addAll(zipPaths);
351
352 if (mSharedLibraries != null) {
353 for (String lib : mSharedLibraries) {
354 if (!zipPaths.contains(lib)) {
355 zipPaths.add(0, lib);
356 }
357 }
358 }
359
360 if (instrumentationLibs != null) {
361 for (String lib : instrumentationLibs) {
362 if (!zipPaths.contains(lib)) {
363 zipPaths.add(0, lib);
364 }
365 }
366 }
367
368 final String zip = mIncludeCode ? TextUtils.join(File.pathSeparator, zipPaths) : "";
369
370 // Add path to libraries in apk for current abi
371 if (mApplicationInfo.primaryCpuAbi != null) {
372 for (String apk : apkPaths) {
373 libPaths.add(apk + "!/lib/" + mApplicationInfo.primaryCpuAbi);
374 }
375 }
376
377 String libraryPermittedPath = mDataDir;
378 boolean isBundledApp = false;
379
380 if (mApplicationInfo.isSystemApp()) {
381 isBundledApp = true;
382 // Add path to system libraries to libPaths;
383 // Access to system libs should be limited
384 // to bundled applications; this is why updated
385 // system apps are not included.
386 libPaths.add(System.getProperty("java.library.path"));
387
388 // This is necessary to grant bundled apps access to
389 // libraries located in subdirectories of /system/lib
390 libraryPermittedPath += File.pathSeparator +
391 System.getProperty("java.library.path");
392 }
393 // DO NOT SHIP: this is a workaround for apps loading native libraries
394 // provided by 3rd party apps using absolute path instead of corresponding
395 // classloader; see http://b/26954419 for example.
396 if (mApplicationInfo.targetSdkVersion <= 23) {
397 libraryPermittedPath += File.pathSeparator + "/data/app";
398 }
399 // -----------------------------------------------------------------------------
400
401 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
402
403 /*
404 * With all the combination done (if necessary, actually
405 * create the class loader.
406 */
407
408 if (ActivityThread.localLOGV)
409 Slog.v(ActivityThread.TAG, "Class path: " + zip +
410 ", JNI path: " + librarySearchPath);
411
412 // Temporarily disable logging of disk reads on the Looper thread
413 // as this is early and necessary.
414 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
415
416 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, isBundledApp,
417 librarySearchPath, libraryPermittedPath, mBaseClassLoader);
418
419 StrictMode.setThreadPolicy(oldPolicy);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700420 return mClassLoader;
421 }
422 }
423
424 /**
425 * Setup value for Thread.getContextClassLoader(). If the
426 * package will not run in in a VM with other packages, we set
427 * the Java context ClassLoader to the
428 * PackageInfo.getClassLoader value. However, if this VM can
429 * contain multiple packages, we intead set the Java context
430 * ClassLoader to a proxy that will warn about the use of Java
431 * context ClassLoaders and then fall through to use the
432 * system ClassLoader.
433 *
434 * <p> Note that this is similar to but not the same as the
435 * android.content.Context.getClassLoader(). While both
436 * context class loaders are typically set to the
437 * PathClassLoader used to load the package archive in the
438 * single application per VM case, a single Android process
439 * may contain several Contexts executing on one thread with
440 * their own logical ClassLoaders while the Java context
441 * ClassLoader is a thread local. This is why in the case when
442 * we have multiple packages per VM we do not set the Java
443 * context ClassLoader to an arbitrary but instead warn the
444 * user to set their own if we detect that they are using a
445 * Java library that expects it to be set.
446 */
447 private void initializeJavaContextClassLoader() {
448 IPackageManager pm = ActivityThread.getPackageManager();
449 android.content.pm.PackageInfo pi;
450 try {
Jeff Sharkeyc7bacab2016-02-09 15:56:11 -0700451 pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
452 UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700453 } catch (RemoteException e) {
Dianne Hackborn208d9372013-02-25 13:17:54 -0800454 throw new IllegalStateException("Unable to get package info for "
455 + mPackageName + "; is system dying?", e);
456 }
457 if (pi == null) {
458 throw new IllegalStateException("Unable to get package info for "
459 + mPackageName + "; is package not installed?");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700460 }
461 /*
462 * Two possible indications that this package could be
463 * sharing its virtual machine with other packages:
464 *
465 * 1.) the sharedUserId attribute is set in the manifest,
466 * indicating a request to share a VM with other
467 * packages with the same sharedUserId.
468 *
469 * 2.) the application element of the manifest has an
470 * attribute specifying a non-default process name,
471 * indicating the desire to run in another packages VM.
472 */
473 boolean sharedUserIdSet = (pi.sharedUserId != null);
474 boolean processNameNotDefault =
475 (pi.applicationInfo != null &&
476 !mPackageName.equals(pi.applicationInfo.processName));
477 boolean sharable = (sharedUserIdSet || processNameNotDefault);
478 ClassLoader contextClassLoader =
479 (sharable)
480 ? new WarningContextClassLoader()
481 : mClassLoader;
482 Thread.currentThread().setContextClassLoader(contextClassLoader);
483 }
484
485 private static class WarningContextClassLoader extends ClassLoader {
486
487 private static boolean warned = false;
488
489 private void warn(String methodName) {
490 if (warned) {
491 return;
492 }
493 warned = true;
494 Thread.currentThread().setContextClassLoader(getParent());
495 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
496 "The class loader returned by " +
497 "Thread.getContextClassLoader() may fail for processes " +
498 "that host multiple applications. You should explicitly " +
499 "specify a context class loader. For example: " +
500 "Thread.setContextClassLoader(getClass().getClassLoader());");
501 }
502
503 @Override public URL getResource(String resName) {
504 warn("getResource");
505 return getParent().getResource(resName);
506 }
507
508 @Override public Enumeration<URL> getResources(String resName) throws IOException {
509 warn("getResources");
510 return getParent().getResources(resName);
511 }
512
513 @Override public InputStream getResourceAsStream(String resName) {
514 warn("getResourceAsStream");
515 return getParent().getResourceAsStream(resName);
516 }
517
518 @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
519 warn("loadClass");
520 return getParent().loadClass(className);
521 }
522
523 @Override public void setClassAssertionStatus(String cname, boolean enable) {
524 warn("setClassAssertionStatus");
525 getParent().setClassAssertionStatus(cname, enable);
526 }
527
528 @Override public void setPackageAssertionStatus(String pname, boolean enable) {
529 warn("setPackageAssertionStatus");
530 getParent().setPackageAssertionStatus(pname, enable);
531 }
532
533 @Override public void setDefaultAssertionStatus(boolean enable) {
534 warn("setDefaultAssertionStatus");
535 getParent().setDefaultAssertionStatus(enable);
536 }
537
538 @Override public void clearAssertionStatus() {
539 warn("clearAssertionStatus");
540 getParent().clearAssertionStatus();
541 }
542 }
543
544 public String getAppDir() {
545 return mAppDir;
546 }
547
Brian Carlstromd893a892012-04-01 21:30:26 -0700548 public String getLibDir() {
549 return mLibDir;
550 }
551
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700552 public String getResDir() {
553 return mResDir;
554 }
555
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700556 public String[] getSplitAppDirs() {
557 return mSplitAppDirs;
558 }
559
560 public String[] getSplitResDirs() {
561 return mSplitResDirs;
562 }
563
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100564 public String[] getOverlayDirs() {
565 return mOverlayDirs;
566 }
567
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700568 public String getDataDir() {
569 return mDataDir;
570 }
571
572 public File getDataDirFile() {
573 return mDataDirFile;
574 }
575
Jeff Sharkey15447792015-11-05 16:18:51 -0800576 public File getDeviceEncryptedDataDirFile() {
577 return mDeviceEncryptedDataDirFile;
578 }
579
580 public File getCredentialEncryptedDataDirFile() {
581 return mCredentialEncryptedDataDirFile;
582 }
583
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700584 public AssetManager getAssets(ActivityThread mainThread) {
585 return getResources(mainThread).getAssets();
586 }
587
588 public Resources getResources(ActivityThread mainThread) {
589 if (mResources == null) {
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700590 mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
Adam Lesinskide898ff2014-01-29 18:20:45 -0800591 mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700592 }
593 return mResources;
594 }
595
596 public Application makeApplication(boolean forceDefaultAppClass,
597 Instrumentation instrumentation) {
598 if (mApplication != null) {
599 return mApplication;
600 }
601
602 Application app = null;
603
604 String appClass = mApplicationInfo.className;
605 if (forceDefaultAppClass || (appClass == null)) {
606 appClass = "android.app.Application";
607 }
608
609 try {
610 java.lang.ClassLoader cl = getClassLoader();
Narayan Kamath8091edb2014-10-15 11:38:44 +0100611 if (!mPackageName.equals("android")) {
612 initializeJavaContextClassLoader();
613 }
Jeff Browndefd4a62014-03-10 21:24:37 -0700614 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700615 app = mActivityThread.mInstrumentation.newApplication(
616 cl, appClass, appContext);
617 appContext.setOuterContext(app);
618 } catch (Exception e) {
619 if (!mActivityThread.mInstrumentation.onException(app, e)) {
620 throw new RuntimeException(
621 "Unable to instantiate application " + appClass
622 + ": " + e.toString(), e);
623 }
624 }
625 mActivityThread.mAllApplications.add(app);
626 mApplication = app;
627
628 if (instrumentation != null) {
629 try {
630 instrumentation.callApplicationOnCreate(app);
631 } catch (Exception e) {
632 if (!instrumentation.onException(app, e)) {
633 throw new RuntimeException(
634 "Unable to create application " + app.getClass().getName()
635 + ": " + e.toString(), e);
636 }
637 }
638 }
Adam Lesinskide898ff2014-01-29 18:20:45 -0800639
640 // Rewrite the R 'constants' for all library apks.
641 SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
642 .getAssignedPackageIdentifiers();
643 final int N = packageIdentifiers.size();
644 for (int i = 0; i < N; i++) {
645 final int id = packageIdentifiers.keyAt(i);
646 if (id == 0x01 || id == 0x7f) {
647 continue;
648 }
649
650 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
651 }
652
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700653 return app;
654 }
655
Adam Lesinskide898ff2014-01-29 18:20:45 -0800656 private void rewriteRValues(ClassLoader cl, String packageName, int id) {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700657 final Class<?> rClazz;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800658 try {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700659 rClazz = cl.loadClass(packageName + ".R");
660 } catch (ClassNotFoundException e) {
661 // This is not necessarily an error, as some packages do not ship with resources
662 // (or they do not need rewriting).
Adam Lesinski1e4663852014-08-15 14:47:28 -0700663 Log.i(TAG, "No resource references to update in package " + packageName);
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700664 return;
665 }
666
Adam Lesinski1e4663852014-08-15 14:47:28 -0700667 final Method callback;
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700668 try {
Adam Lesinski1e4663852014-08-15 14:47:28 -0700669 callback = rClazz.getMethod("onResourcesLoaded", int.class);
670 } catch (NoSuchMethodException e) {
671 // No rewriting to be done.
672 return;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800673 }
Adam Lesinski1e4663852014-08-15 14:47:28 -0700674
675 Throwable cause;
676 try {
677 callback.invoke(null, id);
678 return;
679 } catch (IllegalAccessException e) {
680 cause = e;
681 } catch (InvocationTargetException e) {
682 cause = e.getCause();
683 }
684
685 throw new RuntimeException("Failed to rewrite resource references for " + packageName,
686 cause);
Adam Lesinskide898ff2014-01-29 18:20:45 -0800687 }
688
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700689 public void removeContextRegistrations(Context context,
690 String who, String what) {
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800691 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800692 synchronized (mReceivers) {
693 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
694 mReceivers.remove(context);
695 if (rmap != null) {
696 for (int i = 0; i < rmap.size(); i++) {
697 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
698 IntentReceiverLeaked leak = new IntentReceiverLeaked(
699 what + " " + who + " has leaked IntentReceiver "
700 + rd.getIntentReceiver() + " that was " +
701 "originally registered here. Are you missing a " +
702 "call to unregisterReceiver()?");
703 leak.setStackTrace(rd.getLocation().getStackTrace());
704 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
705 if (reportRegistrationLeaks) {
706 StrictMode.onIntentReceiverLeaked(leak);
707 }
708 try {
709 ActivityManagerNative.getDefault().unregisterReceiver(
710 rd.getIIntentReceiver());
711 } catch (RemoteException e) {
712 // system crashed, nothing we can do
713 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700714 }
715 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800716 mUnregisteredReceivers.remove(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700717 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800718
719 synchronized (mServices) {
720 //Slog.i(TAG, "Receiver registrations: " + mReceivers);
721 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
722 mServices.remove(context);
723 if (smap != null) {
724 for (int i = 0; i < smap.size(); i++) {
725 LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
726 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
727 what + " " + who + " has leaked ServiceConnection "
728 + sd.getServiceConnection() + " that was originally bound here");
729 leak.setStackTrace(sd.getLocation().getStackTrace());
730 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
731 if (reportRegistrationLeaks) {
732 StrictMode.onServiceConnectionLeaked(leak);
733 }
734 try {
735 ActivityManagerNative.getDefault().unbindService(
736 sd.getIServiceConnection());
737 } catch (RemoteException e) {
738 // system crashed, nothing we can do
739 }
740 sd.doForget();
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800741 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700742 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800743 mUnboundServices.remove(context);
744 //Slog.i(TAG, "Service registrations: " + mServices);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700745 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700746 }
747
748 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
749 Context context, Handler handler,
750 Instrumentation instrumentation, boolean registered) {
751 synchronized (mReceivers) {
752 LoadedApk.ReceiverDispatcher rd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700753 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700754 if (registered) {
755 map = mReceivers.get(context);
756 if (map != null) {
757 rd = map.get(r);
758 }
759 }
760 if (rd == null) {
761 rd = new ReceiverDispatcher(r, context, handler,
762 instrumentation, registered);
763 if (registered) {
764 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700765 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700766 mReceivers.put(context, map);
767 }
768 map.put(r, rd);
769 }
770 } else {
771 rd.validate(context, handler);
772 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800773 rd.mForgotten = false;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700774 return rd.getIIntentReceiver();
775 }
776 }
777
778 public IIntentReceiver forgetReceiverDispatcher(Context context,
779 BroadcastReceiver r) {
780 synchronized (mReceivers) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700781 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700782 LoadedApk.ReceiverDispatcher rd = null;
783 if (map != null) {
784 rd = map.get(r);
785 if (rd != null) {
786 map.remove(r);
787 if (map.size() == 0) {
788 mReceivers.remove(context);
789 }
790 if (r.getDebugUnregister()) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700791 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700792 = mUnregisteredReceivers.get(context);
793 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700794 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700795 mUnregisteredReceivers.put(context, holder);
796 }
797 RuntimeException ex = new IllegalArgumentException(
798 "Originally unregistered here:");
799 ex.fillInStackTrace();
800 rd.setUnregisterLocation(ex);
801 holder.put(r, rd);
802 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800803 rd.mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700804 return rd.getIIntentReceiver();
805 }
806 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700807 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700808 = mUnregisteredReceivers.get(context);
809 if (holder != null) {
810 rd = holder.get(r);
811 if (rd != null) {
812 RuntimeException ex = rd.getUnregisterLocation();
813 throw new IllegalArgumentException(
814 "Unregistering Receiver " + r
815 + " that was already unregistered", ex);
816 }
817 }
818 if (context == null) {
819 throw new IllegalStateException("Unbinding Receiver " + r
820 + " from Context that is no longer in use: " + context);
821 } else {
822 throw new IllegalArgumentException("Receiver not registered: " + r);
823 }
824
825 }
826 }
827
828 static final class ReceiverDispatcher {
829
830 final static class InnerReceiver extends IIntentReceiver.Stub {
831 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
832 final LoadedApk.ReceiverDispatcher mStrongRef;
833
834 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
835 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
836 mStrongRef = strong ? rd : null;
837 }
Dianne Hackborn20e80982012-08-31 19:00:44 -0700838 public void performReceive(Intent intent, int resultCode, String data,
839 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700840 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
841 if (ActivityThread.DEBUG_BROADCAST) {
842 int seq = intent.getIntExtra("seq", -1);
843 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
844 + " to " + (rd != null ? rd.mReceiver : null));
845 }
846 if (rd != null) {
847 rd.performReceive(intent, resultCode, data, extras,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700848 ordered, sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700849 } else {
850 // The activity manager dispatched a broadcast to a registered
851 // receiver in this process, but before it could be delivered the
852 // receiver was unregistered. Acknowledge the broadcast on its
853 // behalf so that the system's broadcast sequence can continue.
854 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
855 "Finishing broadcast to unregistered receiver");
856 IActivityManager mgr = ActivityManagerNative.getDefault();
857 try {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -0400858 if (extras != null) {
859 extras.setAllowFds(false);
860 }
riddle_hsu1f5ac4d2015-01-03 15:38:21 +0800861 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700862 } catch (RemoteException e) {
863 Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
864 }
865 }
866 }
867 }
868
869 final IIntentReceiver.Stub mIIntentReceiver;
870 final BroadcastReceiver mReceiver;
871 final Context mContext;
872 final Handler mActivityThread;
873 final Instrumentation mInstrumentation;
874 final boolean mRegistered;
875 final IntentReceiverLeaked mLocation;
876 RuntimeException mUnregisterLocation;
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800877 boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700878
Dianne Hackborne829fef2010-10-26 17:44:01 -0700879 final class Args extends BroadcastReceiver.PendingResult implements Runnable {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700880 private Intent mCurIntent;
Dianne Hackborne829fef2010-10-26 17:44:01 -0700881 private final boolean mOrdered;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700882
Dianne Hackborne829fef2010-10-26 17:44:01 -0700883 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700884 boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700885 super(resultCode, resultData, resultExtras,
riddle_hsu1f5ac4d2015-01-03 15:38:21 +0800886 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
887 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
Dianne Hackborne829fef2010-10-26 17:44:01 -0700888 mCurIntent = intent;
889 mOrdered = ordered;
890 }
891
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700892 public void run() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700893 final BroadcastReceiver receiver = mReceiver;
894 final boolean ordered = mOrdered;
895
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700896 if (ActivityThread.DEBUG_BROADCAST) {
897 int seq = mCurIntent.getIntExtra("seq", -1);
898 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
899 + " seq=" + seq + " to " + mReceiver);
900 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
Dianne Hackborne829fef2010-10-26 17:44:01 -0700901 + " mOrderedHint=" + ordered);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700902 }
903
Dianne Hackborne829fef2010-10-26 17:44:01 -0700904 final IActivityManager mgr = ActivityManagerNative.getDefault();
905 final Intent intent = mCurIntent;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700906 mCurIntent = null;
907
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800908 if (receiver == null || mForgotten) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700909 if (mRegistered && ordered) {
910 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
911 "Finishing null broadcast to " + mReceiver);
912 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700913 }
914 return;
915 }
916
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700917 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700918 try {
919 ClassLoader cl = mReceiver.getClass().getClassLoader();
920 intent.setExtrasClassLoader(cl);
Dianne Hackborne829fef2010-10-26 17:44:01 -0700921 setExtrasClassLoader(cl);
922 receiver.setPendingResult(this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700923 receiver.onReceive(mContext, intent);
924 } catch (Exception e) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700925 if (mRegistered && ordered) {
926 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
927 "Finishing failed broadcast to " + mReceiver);
928 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700929 }
930 if (mInstrumentation == null ||
931 !mInstrumentation.onException(mReceiver, e)) {
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700932 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700933 throw new RuntimeException(
934 "Error receiving broadcast " + intent
935 + " in " + mReceiver, e);
936 }
937 }
Dianne Hackborne829fef2010-10-26 17:44:01 -0700938
939 if (receiver.getPendingResult() != null) {
940 finish();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700941 }
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700942 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700943 }
944 }
945
946 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
947 Handler activityThread, Instrumentation instrumentation,
948 boolean registered) {
949 if (activityThread == null) {
950 throw new NullPointerException("Handler must not be null");
951 }
952
953 mIIntentReceiver = new InnerReceiver(this, !registered);
954 mReceiver = receiver;
955 mContext = context;
956 mActivityThread = activityThread;
957 mInstrumentation = instrumentation;
958 mRegistered = registered;
959 mLocation = new IntentReceiverLeaked(null);
960 mLocation.fillInStackTrace();
961 }
962
963 void validate(Context context, Handler activityThread) {
964 if (mContext != context) {
965 throw new IllegalStateException(
966 "Receiver " + mReceiver +
967 " registered with differing Context (was " +
968 mContext + " now " + context + ")");
969 }
970 if (mActivityThread != activityThread) {
971 throw new IllegalStateException(
972 "Receiver " + mReceiver +
973 " registered with differing handler (was " +
974 mActivityThread + " now " + activityThread + ")");
975 }
976 }
977
978 IntentReceiverLeaked getLocation() {
979 return mLocation;
980 }
981
982 BroadcastReceiver getIntentReceiver() {
983 return mReceiver;
984 }
985
986 IIntentReceiver getIIntentReceiver() {
987 return mIIntentReceiver;
988 }
989
990 void setUnregisterLocation(RuntimeException ex) {
991 mUnregisterLocation = ex;
992 }
993
994 RuntimeException getUnregisterLocation() {
995 return mUnregisterLocation;
996 }
997
Dianne Hackborn20e80982012-08-31 19:00:44 -0700998 public void performReceive(Intent intent, int resultCode, String data,
999 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001000 if (ActivityThread.DEBUG_BROADCAST) {
1001 int seq = intent.getIntExtra("seq", -1);
1002 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
1003 + " to " + mReceiver);
1004 }
Dianne Hackborn20e80982012-08-31 19:00:44 -07001005 Args args = new Args(intent, resultCode, data, extras, ordered,
1006 sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001007 if (!mActivityThread.post(args)) {
1008 if (mRegistered && ordered) {
1009 IActivityManager mgr = ActivityManagerNative.getDefault();
Dianne Hackborne829fef2010-10-26 17:44:01 -07001010 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1011 "Finishing sync broadcast to " + mReceiver);
1012 args.sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001013 }
1014 }
1015 }
1016
1017 }
1018
1019 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1020 Context context, Handler handler, int flags) {
1021 synchronized (mServices) {
1022 LoadedApk.ServiceDispatcher sd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001023 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001024 if (map != null) {
1025 sd = map.get(c);
1026 }
1027 if (sd == null) {
1028 sd = new ServiceDispatcher(c, context, handler, flags);
1029 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001030 map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001031 mServices.put(context, map);
1032 }
1033 map.put(c, sd);
1034 } else {
1035 sd.validate(context, handler);
1036 }
1037 return sd.getIServiceConnection();
1038 }
1039 }
1040
1041 public final IServiceConnection forgetServiceDispatcher(Context context,
1042 ServiceConnection c) {
1043 synchronized (mServices) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001044 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001045 = mServices.get(context);
1046 LoadedApk.ServiceDispatcher sd = null;
1047 if (map != null) {
1048 sd = map.get(c);
1049 if (sd != null) {
1050 map.remove(c);
1051 sd.doForget();
1052 if (map.size() == 0) {
1053 mServices.remove(context);
1054 }
1055 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001056 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001057 = mUnboundServices.get(context);
1058 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001059 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001060 mUnboundServices.put(context, holder);
1061 }
1062 RuntimeException ex = new IllegalArgumentException(
1063 "Originally unbound here:");
1064 ex.fillInStackTrace();
1065 sd.setUnbindLocation(ex);
1066 holder.put(c, sd);
1067 }
1068 return sd.getIServiceConnection();
1069 }
1070 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001071 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001072 = mUnboundServices.get(context);
1073 if (holder != null) {
1074 sd = holder.get(c);
1075 if (sd != null) {
1076 RuntimeException ex = sd.getUnbindLocation();
1077 throw new IllegalArgumentException(
1078 "Unbinding Service " + c
1079 + " that was already unbound", ex);
1080 }
1081 }
1082 if (context == null) {
1083 throw new IllegalStateException("Unbinding Service " + c
1084 + " from Context that is no longer in use: " + context);
1085 } else {
1086 throw new IllegalArgumentException("Service not registered: " + c);
1087 }
1088 }
1089 }
1090
1091 static final class ServiceDispatcher {
1092 private final ServiceDispatcher.InnerConnection mIServiceConnection;
1093 private final ServiceConnection mConnection;
1094 private final Context mContext;
1095 private final Handler mActivityThread;
1096 private final ServiceConnectionLeaked mLocation;
1097 private final int mFlags;
1098
1099 private RuntimeException mUnbindLocation;
1100
1101 private boolean mDied;
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001102 private boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001103
1104 private static class ConnectionInfo {
1105 IBinder binder;
1106 IBinder.DeathRecipient deathMonitor;
1107 }
1108
1109 private static class InnerConnection extends IServiceConnection.Stub {
1110 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1111
1112 InnerConnection(LoadedApk.ServiceDispatcher sd) {
1113 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1114 }
1115
1116 public void connected(ComponentName name, IBinder service) throws RemoteException {
1117 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1118 if (sd != null) {
1119 sd.connected(name, service);
1120 }
1121 }
1122 }
1123
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001124 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1125 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001126
1127 ServiceDispatcher(ServiceConnection conn,
1128 Context context, Handler activityThread, int flags) {
1129 mIServiceConnection = new InnerConnection(this);
1130 mConnection = conn;
1131 mContext = context;
1132 mActivityThread = activityThread;
1133 mLocation = new ServiceConnectionLeaked(null);
1134 mLocation.fillInStackTrace();
1135 mFlags = flags;
1136 }
1137
1138 void validate(Context context, Handler activityThread) {
1139 if (mContext != context) {
1140 throw new RuntimeException(
1141 "ServiceConnection " + mConnection +
1142 " registered with differing Context (was " +
1143 mContext + " now " + context + ")");
1144 }
1145 if (mActivityThread != activityThread) {
1146 throw new RuntimeException(
1147 "ServiceConnection " + mConnection +
1148 " registered with differing handler (was " +
1149 mActivityThread + " now " + activityThread + ")");
1150 }
1151 }
1152
1153 void doForget() {
1154 synchronized(this) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001155 for (int i=0; i<mActiveConnections.size(); i++) {
1156 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001157 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1158 }
1159 mActiveConnections.clear();
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001160 mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001161 }
1162 }
1163
1164 ServiceConnectionLeaked getLocation() {
1165 return mLocation;
1166 }
1167
1168 ServiceConnection getServiceConnection() {
1169 return mConnection;
1170 }
1171
1172 IServiceConnection getIServiceConnection() {
1173 return mIServiceConnection;
1174 }
1175
1176 int getFlags() {
1177 return mFlags;
1178 }
1179
1180 void setUnbindLocation(RuntimeException ex) {
1181 mUnbindLocation = ex;
1182 }
1183
1184 RuntimeException getUnbindLocation() {
1185 return mUnbindLocation;
1186 }
1187
1188 public void connected(ComponentName name, IBinder service) {
1189 if (mActivityThread != null) {
1190 mActivityThread.post(new RunConnection(name, service, 0));
1191 } else {
1192 doConnected(name, service);
1193 }
1194 }
1195
1196 public void death(ComponentName name, IBinder service) {
1197 ServiceDispatcher.ConnectionInfo old;
1198
1199 synchronized (this) {
1200 mDied = true;
1201 old = mActiveConnections.remove(name);
1202 if (old == null || old.binder != service) {
1203 // Death for someone different than who we last
1204 // reported... just ignore it.
1205 return;
1206 }
1207 old.binder.unlinkToDeath(old.deathMonitor, 0);
1208 }
1209
1210 if (mActivityThread != null) {
1211 mActivityThread.post(new RunConnection(name, service, 1));
1212 } else {
1213 doDeath(name, service);
1214 }
1215 }
1216
1217 public void doConnected(ComponentName name, IBinder service) {
1218 ServiceDispatcher.ConnectionInfo old;
1219 ServiceDispatcher.ConnectionInfo info;
1220
1221 synchronized (this) {
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001222 if (mForgotten) {
1223 // We unbound before receiving the connection; ignore
1224 // any connection received.
1225 return;
1226 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001227 old = mActiveConnections.get(name);
1228 if (old != null && old.binder == service) {
1229 // Huh, already have this one. Oh well!
1230 return;
1231 }
1232
1233 if (service != null) {
1234 // A new service is being connected... set it all up.
1235 mDied = false;
1236 info = new ConnectionInfo();
1237 info.binder = service;
1238 info.deathMonitor = new DeathMonitor(name, service);
1239 try {
1240 service.linkToDeath(info.deathMonitor, 0);
1241 mActiveConnections.put(name, info);
1242 } catch (RemoteException e) {
1243 // This service was dead before we got it... just
1244 // don't do anything with it.
1245 mActiveConnections.remove(name);
1246 return;
1247 }
1248
1249 } else {
1250 // The named service is being disconnected... clean up.
1251 mActiveConnections.remove(name);
1252 }
1253
1254 if (old != null) {
1255 old.binder.unlinkToDeath(old.deathMonitor, 0);
1256 }
1257 }
1258
1259 // If there was an old service, it is not disconnected.
1260 if (old != null) {
1261 mConnection.onServiceDisconnected(name);
1262 }
1263 // If there is a new service, it is now connected.
1264 if (service != null) {
1265 mConnection.onServiceConnected(name, service);
1266 }
1267 }
1268
1269 public void doDeath(ComponentName name, IBinder service) {
1270 mConnection.onServiceDisconnected(name);
1271 }
1272
1273 private final class RunConnection implements Runnable {
1274 RunConnection(ComponentName name, IBinder service, int command) {
1275 mName = name;
1276 mService = service;
1277 mCommand = command;
1278 }
1279
1280 public void run() {
1281 if (mCommand == 0) {
1282 doConnected(mName, mService);
1283 } else if (mCommand == 1) {
1284 doDeath(mName, mService);
1285 }
1286 }
1287
1288 final ComponentName mName;
1289 final IBinder mService;
1290 final int mCommand;
1291 }
1292
1293 private final class DeathMonitor implements IBinder.DeathRecipient
1294 {
1295 DeathMonitor(ComponentName name, IBinder service) {
1296 mName = name;
1297 mService = service;
1298 }
1299
1300 public void binderDied() {
1301 death(mName, mService);
1302 }
1303
1304 final ComponentName mName;
1305 final IBinder mService;
1306 }
1307 }
1308}