blob: d143b8634531a555dd2cd6cc19cfd16f1032c148 [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 -070021
22import android.content.BroadcastReceiver;
23import android.content.ComponentName;
24import android.content.Context;
25import android.content.IIntentReceiver;
26import android.content.Intent;
27import android.content.ServiceConnection;
28import android.content.pm.ApplicationInfo;
29import android.content.pm.IPackageManager;
30import android.content.pm.PackageManager;
31import android.content.res.AssetManager;
32import android.content.res.CompatibilityInfo;
33import android.content.res.Resources;
34import android.os.Bundle;
35import 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;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +010048import dalvik.system.VMRuntime;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070049
50import java.io.File;
51import java.io.IOException;
52import java.io.InputStream;
53import java.lang.ref.WeakReference;
Adam Lesinski1e4663852014-08-15 14:47:28 -070054import java.lang.reflect.InvocationTargetException;
55import java.lang.reflect.Method;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070056import java.net.URL;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070057import java.util.ArrayList;
58import java.util.Collections;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070059import java.util.Enumeration;
Narayan Kamath20531682014-07-14 13:18:43 +010060import java.util.Objects;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070061
62final class IntentReceiverLeaked extends AndroidRuntimeException {
63 public IntentReceiverLeaked(String msg) {
64 super(msg);
65 }
66}
67
68final class ServiceConnectionLeaked extends AndroidRuntimeException {
69 public ServiceConnectionLeaked(String msg) {
70 super(msg);
71 }
72}
73
74/**
75 * Local state maintained about a currently loaded .apk.
76 * @hide
77 */
Dianne Hackborn5fd21692011-06-07 14:09:47 -070078public final class LoadedApk {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070079
Amith Yamasani742a6712011-05-04 14:49:28 -070080 private static final String TAG = "LoadedApk";
81
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070082 private final ActivityThread mActivityThread;
Jeff Browndefd4a62014-03-10 21:24:37 -070083 private ApplicationInfo mApplicationInfo;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070084 final String mPackageName;
85 private final String mAppDir;
86 private final String mResDir;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070087 private final String[] mSplitAppDirs;
88 private final String[] mSplitResDirs;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +010089 private final String[] mOverlayDirs;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070090 private final String[] mSharedLibraries;
91 private final String mDataDir;
Kenny Root85387d72010-08-26 10:13:11 -070092 private final String mLibDir;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070093 private final File mDataDirFile;
94 private final ClassLoader mBaseClassLoader;
95 private final boolean mSecurityViolation;
96 private final boolean mIncludeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -070097 private final boolean mRegisterPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -070098 private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070099 Resources mResources;
100 private ClassLoader mClassLoader;
101 private Application mApplication;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700102
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700103 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
104 = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
105 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
106 = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
107 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
108 = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
109 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
110 = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700111
112 int mClientCount = 0;
113
114 Application getApplication() {
115 return mApplication;
116 }
117
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700118 /**
119 * Create information about a new .apk
120 *
121 * NOTE: This constructor is called with ActivityThread's lock held,
122 * so MUST NOT call back out to the activity manager.
123 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700124 public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
Jeff Browndefd4a62014-03-10 21:24:37 -0700125 CompatibilityInfo compatInfo, ClassLoader baseLoader,
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700126 boolean securityViolation, boolean includeCode, boolean registerPackage) {
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700127 final int myUid = Process.myUid();
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100128 aInfo = adjustNativeLibraryPaths(aInfo);
129
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700130 mActivityThread = activityThread;
131 mApplicationInfo = aInfo;
132 mPackageName = aInfo.packageName;
133 mAppDir = aInfo.sourceDir;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700134 mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
135 mSplitAppDirs = aInfo.splitSourceDirs;
136 mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100137 mOverlayDirs = aInfo.resourceDirs;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700138 if (!UserHandle.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) {
139 aInfo.dataDir = PackageManager.getDataDirForUser(UserHandle.getUserId(myUid),
Amith Yamasani742a6712011-05-04 14:49:28 -0700140 mPackageName);
141 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700142 mSharedLibraries = aInfo.sharedLibraryFiles;
143 mDataDir = aInfo.dataDir;
144 mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
Kenny Root85387d72010-08-26 10:13:11 -0700145 mLibDir = aInfo.nativeLibraryDir;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700146 mBaseClassLoader = baseLoader;
147 mSecurityViolation = securityViolation;
148 mIncludeCode = includeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700149 mRegisterPackage = registerPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700150 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700151 }
152
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100153 private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) {
154 // If we're dealing with a multi-arch application that has both
155 // 32 and 64 bit shared libraries, we might need to choose the secondary
156 // depending on what the current runtime's instruction set is.
157 if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
158 final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
159 final String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
160
161 // If the runtimeIsa is the same as the primary isa, then we do nothing.
162 // Everything will be set up correctly because info.nativeLibraryDir will
163 // correspond to the right ISA.
164 if (runtimeIsa.equals(secondaryIsa)) {
165 final ApplicationInfo modified = new ApplicationInfo(info);
166 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
167 return modified;
168 }
169 }
170
171 return info;
172 }
173
Jeff Browndefd4a62014-03-10 21:24:37 -0700174 /**
175 * Create information about the system package.
176 * Must call {@link #installSystemApplicationInfo} later.
177 */
178 LoadedApk(ActivityThread activityThread) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700179 mActivityThread = activityThread;
Jeff Browndefd4a62014-03-10 21:24:37 -0700180 mApplicationInfo = new ApplicationInfo();
181 mApplicationInfo.packageName = "android";
182 mPackageName = "android";
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700183 mAppDir = null;
184 mResDir = null;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700185 mSplitAppDirs = null;
186 mSplitResDirs = null;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100187 mOverlayDirs = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700188 mSharedLibraries = null;
189 mDataDir = null;
190 mDataDirFile = null;
Kenny Root85387d72010-08-26 10:13:11 -0700191 mLibDir = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700192 mBaseClassLoader = null;
193 mSecurityViolation = false;
194 mIncludeCode = true;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700195 mRegisterPackage = false;
Jeff Browndefd4a62014-03-10 21:24:37 -0700196 mClassLoader = ClassLoader.getSystemClassLoader();
197 mResources = Resources.getSystem();
198 }
199
200 /**
201 * Sets application info about the system package.
202 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100203 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
Jeff Browndefd4a62014-03-10 21:24:37 -0700204 assert info.packageName.equals("android");
205 mApplicationInfo = info;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100206 mClassLoader = classLoader;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700207 }
208
209 public String getPackageName() {
210 return mPackageName;
211 }
212
213 public ApplicationInfo getApplicationInfo() {
214 return mApplicationInfo;
215 }
216
217 public boolean isSecurityViolation() {
218 return mSecurityViolation;
219 }
220
Craig Mautner48d0d182013-06-11 07:53:06 -0700221 public CompatibilityInfo getCompatibilityInfo() {
222 return mDisplayAdjustments.getCompatibilityInfo();
223 }
224
225 public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
226 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
227 }
228
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700229 /**
230 * Gets the array of shared libraries that are listed as
231 * used by the given package.
232 *
233 * @param packageName the name of the package (note: not its
234 * file name)
235 * @return null-ok; the array of shared libraries, each one
236 * a fully-qualified path
237 */
238 private static String[] getLibrariesFor(String packageName) {
239 ApplicationInfo ai = null;
240 try {
241 ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700242 PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700243 } catch (RemoteException e) {
244 throw new AssertionError(e);
245 }
246
247 if (ai == null) {
248 return null;
249 }
250
251 return ai.sharedLibraryFiles;
252 }
253
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700254 public ClassLoader getClassLoader() {
255 synchronized (this) {
256 if (mClassLoader != null) {
257 return mClassLoader;
258 }
259
260 if (mIncludeCode && !mPackageName.equals("android")) {
Narayan Kamath20531682014-07-14 13:18:43 +0100261 // Avoid the binder call when the package is the current application package.
262 // The activity manager will perform ensure that dexopt is performed before
263 // spinning up the process.
264 if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
265 final String isa = VMRuntime.getRuntime().vmInstructionSet();
266 try {
Narayan Kamath20531682014-07-14 13:18:43 +0100267 ActivityThread.getPackageManager().performDexOptIfNeeded(mPackageName, isa);
268 } catch (RemoteException re) {
269 // Ignored.
270 }
271 }
272
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700273 final ArrayList<String> zipPaths = new ArrayList<>();
274 final ArrayList<String> libPaths = new ArrayList<>();
275
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700276 if (mRegisterPackage) {
277 try {
278 ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
279 } catch (RemoteException e) {
280 }
281 }
282
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700283 zipPaths.add(mAppDir);
284 if (mSplitAppDirs != null) {
285 Collections.addAll(zipPaths, mSplitAppDirs);
286 }
287
288 libPaths.add(mLibDir);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700289
290 /*
291 * The following is a bit of a hack to inject
292 * instrumentation into the system: If the app
293 * being started matches one of the instrumentation names,
294 * then we combine both the "instrumentation" and
295 * "instrumented" app into the path, along with the
296 * concatenation of both apps' shared library lists.
297 */
298
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700299 String instrumentationPackageName = mActivityThread.mInstrumentationPackageName;
300 String instrumentationAppDir = mActivityThread.mInstrumentationAppDir;
301 String[] instrumentationSplitAppDirs = mActivityThread.mInstrumentationSplitAppDirs;
302 String instrumentationLibDir = mActivityThread.mInstrumentationLibDir;
303
304 String instrumentedAppDir = mActivityThread.mInstrumentedAppDir;
305 String[] instrumentedSplitAppDirs = mActivityThread.mInstrumentedSplitAppDirs;
306 String instrumentedLibDir = mActivityThread.mInstrumentedLibDir;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700307 String[] instrumentationLibs = null;
308
309 if (mAppDir.equals(instrumentationAppDir)
310 || mAppDir.equals(instrumentedAppDir)) {
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700311 zipPaths.clear();
312 zipPaths.add(instrumentationAppDir);
313 if (instrumentationSplitAppDirs != null) {
314 Collections.addAll(zipPaths, instrumentationSplitAppDirs);
315 }
316 zipPaths.add(instrumentedAppDir);
317 if (instrumentedSplitAppDirs != null) {
318 Collections.addAll(zipPaths, instrumentedSplitAppDirs);
319 }
320
321 libPaths.clear();
322 libPaths.add(instrumentationLibDir);
323 libPaths.add(instrumentedLibDir);
324
325 if (!instrumentedAppDir.equals(instrumentationAppDir)) {
326 instrumentationLibs = getLibrariesFor(instrumentationPackageName);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700327 }
328 }
329
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700330 if (mSharedLibraries != null) {
331 for (String lib : mSharedLibraries) {
332 if (!zipPaths.contains(lib)) {
333 zipPaths.add(0, lib);
334 }
335 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700336 }
337
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700338 if (instrumentationLibs != null) {
339 for (String lib : instrumentationLibs) {
340 if (!zipPaths.contains(lib)) {
341 zipPaths.add(0, lib);
342 }
343 }
344 }
345
346 final String zip = TextUtils.join(File.pathSeparator, zipPaths);
347 final String lib = TextUtils.join(File.pathSeparator, libPaths);
348
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700349 /*
350 * With all the combination done (if necessary, actually
351 * create the class loader.
352 */
353
Kenny Root85387d72010-08-26 10:13:11 -0700354 if (ActivityThread.localLOGV)
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700355 Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + lib);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700356
Brad Fitzpatrick624d50f2010-11-09 14:25:12 -0800357 // Temporarily disable logging of disk reads on the Looper thread
358 // as this is early and necessary.
359 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
360
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700361 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, lib,
362 mBaseClassLoader);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700363 initializeJavaContextClassLoader();
Brad Fitzpatrick624d50f2010-11-09 14:25:12 -0800364
365 StrictMode.setThreadPolicy(oldPolicy);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700366 } else {
367 if (mBaseClassLoader == null) {
368 mClassLoader = ClassLoader.getSystemClassLoader();
369 } else {
370 mClassLoader = mBaseClassLoader;
371 }
372 }
373 return mClassLoader;
374 }
375 }
376
377 /**
378 * Setup value for Thread.getContextClassLoader(). If the
379 * package will not run in in a VM with other packages, we set
380 * the Java context ClassLoader to the
381 * PackageInfo.getClassLoader value. However, if this VM can
382 * contain multiple packages, we intead set the Java context
383 * ClassLoader to a proxy that will warn about the use of Java
384 * context ClassLoaders and then fall through to use the
385 * system ClassLoader.
386 *
387 * <p> Note that this is similar to but not the same as the
388 * android.content.Context.getClassLoader(). While both
389 * context class loaders are typically set to the
390 * PathClassLoader used to load the package archive in the
391 * single application per VM case, a single Android process
392 * may contain several Contexts executing on one thread with
393 * their own logical ClassLoaders while the Java context
394 * ClassLoader is a thread local. This is why in the case when
395 * we have multiple packages per VM we do not set the Java
396 * context ClassLoader to an arbitrary but instead warn the
397 * user to set their own if we detect that they are using a
398 * Java library that expects it to be set.
399 */
400 private void initializeJavaContextClassLoader() {
401 IPackageManager pm = ActivityThread.getPackageManager();
402 android.content.pm.PackageInfo pi;
403 try {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700404 pi = pm.getPackageInfo(mPackageName, 0, UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700405 } catch (RemoteException e) {
Dianne Hackborn208d9372013-02-25 13:17:54 -0800406 throw new IllegalStateException("Unable to get package info for "
407 + mPackageName + "; is system dying?", e);
408 }
409 if (pi == null) {
410 throw new IllegalStateException("Unable to get package info for "
411 + mPackageName + "; is package not installed?");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700412 }
413 /*
414 * Two possible indications that this package could be
415 * sharing its virtual machine with other packages:
416 *
417 * 1.) the sharedUserId attribute is set in the manifest,
418 * indicating a request to share a VM with other
419 * packages with the same sharedUserId.
420 *
421 * 2.) the application element of the manifest has an
422 * attribute specifying a non-default process name,
423 * indicating the desire to run in another packages VM.
424 */
425 boolean sharedUserIdSet = (pi.sharedUserId != null);
426 boolean processNameNotDefault =
427 (pi.applicationInfo != null &&
428 !mPackageName.equals(pi.applicationInfo.processName));
429 boolean sharable = (sharedUserIdSet || processNameNotDefault);
430 ClassLoader contextClassLoader =
431 (sharable)
432 ? new WarningContextClassLoader()
433 : mClassLoader;
434 Thread.currentThread().setContextClassLoader(contextClassLoader);
435 }
436
437 private static class WarningContextClassLoader extends ClassLoader {
438
439 private static boolean warned = false;
440
441 private void warn(String methodName) {
442 if (warned) {
443 return;
444 }
445 warned = true;
446 Thread.currentThread().setContextClassLoader(getParent());
447 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
448 "The class loader returned by " +
449 "Thread.getContextClassLoader() may fail for processes " +
450 "that host multiple applications. You should explicitly " +
451 "specify a context class loader. For example: " +
452 "Thread.setContextClassLoader(getClass().getClassLoader());");
453 }
454
455 @Override public URL getResource(String resName) {
456 warn("getResource");
457 return getParent().getResource(resName);
458 }
459
460 @Override public Enumeration<URL> getResources(String resName) throws IOException {
461 warn("getResources");
462 return getParent().getResources(resName);
463 }
464
465 @Override public InputStream getResourceAsStream(String resName) {
466 warn("getResourceAsStream");
467 return getParent().getResourceAsStream(resName);
468 }
469
470 @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
471 warn("loadClass");
472 return getParent().loadClass(className);
473 }
474
475 @Override public void setClassAssertionStatus(String cname, boolean enable) {
476 warn("setClassAssertionStatus");
477 getParent().setClassAssertionStatus(cname, enable);
478 }
479
480 @Override public void setPackageAssertionStatus(String pname, boolean enable) {
481 warn("setPackageAssertionStatus");
482 getParent().setPackageAssertionStatus(pname, enable);
483 }
484
485 @Override public void setDefaultAssertionStatus(boolean enable) {
486 warn("setDefaultAssertionStatus");
487 getParent().setDefaultAssertionStatus(enable);
488 }
489
490 @Override public void clearAssertionStatus() {
491 warn("clearAssertionStatus");
492 getParent().clearAssertionStatus();
493 }
494 }
495
496 public String getAppDir() {
497 return mAppDir;
498 }
499
Brian Carlstromd893a892012-04-01 21:30:26 -0700500 public String getLibDir() {
501 return mLibDir;
502 }
503
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700504 public String getResDir() {
505 return mResDir;
506 }
507
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700508 public String[] getSplitAppDirs() {
509 return mSplitAppDirs;
510 }
511
512 public String[] getSplitResDirs() {
513 return mSplitResDirs;
514 }
515
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100516 public String[] getOverlayDirs() {
517 return mOverlayDirs;
518 }
519
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700520 public String getDataDir() {
521 return mDataDir;
522 }
523
524 public File getDataDirFile() {
525 return mDataDirFile;
526 }
527
528 public AssetManager getAssets(ActivityThread mainThread) {
529 return getResources(mainThread).getAssets();
530 }
531
532 public Resources getResources(ActivityThread mainThread) {
533 if (mResources == null) {
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700534 mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
Adam Lesinskide898ff2014-01-29 18:20:45 -0800535 mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700536 }
537 return mResources;
538 }
539
540 public Application makeApplication(boolean forceDefaultAppClass,
541 Instrumentation instrumentation) {
542 if (mApplication != null) {
543 return mApplication;
544 }
545
546 Application app = null;
547
548 String appClass = mApplicationInfo.className;
549 if (forceDefaultAppClass || (appClass == null)) {
550 appClass = "android.app.Application";
551 }
552
553 try {
554 java.lang.ClassLoader cl = getClassLoader();
Jeff Browndefd4a62014-03-10 21:24:37 -0700555 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700556 app = mActivityThread.mInstrumentation.newApplication(
557 cl, appClass, appContext);
558 appContext.setOuterContext(app);
559 } catch (Exception e) {
560 if (!mActivityThread.mInstrumentation.onException(app, e)) {
561 throw new RuntimeException(
562 "Unable to instantiate application " + appClass
563 + ": " + e.toString(), e);
564 }
565 }
566 mActivityThread.mAllApplications.add(app);
567 mApplication = app;
568
569 if (instrumentation != null) {
570 try {
571 instrumentation.callApplicationOnCreate(app);
572 } catch (Exception e) {
573 if (!instrumentation.onException(app, e)) {
574 throw new RuntimeException(
575 "Unable to create application " + app.getClass().getName()
576 + ": " + e.toString(), e);
577 }
578 }
579 }
Adam Lesinskide898ff2014-01-29 18:20:45 -0800580
581 // Rewrite the R 'constants' for all library apks.
582 SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
583 .getAssignedPackageIdentifiers();
584 final int N = packageIdentifiers.size();
585 for (int i = 0; i < N; i++) {
586 final int id = packageIdentifiers.keyAt(i);
587 if (id == 0x01 || id == 0x7f) {
588 continue;
589 }
590
591 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
592 }
593
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700594 return app;
595 }
596
Adam Lesinskide898ff2014-01-29 18:20:45 -0800597 private void rewriteRValues(ClassLoader cl, String packageName, int id) {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700598 final Class<?> rClazz;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800599 try {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700600 rClazz = cl.loadClass(packageName + ".R");
601 } catch (ClassNotFoundException e) {
602 // This is not necessarily an error, as some packages do not ship with resources
603 // (or they do not need rewriting).
Adam Lesinski1e4663852014-08-15 14:47:28 -0700604 Log.i(TAG, "No resource references to update in package " + packageName);
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700605 return;
606 }
607
Adam Lesinski1e4663852014-08-15 14:47:28 -0700608 final Method callback;
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700609 try {
Adam Lesinski1e4663852014-08-15 14:47:28 -0700610 callback = rClazz.getMethod("onResourcesLoaded", int.class);
611 } catch (NoSuchMethodException e) {
612 // No rewriting to be done.
613 return;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800614 }
Adam Lesinski1e4663852014-08-15 14:47:28 -0700615
616 Throwable cause;
617 try {
618 callback.invoke(null, id);
619 return;
620 } catch (IllegalAccessException e) {
621 cause = e;
622 } catch (InvocationTargetException e) {
623 cause = e.getCause();
624 }
625
626 throw new RuntimeException("Failed to rewrite resource references for " + packageName,
627 cause);
Adam Lesinskide898ff2014-01-29 18:20:45 -0800628 }
629
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700630 public void removeContextRegistrations(Context context,
631 String who, String what) {
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800632 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700633 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
634 mReceivers.remove(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700635 if (rmap != null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700636 for (int i=0; i<rmap.size(); i++) {
637 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700638 IntentReceiverLeaked leak = new IntentReceiverLeaked(
639 what + " " + who + " has leaked IntentReceiver "
640 + rd.getIntentReceiver() + " that was " +
641 "originally registered here. Are you missing a " +
642 "call to unregisterReceiver()?");
643 leak.setStackTrace(rd.getLocation().getStackTrace());
644 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800645 if (reportRegistrationLeaks) {
646 StrictMode.onIntentReceiverLeaked(leak);
647 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700648 try {
649 ActivityManagerNative.getDefault().unregisterReceiver(
650 rd.getIIntentReceiver());
651 } catch (RemoteException e) {
652 // system crashed, nothing we can do
653 }
654 }
655 }
656 mUnregisteredReceivers.remove(context);
657 //Slog.i(TAG, "Receiver registrations: " + mReceivers);
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700658 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700659 mServices.remove(context);
660 if (smap != null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700661 for (int i=0; i<smap.size(); i++) {
662 LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700663 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
664 what + " " + who + " has leaked ServiceConnection "
665 + sd.getServiceConnection() + " that was originally bound here");
666 leak.setStackTrace(sd.getLocation().getStackTrace());
667 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800668 if (reportRegistrationLeaks) {
669 StrictMode.onServiceConnectionLeaked(leak);
670 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700671 try {
672 ActivityManagerNative.getDefault().unbindService(
673 sd.getIServiceConnection());
674 } catch (RemoteException e) {
675 // system crashed, nothing we can do
676 }
677 sd.doForget();
678 }
679 }
680 mUnboundServices.remove(context);
681 //Slog.i(TAG, "Service registrations: " + mServices);
682 }
683
684 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
685 Context context, Handler handler,
686 Instrumentation instrumentation, boolean registered) {
687 synchronized (mReceivers) {
688 LoadedApk.ReceiverDispatcher rd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700689 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700690 if (registered) {
691 map = mReceivers.get(context);
692 if (map != null) {
693 rd = map.get(r);
694 }
695 }
696 if (rd == null) {
697 rd = new ReceiverDispatcher(r, context, handler,
698 instrumentation, registered);
699 if (registered) {
700 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700701 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700702 mReceivers.put(context, map);
703 }
704 map.put(r, rd);
705 }
706 } else {
707 rd.validate(context, handler);
708 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800709 rd.mForgotten = false;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700710 return rd.getIIntentReceiver();
711 }
712 }
713
714 public IIntentReceiver forgetReceiverDispatcher(Context context,
715 BroadcastReceiver r) {
716 synchronized (mReceivers) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700717 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700718 LoadedApk.ReceiverDispatcher rd = null;
719 if (map != null) {
720 rd = map.get(r);
721 if (rd != null) {
722 map.remove(r);
723 if (map.size() == 0) {
724 mReceivers.remove(context);
725 }
726 if (r.getDebugUnregister()) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700727 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700728 = mUnregisteredReceivers.get(context);
729 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700730 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700731 mUnregisteredReceivers.put(context, holder);
732 }
733 RuntimeException ex = new IllegalArgumentException(
734 "Originally unregistered here:");
735 ex.fillInStackTrace();
736 rd.setUnregisterLocation(ex);
737 holder.put(r, rd);
738 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800739 rd.mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700740 return rd.getIIntentReceiver();
741 }
742 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700743 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700744 = mUnregisteredReceivers.get(context);
745 if (holder != null) {
746 rd = holder.get(r);
747 if (rd != null) {
748 RuntimeException ex = rd.getUnregisterLocation();
749 throw new IllegalArgumentException(
750 "Unregistering Receiver " + r
751 + " that was already unregistered", ex);
752 }
753 }
754 if (context == null) {
755 throw new IllegalStateException("Unbinding Receiver " + r
756 + " from Context that is no longer in use: " + context);
757 } else {
758 throw new IllegalArgumentException("Receiver not registered: " + r);
759 }
760
761 }
762 }
763
764 static final class ReceiverDispatcher {
765
766 final static class InnerReceiver extends IIntentReceiver.Stub {
767 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
768 final LoadedApk.ReceiverDispatcher mStrongRef;
769
770 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
771 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
772 mStrongRef = strong ? rd : null;
773 }
Dianne Hackborn20e80982012-08-31 19:00:44 -0700774 public void performReceive(Intent intent, int resultCode, String data,
775 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700776 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
777 if (ActivityThread.DEBUG_BROADCAST) {
778 int seq = intent.getIntExtra("seq", -1);
779 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
780 + " to " + (rd != null ? rd.mReceiver : null));
781 }
782 if (rd != null) {
783 rd.performReceive(intent, resultCode, data, extras,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700784 ordered, sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700785 } else {
786 // The activity manager dispatched a broadcast to a registered
787 // receiver in this process, but before it could be delivered the
788 // receiver was unregistered. Acknowledge the broadcast on its
789 // behalf so that the system's broadcast sequence can continue.
790 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
791 "Finishing broadcast to unregistered receiver");
792 IActivityManager mgr = ActivityManagerNative.getDefault();
793 try {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -0400794 if (extras != null) {
795 extras.setAllowFds(false);
796 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700797 mgr.finishReceiver(this, resultCode, data, extras, false);
798 } catch (RemoteException e) {
799 Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
800 }
801 }
802 }
803 }
804
805 final IIntentReceiver.Stub mIIntentReceiver;
806 final BroadcastReceiver mReceiver;
807 final Context mContext;
808 final Handler mActivityThread;
809 final Instrumentation mInstrumentation;
810 final boolean mRegistered;
811 final IntentReceiverLeaked mLocation;
812 RuntimeException mUnregisterLocation;
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800813 boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700814
Dianne Hackborne829fef2010-10-26 17:44:01 -0700815 final class Args extends BroadcastReceiver.PendingResult implements Runnable {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700816 private Intent mCurIntent;
Dianne Hackborne829fef2010-10-26 17:44:01 -0700817 private final boolean mOrdered;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700818
Dianne Hackborne829fef2010-10-26 17:44:01 -0700819 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700820 boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700821 super(resultCode, resultData, resultExtras,
822 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700823 ordered, sticky, mIIntentReceiver.asBinder(), sendingUser);
Dianne Hackborne829fef2010-10-26 17:44:01 -0700824 mCurIntent = intent;
825 mOrdered = ordered;
826 }
827
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700828 public void run() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700829 final BroadcastReceiver receiver = mReceiver;
830 final boolean ordered = mOrdered;
831
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700832 if (ActivityThread.DEBUG_BROADCAST) {
833 int seq = mCurIntent.getIntExtra("seq", -1);
834 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
835 + " seq=" + seq + " to " + mReceiver);
836 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
Dianne Hackborne829fef2010-10-26 17:44:01 -0700837 + " mOrderedHint=" + ordered);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700838 }
839
Dianne Hackborne829fef2010-10-26 17:44:01 -0700840 final IActivityManager mgr = ActivityManagerNative.getDefault();
841 final Intent intent = mCurIntent;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700842 mCurIntent = null;
843
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800844 if (receiver == null || mForgotten) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700845 if (mRegistered && ordered) {
846 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
847 "Finishing null broadcast to " + mReceiver);
848 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700849 }
850 return;
851 }
852
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700853 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700854 try {
855 ClassLoader cl = mReceiver.getClass().getClassLoader();
856 intent.setExtrasClassLoader(cl);
Dianne Hackborne829fef2010-10-26 17:44:01 -0700857 setExtrasClassLoader(cl);
858 receiver.setPendingResult(this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700859 receiver.onReceive(mContext, intent);
860 } catch (Exception e) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700861 if (mRegistered && ordered) {
862 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
863 "Finishing failed broadcast to " + mReceiver);
864 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700865 }
866 if (mInstrumentation == null ||
867 !mInstrumentation.onException(mReceiver, e)) {
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700868 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700869 throw new RuntimeException(
870 "Error receiving broadcast " + intent
871 + " in " + mReceiver, e);
872 }
873 }
Dianne Hackborne829fef2010-10-26 17:44:01 -0700874
875 if (receiver.getPendingResult() != null) {
876 finish();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700877 }
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700878 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700879 }
880 }
881
882 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
883 Handler activityThread, Instrumentation instrumentation,
884 boolean registered) {
885 if (activityThread == null) {
886 throw new NullPointerException("Handler must not be null");
887 }
888
889 mIIntentReceiver = new InnerReceiver(this, !registered);
890 mReceiver = receiver;
891 mContext = context;
892 mActivityThread = activityThread;
893 mInstrumentation = instrumentation;
894 mRegistered = registered;
895 mLocation = new IntentReceiverLeaked(null);
896 mLocation.fillInStackTrace();
897 }
898
899 void validate(Context context, Handler activityThread) {
900 if (mContext != context) {
901 throw new IllegalStateException(
902 "Receiver " + mReceiver +
903 " registered with differing Context (was " +
904 mContext + " now " + context + ")");
905 }
906 if (mActivityThread != activityThread) {
907 throw new IllegalStateException(
908 "Receiver " + mReceiver +
909 " registered with differing handler (was " +
910 mActivityThread + " now " + activityThread + ")");
911 }
912 }
913
914 IntentReceiverLeaked getLocation() {
915 return mLocation;
916 }
917
918 BroadcastReceiver getIntentReceiver() {
919 return mReceiver;
920 }
921
922 IIntentReceiver getIIntentReceiver() {
923 return mIIntentReceiver;
924 }
925
926 void setUnregisterLocation(RuntimeException ex) {
927 mUnregisterLocation = ex;
928 }
929
930 RuntimeException getUnregisterLocation() {
931 return mUnregisterLocation;
932 }
933
Dianne Hackborn20e80982012-08-31 19:00:44 -0700934 public void performReceive(Intent intent, int resultCode, String data,
935 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700936 if (ActivityThread.DEBUG_BROADCAST) {
937 int seq = intent.getIntExtra("seq", -1);
938 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
939 + " to " + mReceiver);
940 }
Dianne Hackborn20e80982012-08-31 19:00:44 -0700941 Args args = new Args(intent, resultCode, data, extras, ordered,
942 sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700943 if (!mActivityThread.post(args)) {
944 if (mRegistered && ordered) {
945 IActivityManager mgr = ActivityManagerNative.getDefault();
Dianne Hackborne829fef2010-10-26 17:44:01 -0700946 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
947 "Finishing sync broadcast to " + mReceiver);
948 args.sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700949 }
950 }
951 }
952
953 }
954
955 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
956 Context context, Handler handler, int flags) {
957 synchronized (mServices) {
958 LoadedApk.ServiceDispatcher sd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700959 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700960 if (map != null) {
961 sd = map.get(c);
962 }
963 if (sd == null) {
964 sd = new ServiceDispatcher(c, context, handler, flags);
965 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700966 map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700967 mServices.put(context, map);
968 }
969 map.put(c, sd);
970 } else {
971 sd.validate(context, handler);
972 }
973 return sd.getIServiceConnection();
974 }
975 }
976
977 public final IServiceConnection forgetServiceDispatcher(Context context,
978 ServiceConnection c) {
979 synchronized (mServices) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700980 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700981 = mServices.get(context);
982 LoadedApk.ServiceDispatcher sd = null;
983 if (map != null) {
984 sd = map.get(c);
985 if (sd != null) {
986 map.remove(c);
987 sd.doForget();
988 if (map.size() == 0) {
989 mServices.remove(context);
990 }
991 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700992 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700993 = mUnboundServices.get(context);
994 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700995 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700996 mUnboundServices.put(context, holder);
997 }
998 RuntimeException ex = new IllegalArgumentException(
999 "Originally unbound here:");
1000 ex.fillInStackTrace();
1001 sd.setUnbindLocation(ex);
1002 holder.put(c, sd);
1003 }
1004 return sd.getIServiceConnection();
1005 }
1006 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001007 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001008 = mUnboundServices.get(context);
1009 if (holder != null) {
1010 sd = holder.get(c);
1011 if (sd != null) {
1012 RuntimeException ex = sd.getUnbindLocation();
1013 throw new IllegalArgumentException(
1014 "Unbinding Service " + c
1015 + " that was already unbound", ex);
1016 }
1017 }
1018 if (context == null) {
1019 throw new IllegalStateException("Unbinding Service " + c
1020 + " from Context that is no longer in use: " + context);
1021 } else {
1022 throw new IllegalArgumentException("Service not registered: " + c);
1023 }
1024 }
1025 }
1026
1027 static final class ServiceDispatcher {
1028 private final ServiceDispatcher.InnerConnection mIServiceConnection;
1029 private final ServiceConnection mConnection;
1030 private final Context mContext;
1031 private final Handler mActivityThread;
1032 private final ServiceConnectionLeaked mLocation;
1033 private final int mFlags;
1034
1035 private RuntimeException mUnbindLocation;
1036
1037 private boolean mDied;
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001038 private boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001039
1040 private static class ConnectionInfo {
1041 IBinder binder;
1042 IBinder.DeathRecipient deathMonitor;
1043 }
1044
1045 private static class InnerConnection extends IServiceConnection.Stub {
1046 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1047
1048 InnerConnection(LoadedApk.ServiceDispatcher sd) {
1049 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1050 }
1051
1052 public void connected(ComponentName name, IBinder service) throws RemoteException {
1053 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1054 if (sd != null) {
1055 sd.connected(name, service);
1056 }
1057 }
1058 }
1059
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001060 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1061 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001062
1063 ServiceDispatcher(ServiceConnection conn,
1064 Context context, Handler activityThread, int flags) {
1065 mIServiceConnection = new InnerConnection(this);
1066 mConnection = conn;
1067 mContext = context;
1068 mActivityThread = activityThread;
1069 mLocation = new ServiceConnectionLeaked(null);
1070 mLocation.fillInStackTrace();
1071 mFlags = flags;
1072 }
1073
1074 void validate(Context context, Handler activityThread) {
1075 if (mContext != context) {
1076 throw new RuntimeException(
1077 "ServiceConnection " + mConnection +
1078 " registered with differing Context (was " +
1079 mContext + " now " + context + ")");
1080 }
1081 if (mActivityThread != activityThread) {
1082 throw new RuntimeException(
1083 "ServiceConnection " + mConnection +
1084 " registered with differing handler (was " +
1085 mActivityThread + " now " + activityThread + ")");
1086 }
1087 }
1088
1089 void doForget() {
1090 synchronized(this) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001091 for (int i=0; i<mActiveConnections.size(); i++) {
1092 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001093 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1094 }
1095 mActiveConnections.clear();
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001096 mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001097 }
1098 }
1099
1100 ServiceConnectionLeaked getLocation() {
1101 return mLocation;
1102 }
1103
1104 ServiceConnection getServiceConnection() {
1105 return mConnection;
1106 }
1107
1108 IServiceConnection getIServiceConnection() {
1109 return mIServiceConnection;
1110 }
1111
1112 int getFlags() {
1113 return mFlags;
1114 }
1115
1116 void setUnbindLocation(RuntimeException ex) {
1117 mUnbindLocation = ex;
1118 }
1119
1120 RuntimeException getUnbindLocation() {
1121 return mUnbindLocation;
1122 }
1123
1124 public void connected(ComponentName name, IBinder service) {
1125 if (mActivityThread != null) {
1126 mActivityThread.post(new RunConnection(name, service, 0));
1127 } else {
1128 doConnected(name, service);
1129 }
1130 }
1131
1132 public void death(ComponentName name, IBinder service) {
1133 ServiceDispatcher.ConnectionInfo old;
1134
1135 synchronized (this) {
1136 mDied = true;
1137 old = mActiveConnections.remove(name);
1138 if (old == null || old.binder != service) {
1139 // Death for someone different than who we last
1140 // reported... just ignore it.
1141 return;
1142 }
1143 old.binder.unlinkToDeath(old.deathMonitor, 0);
1144 }
1145
1146 if (mActivityThread != null) {
1147 mActivityThread.post(new RunConnection(name, service, 1));
1148 } else {
1149 doDeath(name, service);
1150 }
1151 }
1152
1153 public void doConnected(ComponentName name, IBinder service) {
1154 ServiceDispatcher.ConnectionInfo old;
1155 ServiceDispatcher.ConnectionInfo info;
1156
1157 synchronized (this) {
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001158 if (mForgotten) {
1159 // We unbound before receiving the connection; ignore
1160 // any connection received.
1161 return;
1162 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001163 old = mActiveConnections.get(name);
1164 if (old != null && old.binder == service) {
1165 // Huh, already have this one. Oh well!
1166 return;
1167 }
1168
1169 if (service != null) {
1170 // A new service is being connected... set it all up.
1171 mDied = false;
1172 info = new ConnectionInfo();
1173 info.binder = service;
1174 info.deathMonitor = new DeathMonitor(name, service);
1175 try {
1176 service.linkToDeath(info.deathMonitor, 0);
1177 mActiveConnections.put(name, info);
1178 } catch (RemoteException e) {
1179 // This service was dead before we got it... just
1180 // don't do anything with it.
1181 mActiveConnections.remove(name);
1182 return;
1183 }
1184
1185 } else {
1186 // The named service is being disconnected... clean up.
1187 mActiveConnections.remove(name);
1188 }
1189
1190 if (old != null) {
1191 old.binder.unlinkToDeath(old.deathMonitor, 0);
1192 }
1193 }
1194
1195 // If there was an old service, it is not disconnected.
1196 if (old != null) {
1197 mConnection.onServiceDisconnected(name);
1198 }
1199 // If there is a new service, it is now connected.
1200 if (service != null) {
1201 mConnection.onServiceConnected(name, service);
1202 }
1203 }
1204
1205 public void doDeath(ComponentName name, IBinder service) {
1206 mConnection.onServiceDisconnected(name);
1207 }
1208
1209 private final class RunConnection implements Runnable {
1210 RunConnection(ComponentName name, IBinder service, int command) {
1211 mName = name;
1212 mService = service;
1213 mCommand = command;
1214 }
1215
1216 public void run() {
1217 if (mCommand == 0) {
1218 doConnected(mName, mService);
1219 } else if (mCommand == 1) {
1220 doDeath(mName, mService);
1221 }
1222 }
1223
1224 final ComponentName mName;
1225 final IBinder mService;
1226 final int mCommand;
1227 }
1228
1229 private final class DeathMonitor implements IBinder.DeathRecipient
1230 {
1231 DeathMonitor(ComponentName name, IBinder service) {
1232 mName = name;
1233 mService = service;
1234 }
1235
1236 public void binderDied() {
1237 death(mName, mService);
1238 }
1239
1240 final ComponentName mName;
1241 final IBinder mService;
1242 }
1243 }
1244}