blob: 973196c1f3f8811a1f025531ac079f40beae6e52 [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);
Brad Fitzpatrick624d50f2010-11-09 14:25:12 -0800363
364 StrictMode.setThreadPolicy(oldPolicy);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700365 } else {
366 if (mBaseClassLoader == null) {
367 mClassLoader = ClassLoader.getSystemClassLoader();
368 } else {
369 mClassLoader = mBaseClassLoader;
370 }
371 }
372 return mClassLoader;
373 }
374 }
375
376 /**
377 * Setup value for Thread.getContextClassLoader(). If the
378 * package will not run in in a VM with other packages, we set
379 * the Java context ClassLoader to the
380 * PackageInfo.getClassLoader value. However, if this VM can
381 * contain multiple packages, we intead set the Java context
382 * ClassLoader to a proxy that will warn about the use of Java
383 * context ClassLoaders and then fall through to use the
384 * system ClassLoader.
385 *
386 * <p> Note that this is similar to but not the same as the
387 * android.content.Context.getClassLoader(). While both
388 * context class loaders are typically set to the
389 * PathClassLoader used to load the package archive in the
390 * single application per VM case, a single Android process
391 * may contain several Contexts executing on one thread with
392 * their own logical ClassLoaders while the Java context
393 * ClassLoader is a thread local. This is why in the case when
394 * we have multiple packages per VM we do not set the Java
395 * context ClassLoader to an arbitrary but instead warn the
396 * user to set their own if we detect that they are using a
397 * Java library that expects it to be set.
398 */
399 private void initializeJavaContextClassLoader() {
400 IPackageManager pm = ActivityThread.getPackageManager();
401 android.content.pm.PackageInfo pi;
402 try {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700403 pi = pm.getPackageInfo(mPackageName, 0, UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700404 } catch (RemoteException e) {
Dianne Hackborn208d9372013-02-25 13:17:54 -0800405 throw new IllegalStateException("Unable to get package info for "
406 + mPackageName + "; is system dying?", e);
407 }
408 if (pi == null) {
409 throw new IllegalStateException("Unable to get package info for "
410 + mPackageName + "; is package not installed?");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700411 }
412 /*
413 * Two possible indications that this package could be
414 * sharing its virtual machine with other packages:
415 *
416 * 1.) the sharedUserId attribute is set in the manifest,
417 * indicating a request to share a VM with other
418 * packages with the same sharedUserId.
419 *
420 * 2.) the application element of the manifest has an
421 * attribute specifying a non-default process name,
422 * indicating the desire to run in another packages VM.
423 */
424 boolean sharedUserIdSet = (pi.sharedUserId != null);
425 boolean processNameNotDefault =
426 (pi.applicationInfo != null &&
427 !mPackageName.equals(pi.applicationInfo.processName));
428 boolean sharable = (sharedUserIdSet || processNameNotDefault);
429 ClassLoader contextClassLoader =
430 (sharable)
431 ? new WarningContextClassLoader()
432 : mClassLoader;
433 Thread.currentThread().setContextClassLoader(contextClassLoader);
434 }
435
436 private static class WarningContextClassLoader extends ClassLoader {
437
438 private static boolean warned = false;
439
440 private void warn(String methodName) {
441 if (warned) {
442 return;
443 }
444 warned = true;
445 Thread.currentThread().setContextClassLoader(getParent());
446 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
447 "The class loader returned by " +
448 "Thread.getContextClassLoader() may fail for processes " +
449 "that host multiple applications. You should explicitly " +
450 "specify a context class loader. For example: " +
451 "Thread.setContextClassLoader(getClass().getClassLoader());");
452 }
453
454 @Override public URL getResource(String resName) {
455 warn("getResource");
456 return getParent().getResource(resName);
457 }
458
459 @Override public Enumeration<URL> getResources(String resName) throws IOException {
460 warn("getResources");
461 return getParent().getResources(resName);
462 }
463
464 @Override public InputStream getResourceAsStream(String resName) {
465 warn("getResourceAsStream");
466 return getParent().getResourceAsStream(resName);
467 }
468
469 @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
470 warn("loadClass");
471 return getParent().loadClass(className);
472 }
473
474 @Override public void setClassAssertionStatus(String cname, boolean enable) {
475 warn("setClassAssertionStatus");
476 getParent().setClassAssertionStatus(cname, enable);
477 }
478
479 @Override public void setPackageAssertionStatus(String pname, boolean enable) {
480 warn("setPackageAssertionStatus");
481 getParent().setPackageAssertionStatus(pname, enable);
482 }
483
484 @Override public void setDefaultAssertionStatus(boolean enable) {
485 warn("setDefaultAssertionStatus");
486 getParent().setDefaultAssertionStatus(enable);
487 }
488
489 @Override public void clearAssertionStatus() {
490 warn("clearAssertionStatus");
491 getParent().clearAssertionStatus();
492 }
493 }
494
495 public String getAppDir() {
496 return mAppDir;
497 }
498
Brian Carlstromd893a892012-04-01 21:30:26 -0700499 public String getLibDir() {
500 return mLibDir;
501 }
502
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700503 public String getResDir() {
504 return mResDir;
505 }
506
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700507 public String[] getSplitAppDirs() {
508 return mSplitAppDirs;
509 }
510
511 public String[] getSplitResDirs() {
512 return mSplitResDirs;
513 }
514
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100515 public String[] getOverlayDirs() {
516 return mOverlayDirs;
517 }
518
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700519 public String getDataDir() {
520 return mDataDir;
521 }
522
523 public File getDataDirFile() {
524 return mDataDirFile;
525 }
526
527 public AssetManager getAssets(ActivityThread mainThread) {
528 return getResources(mainThread).getAssets();
529 }
530
531 public Resources getResources(ActivityThread mainThread) {
532 if (mResources == null) {
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700533 mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
Adam Lesinskide898ff2014-01-29 18:20:45 -0800534 mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700535 }
536 return mResources;
537 }
538
539 public Application makeApplication(boolean forceDefaultAppClass,
540 Instrumentation instrumentation) {
541 if (mApplication != null) {
542 return mApplication;
543 }
544
545 Application app = null;
546
547 String appClass = mApplicationInfo.className;
548 if (forceDefaultAppClass || (appClass == null)) {
549 appClass = "android.app.Application";
550 }
551
552 try {
553 java.lang.ClassLoader cl = getClassLoader();
Narayan Kamath8091edb2014-10-15 11:38:44 +0100554 if (!mPackageName.equals("android")) {
555 initializeJavaContextClassLoader();
556 }
Jeff Browndefd4a62014-03-10 21:24:37 -0700557 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700558 app = mActivityThread.mInstrumentation.newApplication(
559 cl, appClass, appContext);
560 appContext.setOuterContext(app);
561 } catch (Exception e) {
562 if (!mActivityThread.mInstrumentation.onException(app, e)) {
563 throw new RuntimeException(
564 "Unable to instantiate application " + appClass
565 + ": " + e.toString(), e);
566 }
567 }
568 mActivityThread.mAllApplications.add(app);
569 mApplication = app;
570
571 if (instrumentation != null) {
572 try {
573 instrumentation.callApplicationOnCreate(app);
574 } catch (Exception e) {
575 if (!instrumentation.onException(app, e)) {
576 throw new RuntimeException(
577 "Unable to create application " + app.getClass().getName()
578 + ": " + e.toString(), e);
579 }
580 }
581 }
Adam Lesinskide898ff2014-01-29 18:20:45 -0800582
583 // Rewrite the R 'constants' for all library apks.
584 SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
585 .getAssignedPackageIdentifiers();
586 final int N = packageIdentifiers.size();
587 for (int i = 0; i < N; i++) {
588 final int id = packageIdentifiers.keyAt(i);
589 if (id == 0x01 || id == 0x7f) {
590 continue;
591 }
592
593 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
594 }
595
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700596 return app;
597 }
598
Adam Lesinskide898ff2014-01-29 18:20:45 -0800599 private void rewriteRValues(ClassLoader cl, String packageName, int id) {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700600 final Class<?> rClazz;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800601 try {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700602 rClazz = cl.loadClass(packageName + ".R");
603 } catch (ClassNotFoundException e) {
604 // This is not necessarily an error, as some packages do not ship with resources
605 // (or they do not need rewriting).
Adam Lesinski1e4663852014-08-15 14:47:28 -0700606 Log.i(TAG, "No resource references to update in package " + packageName);
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700607 return;
608 }
609
Adam Lesinski1e4663852014-08-15 14:47:28 -0700610 final Method callback;
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700611 try {
Adam Lesinski1e4663852014-08-15 14:47:28 -0700612 callback = rClazz.getMethod("onResourcesLoaded", int.class);
613 } catch (NoSuchMethodException e) {
614 // No rewriting to be done.
615 return;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800616 }
Adam Lesinski1e4663852014-08-15 14:47:28 -0700617
618 Throwable cause;
619 try {
620 callback.invoke(null, id);
621 return;
622 } catch (IllegalAccessException e) {
623 cause = e;
624 } catch (InvocationTargetException e) {
625 cause = e.getCause();
626 }
627
628 throw new RuntimeException("Failed to rewrite resource references for " + packageName,
629 cause);
Adam Lesinskide898ff2014-01-29 18:20:45 -0800630 }
631
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700632 public void removeContextRegistrations(Context context,
633 String who, String what) {
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800634 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700635 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
636 mReceivers.remove(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700637 if (rmap != null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700638 for (int i=0; i<rmap.size(); i++) {
639 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700640 IntentReceiverLeaked leak = new IntentReceiverLeaked(
641 what + " " + who + " has leaked IntentReceiver "
642 + rd.getIntentReceiver() + " that was " +
643 "originally registered here. Are you missing a " +
644 "call to unregisterReceiver()?");
645 leak.setStackTrace(rd.getLocation().getStackTrace());
646 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800647 if (reportRegistrationLeaks) {
648 StrictMode.onIntentReceiverLeaked(leak);
649 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700650 try {
651 ActivityManagerNative.getDefault().unregisterReceiver(
652 rd.getIIntentReceiver());
653 } catch (RemoteException e) {
654 // system crashed, nothing we can do
655 }
656 }
657 }
658 mUnregisteredReceivers.remove(context);
659 //Slog.i(TAG, "Receiver registrations: " + mReceivers);
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700660 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700661 mServices.remove(context);
662 if (smap != null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700663 for (int i=0; i<smap.size(); i++) {
664 LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700665 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
666 what + " " + who + " has leaked ServiceConnection "
667 + sd.getServiceConnection() + " that was originally bound here");
668 leak.setStackTrace(sd.getLocation().getStackTrace());
669 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800670 if (reportRegistrationLeaks) {
671 StrictMode.onServiceConnectionLeaked(leak);
672 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700673 try {
674 ActivityManagerNative.getDefault().unbindService(
675 sd.getIServiceConnection());
676 } catch (RemoteException e) {
677 // system crashed, nothing we can do
678 }
679 sd.doForget();
680 }
681 }
682 mUnboundServices.remove(context);
683 //Slog.i(TAG, "Service registrations: " + mServices);
684 }
685
686 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
687 Context context, Handler handler,
688 Instrumentation instrumentation, boolean registered) {
689 synchronized (mReceivers) {
690 LoadedApk.ReceiverDispatcher rd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700691 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700692 if (registered) {
693 map = mReceivers.get(context);
694 if (map != null) {
695 rd = map.get(r);
696 }
697 }
698 if (rd == null) {
699 rd = new ReceiverDispatcher(r, context, handler,
700 instrumentation, registered);
701 if (registered) {
702 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700703 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700704 mReceivers.put(context, map);
705 }
706 map.put(r, rd);
707 }
708 } else {
709 rd.validate(context, handler);
710 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800711 rd.mForgotten = false;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700712 return rd.getIIntentReceiver();
713 }
714 }
715
716 public IIntentReceiver forgetReceiverDispatcher(Context context,
717 BroadcastReceiver r) {
718 synchronized (mReceivers) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700719 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700720 LoadedApk.ReceiverDispatcher rd = null;
721 if (map != null) {
722 rd = map.get(r);
723 if (rd != null) {
724 map.remove(r);
725 if (map.size() == 0) {
726 mReceivers.remove(context);
727 }
728 if (r.getDebugUnregister()) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700729 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700730 = mUnregisteredReceivers.get(context);
731 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700732 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700733 mUnregisteredReceivers.put(context, holder);
734 }
735 RuntimeException ex = new IllegalArgumentException(
736 "Originally unregistered here:");
737 ex.fillInStackTrace();
738 rd.setUnregisterLocation(ex);
739 holder.put(r, rd);
740 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800741 rd.mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700742 return rd.getIIntentReceiver();
743 }
744 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700745 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700746 = mUnregisteredReceivers.get(context);
747 if (holder != null) {
748 rd = holder.get(r);
749 if (rd != null) {
750 RuntimeException ex = rd.getUnregisterLocation();
751 throw new IllegalArgumentException(
752 "Unregistering Receiver " + r
753 + " that was already unregistered", ex);
754 }
755 }
756 if (context == null) {
757 throw new IllegalStateException("Unbinding Receiver " + r
758 + " from Context that is no longer in use: " + context);
759 } else {
760 throw new IllegalArgumentException("Receiver not registered: " + r);
761 }
762
763 }
764 }
765
766 static final class ReceiverDispatcher {
767
768 final static class InnerReceiver extends IIntentReceiver.Stub {
769 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
770 final LoadedApk.ReceiverDispatcher mStrongRef;
771
772 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
773 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
774 mStrongRef = strong ? rd : null;
775 }
Dianne Hackborn20e80982012-08-31 19:00:44 -0700776 public void performReceive(Intent intent, int resultCode, String data,
777 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700778 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
779 if (ActivityThread.DEBUG_BROADCAST) {
780 int seq = intent.getIntExtra("seq", -1);
781 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
782 + " to " + (rd != null ? rd.mReceiver : null));
783 }
784 if (rd != null) {
785 rd.performReceive(intent, resultCode, data, extras,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700786 ordered, sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700787 } else {
788 // The activity manager dispatched a broadcast to a registered
789 // receiver in this process, but before it could be delivered the
790 // receiver was unregistered. Acknowledge the broadcast on its
791 // behalf so that the system's broadcast sequence can continue.
792 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
793 "Finishing broadcast to unregistered receiver");
794 IActivityManager mgr = ActivityManagerNative.getDefault();
795 try {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -0400796 if (extras != null) {
797 extras.setAllowFds(false);
798 }
riddle_hsu1f5ac4d2015-01-03 15:38:21 +0800799 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700800 } catch (RemoteException e) {
801 Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
802 }
803 }
804 }
805 }
806
807 final IIntentReceiver.Stub mIIntentReceiver;
808 final BroadcastReceiver mReceiver;
809 final Context mContext;
810 final Handler mActivityThread;
811 final Instrumentation mInstrumentation;
812 final boolean mRegistered;
813 final IntentReceiverLeaked mLocation;
814 RuntimeException mUnregisterLocation;
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800815 boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700816
Dianne Hackborne829fef2010-10-26 17:44:01 -0700817 final class Args extends BroadcastReceiver.PendingResult implements Runnable {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700818 private Intent mCurIntent;
Dianne Hackborne829fef2010-10-26 17:44:01 -0700819 private final boolean mOrdered;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700820
Dianne Hackborne829fef2010-10-26 17:44:01 -0700821 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700822 boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700823 super(resultCode, resultData, resultExtras,
riddle_hsu1f5ac4d2015-01-03 15:38:21 +0800824 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
825 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
Dianne Hackborne829fef2010-10-26 17:44:01 -0700826 mCurIntent = intent;
827 mOrdered = ordered;
828 }
829
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700830 public void run() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700831 final BroadcastReceiver receiver = mReceiver;
832 final boolean ordered = mOrdered;
833
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700834 if (ActivityThread.DEBUG_BROADCAST) {
835 int seq = mCurIntent.getIntExtra("seq", -1);
836 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
837 + " seq=" + seq + " to " + mReceiver);
838 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
Dianne Hackborne829fef2010-10-26 17:44:01 -0700839 + " mOrderedHint=" + ordered);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700840 }
841
Dianne Hackborne829fef2010-10-26 17:44:01 -0700842 final IActivityManager mgr = ActivityManagerNative.getDefault();
843 final Intent intent = mCurIntent;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700844 mCurIntent = null;
845
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800846 if (receiver == null || mForgotten) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700847 if (mRegistered && ordered) {
848 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
849 "Finishing null broadcast to " + mReceiver);
850 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700851 }
852 return;
853 }
854
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700855 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700856 try {
857 ClassLoader cl = mReceiver.getClass().getClassLoader();
858 intent.setExtrasClassLoader(cl);
Dianne Hackborne829fef2010-10-26 17:44:01 -0700859 setExtrasClassLoader(cl);
860 receiver.setPendingResult(this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700861 receiver.onReceive(mContext, intent);
862 } catch (Exception e) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700863 if (mRegistered && ordered) {
864 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
865 "Finishing failed broadcast to " + mReceiver);
866 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700867 }
868 if (mInstrumentation == null ||
869 !mInstrumentation.onException(mReceiver, e)) {
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700870 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700871 throw new RuntimeException(
872 "Error receiving broadcast " + intent
873 + " in " + mReceiver, e);
874 }
875 }
Dianne Hackborne829fef2010-10-26 17:44:01 -0700876
877 if (receiver.getPendingResult() != null) {
878 finish();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700879 }
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700880 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700881 }
882 }
883
884 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
885 Handler activityThread, Instrumentation instrumentation,
886 boolean registered) {
887 if (activityThread == null) {
888 throw new NullPointerException("Handler must not be null");
889 }
890
891 mIIntentReceiver = new InnerReceiver(this, !registered);
892 mReceiver = receiver;
893 mContext = context;
894 mActivityThread = activityThread;
895 mInstrumentation = instrumentation;
896 mRegistered = registered;
897 mLocation = new IntentReceiverLeaked(null);
898 mLocation.fillInStackTrace();
899 }
900
901 void validate(Context context, Handler activityThread) {
902 if (mContext != context) {
903 throw new IllegalStateException(
904 "Receiver " + mReceiver +
905 " registered with differing Context (was " +
906 mContext + " now " + context + ")");
907 }
908 if (mActivityThread != activityThread) {
909 throw new IllegalStateException(
910 "Receiver " + mReceiver +
911 " registered with differing handler (was " +
912 mActivityThread + " now " + activityThread + ")");
913 }
914 }
915
916 IntentReceiverLeaked getLocation() {
917 return mLocation;
918 }
919
920 BroadcastReceiver getIntentReceiver() {
921 return mReceiver;
922 }
923
924 IIntentReceiver getIIntentReceiver() {
925 return mIIntentReceiver;
926 }
927
928 void setUnregisterLocation(RuntimeException ex) {
929 mUnregisterLocation = ex;
930 }
931
932 RuntimeException getUnregisterLocation() {
933 return mUnregisterLocation;
934 }
935
Dianne Hackborn20e80982012-08-31 19:00:44 -0700936 public void performReceive(Intent intent, int resultCode, String data,
937 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700938 if (ActivityThread.DEBUG_BROADCAST) {
939 int seq = intent.getIntExtra("seq", -1);
940 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
941 + " to " + mReceiver);
942 }
Dianne Hackborn20e80982012-08-31 19:00:44 -0700943 Args args = new Args(intent, resultCode, data, extras, ordered,
944 sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700945 if (!mActivityThread.post(args)) {
946 if (mRegistered && ordered) {
947 IActivityManager mgr = ActivityManagerNative.getDefault();
Dianne Hackborne829fef2010-10-26 17:44:01 -0700948 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
949 "Finishing sync broadcast to " + mReceiver);
950 args.sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700951 }
952 }
953 }
954
955 }
956
957 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
958 Context context, Handler handler, int flags) {
959 synchronized (mServices) {
960 LoadedApk.ServiceDispatcher sd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700961 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700962 if (map != null) {
963 sd = map.get(c);
964 }
965 if (sd == null) {
966 sd = new ServiceDispatcher(c, context, handler, flags);
967 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700968 map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700969 mServices.put(context, map);
970 }
971 map.put(c, sd);
972 } else {
973 sd.validate(context, handler);
974 }
975 return sd.getIServiceConnection();
976 }
977 }
978
979 public final IServiceConnection forgetServiceDispatcher(Context context,
980 ServiceConnection c) {
981 synchronized (mServices) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700982 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700983 = mServices.get(context);
984 LoadedApk.ServiceDispatcher sd = null;
985 if (map != null) {
986 sd = map.get(c);
987 if (sd != null) {
988 map.remove(c);
989 sd.doForget();
990 if (map.size() == 0) {
991 mServices.remove(context);
992 }
993 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700994 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700995 = mUnboundServices.get(context);
996 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700997 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700998 mUnboundServices.put(context, holder);
999 }
1000 RuntimeException ex = new IllegalArgumentException(
1001 "Originally unbound here:");
1002 ex.fillInStackTrace();
1003 sd.setUnbindLocation(ex);
1004 holder.put(c, sd);
1005 }
1006 return sd.getIServiceConnection();
1007 }
1008 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001009 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001010 = mUnboundServices.get(context);
1011 if (holder != null) {
1012 sd = holder.get(c);
1013 if (sd != null) {
1014 RuntimeException ex = sd.getUnbindLocation();
1015 throw new IllegalArgumentException(
1016 "Unbinding Service " + c
1017 + " that was already unbound", ex);
1018 }
1019 }
1020 if (context == null) {
1021 throw new IllegalStateException("Unbinding Service " + c
1022 + " from Context that is no longer in use: " + context);
1023 } else {
1024 throw new IllegalArgumentException("Service not registered: " + c);
1025 }
1026 }
1027 }
1028
1029 static final class ServiceDispatcher {
1030 private final ServiceDispatcher.InnerConnection mIServiceConnection;
1031 private final ServiceConnection mConnection;
1032 private final Context mContext;
1033 private final Handler mActivityThread;
1034 private final ServiceConnectionLeaked mLocation;
1035 private final int mFlags;
1036
1037 private RuntimeException mUnbindLocation;
1038
1039 private boolean mDied;
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001040 private boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001041
1042 private static class ConnectionInfo {
1043 IBinder binder;
1044 IBinder.DeathRecipient deathMonitor;
1045 }
1046
1047 private static class InnerConnection extends IServiceConnection.Stub {
1048 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1049
1050 InnerConnection(LoadedApk.ServiceDispatcher sd) {
1051 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1052 }
1053
1054 public void connected(ComponentName name, IBinder service) throws RemoteException {
1055 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1056 if (sd != null) {
1057 sd.connected(name, service);
1058 }
1059 }
1060 }
1061
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001062 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1063 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001064
1065 ServiceDispatcher(ServiceConnection conn,
1066 Context context, Handler activityThread, int flags) {
1067 mIServiceConnection = new InnerConnection(this);
1068 mConnection = conn;
1069 mContext = context;
1070 mActivityThread = activityThread;
1071 mLocation = new ServiceConnectionLeaked(null);
1072 mLocation.fillInStackTrace();
1073 mFlags = flags;
1074 }
1075
1076 void validate(Context context, Handler activityThread) {
1077 if (mContext != context) {
1078 throw new RuntimeException(
1079 "ServiceConnection " + mConnection +
1080 " registered with differing Context (was " +
1081 mContext + " now " + context + ")");
1082 }
1083 if (mActivityThread != activityThread) {
1084 throw new RuntimeException(
1085 "ServiceConnection " + mConnection +
1086 " registered with differing handler (was " +
1087 mActivityThread + " now " + activityThread + ")");
1088 }
1089 }
1090
1091 void doForget() {
1092 synchronized(this) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001093 for (int i=0; i<mActiveConnections.size(); i++) {
1094 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001095 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1096 }
1097 mActiveConnections.clear();
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001098 mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001099 }
1100 }
1101
1102 ServiceConnectionLeaked getLocation() {
1103 return mLocation;
1104 }
1105
1106 ServiceConnection getServiceConnection() {
1107 return mConnection;
1108 }
1109
1110 IServiceConnection getIServiceConnection() {
1111 return mIServiceConnection;
1112 }
1113
1114 int getFlags() {
1115 return mFlags;
1116 }
1117
1118 void setUnbindLocation(RuntimeException ex) {
1119 mUnbindLocation = ex;
1120 }
1121
1122 RuntimeException getUnbindLocation() {
1123 return mUnbindLocation;
1124 }
1125
1126 public void connected(ComponentName name, IBinder service) {
1127 if (mActivityThread != null) {
1128 mActivityThread.post(new RunConnection(name, service, 0));
1129 } else {
1130 doConnected(name, service);
1131 }
1132 }
1133
1134 public void death(ComponentName name, IBinder service) {
1135 ServiceDispatcher.ConnectionInfo old;
1136
1137 synchronized (this) {
1138 mDied = true;
1139 old = mActiveConnections.remove(name);
1140 if (old == null || old.binder != service) {
1141 // Death for someone different than who we last
1142 // reported... just ignore it.
1143 return;
1144 }
1145 old.binder.unlinkToDeath(old.deathMonitor, 0);
1146 }
1147
1148 if (mActivityThread != null) {
1149 mActivityThread.post(new RunConnection(name, service, 1));
1150 } else {
1151 doDeath(name, service);
1152 }
1153 }
1154
1155 public void doConnected(ComponentName name, IBinder service) {
1156 ServiceDispatcher.ConnectionInfo old;
1157 ServiceDispatcher.ConnectionInfo info;
1158
1159 synchronized (this) {
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001160 if (mForgotten) {
1161 // We unbound before receiving the connection; ignore
1162 // any connection received.
1163 return;
1164 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001165 old = mActiveConnections.get(name);
1166 if (old != null && old.binder == service) {
1167 // Huh, already have this one. Oh well!
1168 return;
1169 }
1170
1171 if (service != null) {
1172 // A new service is being connected... set it all up.
1173 mDied = false;
1174 info = new ConnectionInfo();
1175 info.binder = service;
1176 info.deathMonitor = new DeathMonitor(name, service);
1177 try {
1178 service.linkToDeath(info.deathMonitor, 0);
1179 mActiveConnections.put(name, info);
1180 } catch (RemoteException e) {
1181 // This service was dead before we got it... just
1182 // don't do anything with it.
1183 mActiveConnections.remove(name);
1184 return;
1185 }
1186
1187 } else {
1188 // The named service is being disconnected... clean up.
1189 mActiveConnections.remove(name);
1190 }
1191
1192 if (old != null) {
1193 old.binder.unlinkToDeath(old.deathMonitor, 0);
1194 }
1195 }
1196
1197 // If there was an old service, it is not disconnected.
1198 if (old != null) {
1199 mConnection.onServiceDisconnected(name);
1200 }
1201 // If there is a new service, it is now connected.
1202 if (service != null) {
1203 mConnection.onServiceConnected(name, service);
1204 }
1205 }
1206
1207 public void doDeath(ComponentName name, IBinder service) {
1208 mConnection.onServiceDisconnected(name);
1209 }
1210
1211 private final class RunConnection implements Runnable {
1212 RunConnection(ComponentName name, IBinder service, int command) {
1213 mName = name;
1214 mService = service;
1215 mCommand = command;
1216 }
1217
1218 public void run() {
1219 if (mCommand == 0) {
1220 doConnected(mName, mService);
1221 } else if (mCommand == 1) {
1222 doDeath(mName, mService);
1223 }
1224 }
1225
1226 final ComponentName mName;
1227 final IBinder mService;
1228 final int mCommand;
1229 }
1230
1231 private final class DeathMonitor implements IBinder.DeathRecipient
1232 {
1233 DeathMonitor(ComponentName name, IBinder service) {
1234 mName = name;
1235 mService = service;
1236 }
1237
1238 public void binderDied() {
1239 death(mName, mService);
1240 }
1241
1242 final ComponentName mName;
1243 final IBinder mService;
1244 }
1245 }
1246}