blob: 7754244cae8e810aee5cdef1b91de087ee1baaa0 [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
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070019import android.content.BroadcastReceiver;
20import android.content.ComponentName;
21import android.content.Context;
22import android.content.IIntentReceiver;
23import android.content.Intent;
24import android.content.ServiceConnection;
25import android.content.pm.ApplicationInfo;
26import android.content.pm.IPackageManager;
27import android.content.pm.PackageManager;
28import android.content.res.AssetManager;
29import android.content.res.CompatibilityInfo;
30import android.content.res.Resources;
31import android.os.Bundle;
Calin Juravle2a727d72016-04-15 19:33:46 +010032import android.os.Environment;
Jeff Sharkey15447792015-11-05 16:18:51 -080033import android.os.FileUtils;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070034import android.os.Handler;
35import android.os.IBinder;
36import android.os.Process;
37import android.os.RemoteException;
Brad Fitzpatrick624d50f2010-11-09 14:25:12 -080038import android.os.StrictMode;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060039import android.os.SystemProperties;
Dianne Hackborn1ded0b12012-04-26 14:14:50 -070040import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070041import android.os.UserHandle;
Calin Juravle2a727d72016-04-15 19:33:46 +010042import android.system.Os;
43import android.system.OsConstants;
44import android.system.ErrnoException;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060045import android.text.TextUtils;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070046import android.util.AndroidRuntimeException;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060047import android.util.ArrayMap;
Adam Lesinski2cb761e2014-08-15 13:59:02 -070048import android.util.Log;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070049import android.util.Slog;
Adam Lesinskide898ff2014-01-29 18:20:45 -080050import android.util.SparseArray;
Jeff Browna492c3a2012-08-23 19:48:44 -070051import android.view.Display;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060052import android.view.DisplayAdjustments;
Jeff Sharkeyb9f36742015-04-08 21:02:14 -070053
Narayan Kamath7dba6eb2014-07-16 08:53:30 +010054import dalvik.system.VMRuntime;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070055
56import java.io.File;
Calin Juravle2a727d72016-04-15 19:33:46 +010057import java.io.FileDescriptor;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070058import java.io.IOException;
59import java.io.InputStream;
60import java.lang.ref.WeakReference;
Adam Lesinski1e4663852014-08-15 14:47:28 -070061import java.lang.reflect.InvocationTargetException;
62import java.lang.reflect.Method;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070063import java.net.URL;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070064import java.util.ArrayList;
65import java.util.Collections;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070066import java.util.Enumeration;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060067import java.util.List;
Narayan Kamath20531682014-07-14 13:18:43 +010068import java.util.Objects;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070069
Calin Juravle2a727d72016-04-15 19:33:46 +010070import libcore.io.IoUtils;
71
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070072final class IntentReceiverLeaked extends AndroidRuntimeException {
73 public IntentReceiverLeaked(String msg) {
74 super(msg);
75 }
76}
77
78final class ServiceConnectionLeaked extends AndroidRuntimeException {
79 public ServiceConnectionLeaked(String msg) {
80 super(msg);
81 }
82}
83
84/**
85 * Local state maintained about a currently loaded .apk.
86 * @hide
87 */
Dianne Hackborn5fd21692011-06-07 14:09:47 -070088public final class LoadedApk {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070089
Amith Yamasani742a6712011-05-04 14:49:28 -070090 private static final String TAG = "LoadedApk";
91
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070092 private final ActivityThread mActivityThread;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070093 final String mPackageName;
Todd Kennedy39bfee52016-02-24 10:28:21 -080094 private ApplicationInfo mApplicationInfo;
95 private String mAppDir;
96 private String mResDir;
97 private String[] mSplitAppDirs;
98 private String[] mSplitResDirs;
99 private String[] mOverlayDirs;
100 private String[] mSharedLibraries;
101 private String mDataDir;
102 private String mLibDir;
103 private File mDataDirFile;
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600104 private File mDeviceProtectedDataDirFile;
105 private File mCredentialProtectedDataDirFile;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700106 private final ClassLoader mBaseClassLoader;
107 private final boolean mSecurityViolation;
108 private final boolean mIncludeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700109 private final boolean mRegisterPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700110 private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800111 /** WARNING: This may change. Don't hold external references to it. */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700112 Resources mResources;
113 private ClassLoader mClassLoader;
114 private Application mApplication;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700115
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700116 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
117 = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
118 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
119 = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
120 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
121 = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
122 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
123 = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700124
125 int mClientCount = 0;
126
127 Application getApplication() {
128 return mApplication;
129 }
130
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700131 /**
132 * Create information about a new .apk
133 *
134 * NOTE: This constructor is called with ActivityThread's lock held,
135 * so MUST NOT call back out to the activity manager.
136 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700137 public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
Jeff Browndefd4a62014-03-10 21:24:37 -0700138 CompatibilityInfo compatInfo, ClassLoader baseLoader,
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700139 boolean securityViolation, boolean includeCode, boolean registerPackage) {
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100140
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700141 mActivityThread = activityThread;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800142 setApplicationInfo(aInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700143 mPackageName = aInfo.packageName;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700144 mBaseClassLoader = baseLoader;
145 mSecurityViolation = securityViolation;
146 mIncludeCode = includeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700147 mRegisterPackage = registerPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700148 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700149 }
150
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100151 private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) {
152 // If we're dealing with a multi-arch application that has both
153 // 32 and 64 bit shared libraries, we might need to choose the secondary
154 // depending on what the current runtime's instruction set is.
155 if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
156 final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
jgu214741cd92014-12-17 17:23:29 -0500157
158 // Get the instruction set that the libraries of secondary Abi is supported.
159 // In presence of a native bridge this might be different than the one secondary Abi used.
160 String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
161 final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
162 secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100163
164 // If the runtimeIsa is the same as the primary isa, then we do nothing.
165 // Everything will be set up correctly because info.nativeLibraryDir will
166 // correspond to the right ISA.
167 if (runtimeIsa.equals(secondaryIsa)) {
168 final ApplicationInfo modified = new ApplicationInfo(info);
169 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
Dmitriy Ivanove56b3f62015-06-05 22:00:13 -0700170 modified.primaryCpuAbi = modified.secondaryCpuAbi;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100171 return modified;
172 }
173 }
174
175 return info;
176 }
177
Jeff Browndefd4a62014-03-10 21:24:37 -0700178 /**
179 * Create information about the system package.
180 * Must call {@link #installSystemApplicationInfo} later.
181 */
182 LoadedApk(ActivityThread activityThread) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700183 mActivityThread = activityThread;
Jeff Browndefd4a62014-03-10 21:24:37 -0700184 mApplicationInfo = new ApplicationInfo();
185 mApplicationInfo.packageName = "android";
186 mPackageName = "android";
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700187 mAppDir = null;
188 mResDir = null;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700189 mSplitAppDirs = null;
190 mSplitResDirs = null;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100191 mOverlayDirs = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700192 mSharedLibraries = null;
193 mDataDir = null;
194 mDataDirFile = null;
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600195 mDeviceProtectedDataDirFile = null;
196 mCredentialProtectedDataDirFile = null;
Kenny Root85387d72010-08-26 10:13:11 -0700197 mLibDir = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700198 mBaseClassLoader = null;
199 mSecurityViolation = false;
200 mIncludeCode = true;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700201 mRegisterPackage = false;
Jeff Browndefd4a62014-03-10 21:24:37 -0700202 mClassLoader = ClassLoader.getSystemClassLoader();
203 mResources = Resources.getSystem();
204 }
205
206 /**
207 * Sets application info about the system package.
208 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100209 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
Jeff Browndefd4a62014-03-10 21:24:37 -0700210 assert info.packageName.equals("android");
211 mApplicationInfo = info;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100212 mClassLoader = classLoader;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700213 }
214
215 public String getPackageName() {
216 return mPackageName;
217 }
218
219 public ApplicationInfo getApplicationInfo() {
220 return mApplicationInfo;
221 }
222
Jeff Sharkey369f5092016-02-29 11:16:21 -0700223 public int getTargetSdkVersion() {
224 return mApplicationInfo.targetSdkVersion;
225 }
226
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700227 public boolean isSecurityViolation() {
228 return mSecurityViolation;
229 }
230
Craig Mautner48d0d182013-06-11 07:53:06 -0700231 public CompatibilityInfo getCompatibilityInfo() {
232 return mDisplayAdjustments.getCompatibilityInfo();
233 }
234
235 public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
236 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
237 }
238
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700239 /**
240 * Gets the array of shared libraries that are listed as
241 * used by the given package.
242 *
243 * @param packageName the name of the package (note: not its
244 * file name)
245 * @return null-ok; the array of shared libraries, each one
246 * a fully-qualified path
247 */
248 private static String[] getLibrariesFor(String packageName) {
249 ApplicationInfo ai = null;
250 try {
251 ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700252 PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700253 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700254 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700255 }
256
257 if (ai == null) {
258 return null;
259 }
260
261 return ai.sharedLibraryFiles;
262 }
263
Todd Kennedy39bfee52016-02-24 10:28:21 -0800264 public void updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths) {
265 setApplicationInfo(aInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700266
Todd Kennedy39bfee52016-02-24 10:28:21 -0800267 final List<String> newPaths = new ArrayList<>();
268 makePaths(mActivityThread, aInfo, newPaths, null /*libPaths*/);
269 final List<String> addedPaths = new ArrayList<>(newPaths.size());
270
271 if (oldPaths != null) {
272 for (String path : newPaths) {
273 final String apkName = path.substring(path.lastIndexOf(File.separator));
274 boolean match = false;
275 for (String oldPath : oldPaths) {
276 final String oldApkName = oldPath.substring(path.lastIndexOf(File.separator));
277 if (apkName.equals(oldApkName)) {
278 match = true;
279 break;
280 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700281 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800282 if (!match) {
283 addedPaths.add(path);
284 }
285 }
286 } else {
287 addedPaths.addAll(newPaths);
288 }
289 synchronized (this) {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700290 createOrUpdateClassLoaderLocked(addedPaths);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800291 if (mResources != null) {
Adam Lesinski082614c2016-03-04 14:33:47 -0800292 mResources = mActivityThread.getTopLevelResources(mResDir, mSplitResDirs,
Todd Kennedy39bfee52016-02-24 10:28:21 -0800293 mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
Adam Lesinski082614c2016-03-04 14:33:47 -0800294 this);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800295 }
296 }
297 }
298
299 private void setApplicationInfo(ApplicationInfo aInfo) {
300 final int myUid = Process.myUid();
301 aInfo = adjustNativeLibraryPaths(aInfo);
302 mApplicationInfo = aInfo;
303 mAppDir = aInfo.sourceDir;
304 mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
305 mSplitAppDirs = aInfo.splitSourceDirs;
306 mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
307 mOverlayDirs = aInfo.resourceDirs;
308 mSharedLibraries = aInfo.sharedLibraryFiles;
309 mDataDir = aInfo.dataDir;
310 mLibDir = aInfo.nativeLibraryDir;
311 mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600312 mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir);
313 mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800314 }
315
316 public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
317 List<String> outZipPaths, List<String> outLibPaths) {
318 final String appDir = aInfo.sourceDir;
319 final String[] splitAppDirs = aInfo.splitSourceDirs;
320 final String libDir = aInfo.nativeLibraryDir;
321 final String[] sharedLibraries = aInfo.sharedLibraryFiles;
322
323 outZipPaths.clear();
324 outZipPaths.add(appDir);
325 if (splitAppDirs != null) {
326 Collections.addAll(outZipPaths, splitAppDirs);
327 }
328
329 if (outLibPaths != null) {
330 outLibPaths.clear();
331 }
332
333 /*
334 * The following is a bit of a hack to inject
335 * instrumentation into the system: If the app
336 * being started matches one of the instrumentation names,
337 * then we combine both the "instrumentation" and
338 * "instrumented" app into the path, along with the
339 * concatenation of both apps' shared library lists.
340 */
341
342 String instrumentationPackageName = activityThread.mInstrumentationPackageName;
343 String instrumentationAppDir = activityThread.mInstrumentationAppDir;
344 String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
345 String instrumentationLibDir = activityThread.mInstrumentationLibDir;
346
347 String instrumentedAppDir = activityThread.mInstrumentedAppDir;
348 String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
349 String instrumentedLibDir = activityThread.mInstrumentedLibDir;
350 String[] instrumentationLibs = null;
351
352 if (appDir.equals(instrumentationAppDir)
353 || appDir.equals(instrumentedAppDir)) {
354 outZipPaths.clear();
355 outZipPaths.add(instrumentationAppDir);
356 if (instrumentationSplitAppDirs != null) {
357 Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
358 }
Jeff Haoc7b94822016-03-16 15:56:07 -0700359 if (!instrumentationAppDir.equals(instrumentedAppDir)) {
360 outZipPaths.add(instrumentedAppDir);
361 if (instrumentedSplitAppDirs != null) {
362 Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
363 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700364 }
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800365
Todd Kennedy39bfee52016-02-24 10:28:21 -0800366 if (outLibPaths != null) {
367 outLibPaths.add(instrumentationLibDir);
Jeff Haoc7b94822016-03-16 15:56:07 -0700368 if (!instrumentationLibDir.equals(instrumentedLibDir)) {
369 outLibPaths.add(instrumentedLibDir);
370 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800371 }
372
373 if (!instrumentedAppDir.equals(instrumentationAppDir)) {
374 instrumentationLibs = getLibrariesFor(instrumentationPackageName);
375 }
376 }
377
378 if (outLibPaths != null) {
379 if (outLibPaths.isEmpty()) {
380 outLibPaths.add(libDir);
381 }
382
383 // Add path to libraries in apk for current abi. Do this now because more entries
384 // will be added to zipPaths that shouldn't be part of the library path.
385 if (aInfo.primaryCpuAbi != null) {
Alex Light20ed24f2016-04-20 14:07:43 -0700386 // Add fake libs into the library search path if we target prior to N.
387 if (aInfo.targetSdkVersion <= 23) {
388 outLibPaths.add("/system/fake-libs" +
389 (VMRuntime.is64BitAbi(aInfo.primaryCpuAbi) ? "64" : ""));
390 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800391 for (String apk : outZipPaths) {
392 outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
393 }
394 }
395
396 if (aInfo.isSystemApp() && !aInfo.isUpdatedSystemApp()) {
397 // Add path to system libraries to libPaths;
398 // Access to system libs should be limited
399 // to bundled applications; this is why updated
400 // system apps are not included.
401 outLibPaths.add(System.getProperty("java.library.path"));
402 }
403 }
404
405 if (sharedLibraries != null) {
406 for (String lib : sharedLibraries) {
407 if (!outZipPaths.contains(lib)) {
408 outZipPaths.add(0, lib);
409 }
410 }
411 }
412
413 if (instrumentationLibs != null) {
414 for (String lib : instrumentationLibs) {
415 if (!outZipPaths.contains(lib)) {
416 outZipPaths.add(0, lib);
417 }
418 }
419 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800420 }
421
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700422 private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
423 if (mPackageName.equals("android")) {
Calin Juravle430ef452016-04-22 17:43:07 +0100424 // Note: This branch is taken for system server and we don't need to setup
425 // jit profiling support.
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700426 if (mClassLoader != null) {
427 // nothing to update
428 return;
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800429 }
430
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700431 if (mBaseClassLoader != null) {
432 mClassLoader = mBaseClassLoader;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800433 } else {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700434 mClassLoader = ClassLoader.getSystemClassLoader();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800435 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700436
437 return;
438 }
439
440 // Avoid the binder call when the package is the current application package.
441 // The activity manager will perform ensure that dexopt is performed before
442 // spinning up the process.
443 if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
444 VMRuntime.getRuntime().vmInstructionSet();
445 try {
Brian Carlstromca82e612016-04-19 23:16:08 -0700446 ActivityThread.getPackageManager().notifyPackageUse(mPackageName,
447 PackageManager.NOTIFY_PACKAGE_USE_CROSS_PACKAGE);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700448 } catch (RemoteException re) {
449 throw re.rethrowFromSystemServer();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800450 }
451 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700452
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700453 if (mRegisterPackage) {
454 try {
455 ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
456 } catch (RemoteException e) {
457 throw e.rethrowFromSystemServer();
458 }
459 }
460
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700461 // Lists for the elements of zip/code and native libraries.
462 //
463 // Both lists are usually not empty. We expect on average one APK for the zip component,
464 // but shared libraries and splits are not uncommon. We expect at least three elements
465 // for native libraries (app-based, system, vendor). As such, give both some breathing
466 // space and initialize to a small value (instead of incurring growth code).
467 final List<String> zipPaths = new ArrayList<>(10);
468 final List<String> libPaths = new ArrayList<>(10);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700469 makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
Narayan Kamath8995b002016-05-11 20:31:09 +0100470
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700471 final boolean isBundledApp = mApplicationInfo.isSystemApp()
472 && !mApplicationInfo.isUpdatedSystemApp();
Dimitry Ivanovbf3b5f72016-05-03 11:34:58 -0700473
Dimitry Ivanoveb96b002016-05-10 10:51:40 -0700474 String libraryPermittedPath = mDataDir;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700475 if (isBundledApp) {
476 // This is necessary to grant bundled apps access to
477 // libraries located in subdirectories of /system/lib
478 libraryPermittedPath += File.pathSeparator +
479 System.getProperty("java.library.path");
480 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700481
482 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
483
Narayan Kamath8995b002016-05-11 20:31:09 +0100484 // If we're not asked to include code, we construct a classloader that has
485 // no code path included. We still need to set up the library search paths
486 // and permitted path because NativeActivity relies on it (it attempts to
487 // call System.loadLibrary() on a classloader from a LoadedApk with
488 // mIncludeCode == false).
489 if (!mIncludeCode) {
490 if (mClassLoader == null) {
491 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
492 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
493 "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
494 librarySearchPath, libraryPermittedPath, mBaseClassLoader);
495 StrictMode.setThreadPolicy(oldPolicy);
496 }
497
498 return;
499 }
500
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700501 /*
Narayan Kamath8995b002016-05-11 20:31:09 +0100502 * With all the combination done (if necessary, actually create the java class
503 * loader and set up JIT profiling support if necessary.
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700504 *
505 * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils.
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700506 */
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700507 final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
508 TextUtils.join(File.pathSeparator, zipPaths);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700509
510 if (ActivityThread.localLOGV)
511 Slog.v(ActivityThread.TAG, "Class path: " + zip +
512 ", JNI path: " + librarySearchPath);
513
Calin Juravle430ef452016-04-22 17:43:07 +0100514 boolean needToSetupJitProfiles = false;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700515 if (mClassLoader == null) {
516 // Temporarily disable logging of disk reads on the Looper thread
517 // as this is early and necessary.
518 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
519
520 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
521 mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
522 libraryPermittedPath, mBaseClassLoader);
523
524 StrictMode.setThreadPolicy(oldPolicy);
Calin Juravle430ef452016-04-22 17:43:07 +0100525 // Setup the class loader paths for profiling.
526 needToSetupJitProfiles = true;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700527 }
528
529 if (addedPaths != null && addedPaths.size() > 0) {
530 final String add = TextUtils.join(File.pathSeparator, addedPaths);
531 ApplicationLoaders.getDefault().addPath(mClassLoader, add);
Calin Juravle430ef452016-04-22 17:43:07 +0100532 // Setup the new code paths for profiling.
533 needToSetupJitProfiles = true;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700534 }
Calin Juravle2a727d72016-04-15 19:33:46 +0100535
536 // Setup jit profile support.
Narayan Kamath2d4a2222016-04-25 19:16:56 +0100537 //
Calin Juravle2a727d72016-04-15 19:33:46 +0100538 // It is ok to call this multiple times if the application gets updated with new splits.
539 // The runtime only keeps track of unique code paths and can handle re-registration of
540 // the same code path. There's no need to pass `addedPaths` since any new code paths
541 // are already in `mApplicationInfo`.
Narayan Kamath2d4a2222016-04-25 19:16:56 +0100542 //
543 // It is NOT ok to call this function from the system_server (for any of the packages it
544 // loads code from) so we explicitly disallow it there.
545 if (needToSetupJitProfiles && !ActivityThread.isSystem()) {
Calin Juravle430ef452016-04-22 17:43:07 +0100546 setupJitProfileSupport();
Calin Juravle430ef452016-04-22 17:43:07 +0100547 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800548 }
549
550 public ClassLoader getClassLoader() {
551 synchronized (this) {
552 if (mClassLoader == null) {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700553 createOrUpdateClassLoaderLocked(null /*addedPaths*/);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800554 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700555 return mClassLoader;
556 }
557 }
558
Calin Juravle2a727d72016-04-15 19:33:46 +0100559 // Keep in sync with installd (frameworks/native/cmds/installd/commands.cpp).
560 private static File getPrimaryProfileFile(String packageName) {
561 File profileDir = Environment.getDataProfilesDePackageDirectory(
562 UserHandle.myUserId(), packageName);
563 return new File(profileDir, "primary.prof");
564 }
565
566 private void setupJitProfileSupport() {
567 if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
568 return;
569 }
Calin Juravle126f7802016-05-24 15:23:47 +0100570 // Only set up profile support if the loaded apk has the same uid as the
571 // current process.
572 // Currently, we do not support profiling across different apps.
573 // (e.g. application's uid might be different when the code is
574 // loaded by another app via createApplicationContext)
575 if (mApplicationInfo.uid != Process.myUid()) {
576 return;
577 }
578
Calin Juravle2a727d72016-04-15 19:33:46 +0100579 final List<String> codePaths = new ArrayList<>();
580 if ((mApplicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
581 codePaths.add(mApplicationInfo.sourceDir);
582 }
583 if (mApplicationInfo.splitSourceDirs != null) {
584 Collections.addAll(codePaths, mApplicationInfo.splitSourceDirs);
585 }
586
587 if (codePaths.isEmpty()) {
588 // If there are no code paths there's no need to setup a profile file and register with
589 // the runtime,
590 return;
591 }
592
593 final File profileFile = getPrimaryProfileFile(mPackageName);
Calin Juravle2a727d72016-04-15 19:33:46 +0100594 final File foreignDexProfilesFile =
595 Environment.getDataProfilesDeForeignDexDirectory(UserHandle.myUserId());
Calin Juravle126f7802016-05-24 15:23:47 +0100596
597 VMRuntime.registerAppInfo(profileFile.getPath(), mApplicationInfo.dataDir,
598 codePaths.toArray(new String[codePaths.size()]), foreignDexProfilesFile.getPath());
Calin Juravle2a727d72016-04-15 19:33:46 +0100599 }
600
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700601 /**
602 * Setup value for Thread.getContextClassLoader(). If the
603 * package will not run in in a VM with other packages, we set
604 * the Java context ClassLoader to the
605 * PackageInfo.getClassLoader value. However, if this VM can
606 * contain multiple packages, we intead set the Java context
607 * ClassLoader to a proxy that will warn about the use of Java
608 * context ClassLoaders and then fall through to use the
609 * system ClassLoader.
610 *
611 * <p> Note that this is similar to but not the same as the
612 * android.content.Context.getClassLoader(). While both
613 * context class loaders are typically set to the
614 * PathClassLoader used to load the package archive in the
615 * single application per VM case, a single Android process
616 * may contain several Contexts executing on one thread with
617 * their own logical ClassLoaders while the Java context
618 * ClassLoader is a thread local. This is why in the case when
619 * we have multiple packages per VM we do not set the Java
620 * context ClassLoader to an arbitrary but instead warn the
621 * user to set their own if we detect that they are using a
622 * Java library that expects it to be set.
623 */
624 private void initializeJavaContextClassLoader() {
625 IPackageManager pm = ActivityThread.getPackageManager();
626 android.content.pm.PackageInfo pi;
627 try {
Jeff Sharkeyc7bacab2016-02-09 15:56:11 -0700628 pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
629 UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700630 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700631 throw e.rethrowFromSystemServer();
Dianne Hackborn208d9372013-02-25 13:17:54 -0800632 }
633 if (pi == null) {
634 throw new IllegalStateException("Unable to get package info for "
635 + mPackageName + "; is package not installed?");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700636 }
637 /*
638 * Two possible indications that this package could be
639 * sharing its virtual machine with other packages:
640 *
641 * 1.) the sharedUserId attribute is set in the manifest,
642 * indicating a request to share a VM with other
643 * packages with the same sharedUserId.
644 *
645 * 2.) the application element of the manifest has an
646 * attribute specifying a non-default process name,
647 * indicating the desire to run in another packages VM.
648 */
649 boolean sharedUserIdSet = (pi.sharedUserId != null);
650 boolean processNameNotDefault =
651 (pi.applicationInfo != null &&
652 !mPackageName.equals(pi.applicationInfo.processName));
653 boolean sharable = (sharedUserIdSet || processNameNotDefault);
654 ClassLoader contextClassLoader =
655 (sharable)
656 ? new WarningContextClassLoader()
657 : mClassLoader;
658 Thread.currentThread().setContextClassLoader(contextClassLoader);
659 }
660
661 private static class WarningContextClassLoader extends ClassLoader {
662
663 private static boolean warned = false;
664
665 private void warn(String methodName) {
666 if (warned) {
667 return;
668 }
669 warned = true;
670 Thread.currentThread().setContextClassLoader(getParent());
671 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
672 "The class loader returned by " +
673 "Thread.getContextClassLoader() may fail for processes " +
674 "that host multiple applications. You should explicitly " +
675 "specify a context class loader. For example: " +
676 "Thread.setContextClassLoader(getClass().getClassLoader());");
677 }
678
679 @Override public URL getResource(String resName) {
680 warn("getResource");
681 return getParent().getResource(resName);
682 }
683
684 @Override public Enumeration<URL> getResources(String resName) throws IOException {
685 warn("getResources");
686 return getParent().getResources(resName);
687 }
688
689 @Override public InputStream getResourceAsStream(String resName) {
690 warn("getResourceAsStream");
691 return getParent().getResourceAsStream(resName);
692 }
693
694 @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
695 warn("loadClass");
696 return getParent().loadClass(className);
697 }
698
699 @Override public void setClassAssertionStatus(String cname, boolean enable) {
700 warn("setClassAssertionStatus");
701 getParent().setClassAssertionStatus(cname, enable);
702 }
703
704 @Override public void setPackageAssertionStatus(String pname, boolean enable) {
705 warn("setPackageAssertionStatus");
706 getParent().setPackageAssertionStatus(pname, enable);
707 }
708
709 @Override public void setDefaultAssertionStatus(boolean enable) {
710 warn("setDefaultAssertionStatus");
711 getParent().setDefaultAssertionStatus(enable);
712 }
713
714 @Override public void clearAssertionStatus() {
715 warn("clearAssertionStatus");
716 getParent().clearAssertionStatus();
717 }
718 }
719
720 public String getAppDir() {
721 return mAppDir;
722 }
723
Brian Carlstromd893a892012-04-01 21:30:26 -0700724 public String getLibDir() {
725 return mLibDir;
726 }
727
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700728 public String getResDir() {
729 return mResDir;
730 }
731
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700732 public String[] getSplitAppDirs() {
733 return mSplitAppDirs;
734 }
735
736 public String[] getSplitResDirs() {
737 return mSplitResDirs;
738 }
739
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100740 public String[] getOverlayDirs() {
741 return mOverlayDirs;
742 }
743
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700744 public String getDataDir() {
745 return mDataDir;
746 }
747
748 public File getDataDirFile() {
749 return mDataDirFile;
750 }
751
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600752 public File getDeviceProtectedDataDirFile() {
753 return mDeviceProtectedDataDirFile;
Jeff Sharkey15447792015-11-05 16:18:51 -0800754 }
755
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600756 public File getCredentialProtectedDataDirFile() {
757 return mCredentialProtectedDataDirFile;
Jeff Sharkey15447792015-11-05 16:18:51 -0800758 }
759
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700760 public AssetManager getAssets(ActivityThread mainThread) {
761 return getResources(mainThread).getAssets();
762 }
763
764 public Resources getResources(ActivityThread mainThread) {
765 if (mResources == null) {
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700766 mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
Adam Lesinski082614c2016-03-04 14:33:47 -0800767 mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700768 }
769 return mResources;
770 }
771
772 public Application makeApplication(boolean forceDefaultAppClass,
773 Instrumentation instrumentation) {
774 if (mApplication != null) {
775 return mApplication;
776 }
777
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700778 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
779
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700780 Application app = null;
781
782 String appClass = mApplicationInfo.className;
783 if (forceDefaultAppClass || (appClass == null)) {
784 appClass = "android.app.Application";
785 }
786
787 try {
788 java.lang.ClassLoader cl = getClassLoader();
Narayan Kamath8091edb2014-10-15 11:38:44 +0100789 if (!mPackageName.equals("android")) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700790 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
791 "initializeJavaContextClassLoader");
Narayan Kamath8091edb2014-10-15 11:38:44 +0100792 initializeJavaContextClassLoader();
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700793 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Narayan Kamath8091edb2014-10-15 11:38:44 +0100794 }
Jeff Browndefd4a62014-03-10 21:24:37 -0700795 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700796 app = mActivityThread.mInstrumentation.newApplication(
797 cl, appClass, appContext);
798 appContext.setOuterContext(app);
799 } catch (Exception e) {
800 if (!mActivityThread.mInstrumentation.onException(app, e)) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700801 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700802 throw new RuntimeException(
803 "Unable to instantiate application " + appClass
804 + ": " + e.toString(), e);
805 }
806 }
807 mActivityThread.mAllApplications.add(app);
808 mApplication = app;
809
810 if (instrumentation != null) {
811 try {
812 instrumentation.callApplicationOnCreate(app);
813 } catch (Exception e) {
814 if (!instrumentation.onException(app, e)) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700815 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700816 throw new RuntimeException(
817 "Unable to create application " + app.getClass().getName()
818 + ": " + e.toString(), e);
819 }
820 }
821 }
Adam Lesinskide898ff2014-01-29 18:20:45 -0800822
823 // Rewrite the R 'constants' for all library apks.
824 SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
825 .getAssignedPackageIdentifiers();
826 final int N = packageIdentifiers.size();
827 for (int i = 0; i < N; i++) {
828 final int id = packageIdentifiers.keyAt(i);
829 if (id == 0x01 || id == 0x7f) {
830 continue;
831 }
832
833 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
834 }
835
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700836 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
837
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700838 return app;
839 }
840
Adam Lesinskide898ff2014-01-29 18:20:45 -0800841 private void rewriteRValues(ClassLoader cl, String packageName, int id) {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700842 final Class<?> rClazz;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800843 try {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700844 rClazz = cl.loadClass(packageName + ".R");
845 } catch (ClassNotFoundException e) {
846 // This is not necessarily an error, as some packages do not ship with resources
847 // (or they do not need rewriting).
Adam Lesinski1e4663852014-08-15 14:47:28 -0700848 Log.i(TAG, "No resource references to update in package " + packageName);
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700849 return;
850 }
851
Adam Lesinski1e4663852014-08-15 14:47:28 -0700852 final Method callback;
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700853 try {
Adam Lesinski1e4663852014-08-15 14:47:28 -0700854 callback = rClazz.getMethod("onResourcesLoaded", int.class);
855 } catch (NoSuchMethodException e) {
856 // No rewriting to be done.
857 return;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800858 }
Adam Lesinski1e4663852014-08-15 14:47:28 -0700859
860 Throwable cause;
861 try {
862 callback.invoke(null, id);
863 return;
864 } catch (IllegalAccessException e) {
865 cause = e;
866 } catch (InvocationTargetException e) {
867 cause = e.getCause();
868 }
869
870 throw new RuntimeException("Failed to rewrite resource references for " + packageName,
871 cause);
Adam Lesinskide898ff2014-01-29 18:20:45 -0800872 }
873
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700874 public void removeContextRegistrations(Context context,
875 String who, String what) {
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800876 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800877 synchronized (mReceivers) {
878 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
879 mReceivers.remove(context);
880 if (rmap != null) {
881 for (int i = 0; i < rmap.size(); i++) {
882 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
883 IntentReceiverLeaked leak = new IntentReceiverLeaked(
884 what + " " + who + " has leaked IntentReceiver "
885 + rd.getIntentReceiver() + " that was " +
886 "originally registered here. Are you missing a " +
887 "call to unregisterReceiver()?");
888 leak.setStackTrace(rd.getLocation().getStackTrace());
889 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
890 if (reportRegistrationLeaks) {
891 StrictMode.onIntentReceiverLeaked(leak);
892 }
893 try {
894 ActivityManagerNative.getDefault().unregisterReceiver(
895 rd.getIIntentReceiver());
896 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700897 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800898 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700899 }
900 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800901 mUnregisteredReceivers.remove(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700902 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800903
904 synchronized (mServices) {
905 //Slog.i(TAG, "Receiver registrations: " + mReceivers);
906 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
907 mServices.remove(context);
908 if (smap != null) {
909 for (int i = 0; i < smap.size(); i++) {
910 LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
911 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
912 what + " " + who + " has leaked ServiceConnection "
913 + sd.getServiceConnection() + " that was originally bound here");
914 leak.setStackTrace(sd.getLocation().getStackTrace());
915 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
916 if (reportRegistrationLeaks) {
917 StrictMode.onServiceConnectionLeaked(leak);
918 }
919 try {
920 ActivityManagerNative.getDefault().unbindService(
921 sd.getIServiceConnection());
922 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700923 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800924 }
925 sd.doForget();
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800926 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700927 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800928 mUnboundServices.remove(context);
929 //Slog.i(TAG, "Service registrations: " + mServices);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700930 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700931 }
932
933 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
934 Context context, Handler handler,
935 Instrumentation instrumentation, boolean registered) {
936 synchronized (mReceivers) {
937 LoadedApk.ReceiverDispatcher rd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700938 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700939 if (registered) {
940 map = mReceivers.get(context);
941 if (map != null) {
942 rd = map.get(r);
943 }
944 }
945 if (rd == null) {
946 rd = new ReceiverDispatcher(r, context, handler,
947 instrumentation, registered);
948 if (registered) {
949 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700950 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700951 mReceivers.put(context, map);
952 }
953 map.put(r, rd);
954 }
955 } else {
956 rd.validate(context, handler);
957 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800958 rd.mForgotten = false;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700959 return rd.getIIntentReceiver();
960 }
961 }
962
963 public IIntentReceiver forgetReceiverDispatcher(Context context,
964 BroadcastReceiver r) {
965 synchronized (mReceivers) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700966 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700967 LoadedApk.ReceiverDispatcher rd = null;
968 if (map != null) {
969 rd = map.get(r);
970 if (rd != null) {
971 map.remove(r);
972 if (map.size() == 0) {
973 mReceivers.remove(context);
974 }
975 if (r.getDebugUnregister()) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700976 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700977 = mUnregisteredReceivers.get(context);
978 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700979 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700980 mUnregisteredReceivers.put(context, holder);
981 }
982 RuntimeException ex = new IllegalArgumentException(
983 "Originally unregistered here:");
984 ex.fillInStackTrace();
985 rd.setUnregisterLocation(ex);
986 holder.put(r, rd);
987 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800988 rd.mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700989 return rd.getIIntentReceiver();
990 }
991 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700992 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700993 = mUnregisteredReceivers.get(context);
994 if (holder != null) {
995 rd = holder.get(r);
996 if (rd != null) {
997 RuntimeException ex = rd.getUnregisterLocation();
998 throw new IllegalArgumentException(
999 "Unregistering Receiver " + r
1000 + " that was already unregistered", ex);
1001 }
1002 }
1003 if (context == null) {
1004 throw new IllegalStateException("Unbinding Receiver " + r
1005 + " from Context that is no longer in use: " + context);
1006 } else {
1007 throw new IllegalArgumentException("Receiver not registered: " + r);
1008 }
1009
1010 }
1011 }
1012
1013 static final class ReceiverDispatcher {
1014
1015 final static class InnerReceiver extends IIntentReceiver.Stub {
1016 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
1017 final LoadedApk.ReceiverDispatcher mStrongRef;
1018
1019 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
1020 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
1021 mStrongRef = strong ? rd : null;
1022 }
Jeff Sharkeyd136e512016-03-09 22:30:56 -07001023
1024 @Override
Dianne Hackborn20e80982012-08-31 19:00:44 -07001025 public void performReceive(Intent intent, int resultCode, String data,
1026 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn26756162016-05-17 13:40:44 -07001027 final LoadedApk.ReceiverDispatcher rd;
1028 if (intent == null) {
1029 Log.wtf(TAG, "Null intent received");
1030 rd = null;
1031 } else {
1032 rd = mDispatcher.get();
1033 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001034 if (ActivityThread.DEBUG_BROADCAST) {
1035 int seq = intent.getIntExtra("seq", -1);
Dianne Hackborn26756162016-05-17 13:40:44 -07001036 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
1037 + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001038 }
1039 if (rd != null) {
1040 rd.performReceive(intent, resultCode, data, extras,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001041 ordered, sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001042 } else {
1043 // The activity manager dispatched a broadcast to a registered
1044 // receiver in this process, but before it could be delivered the
1045 // receiver was unregistered. Acknowledge the broadcast on its
1046 // behalf so that the system's broadcast sequence can continue.
1047 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1048 "Finishing broadcast to unregistered receiver");
1049 IActivityManager mgr = ActivityManagerNative.getDefault();
1050 try {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001051 if (extras != null) {
1052 extras.setAllowFds(false);
1053 }
riddle_hsu1f5ac4d2015-01-03 15:38:21 +08001054 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001055 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001056 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001057 }
1058 }
1059 }
1060 }
1061
1062 final IIntentReceiver.Stub mIIntentReceiver;
1063 final BroadcastReceiver mReceiver;
1064 final Context mContext;
1065 final Handler mActivityThread;
1066 final Instrumentation mInstrumentation;
1067 final boolean mRegistered;
1068 final IntentReceiverLeaked mLocation;
1069 RuntimeException mUnregisterLocation;
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -08001070 boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001071
Dianne Hackborne829fef2010-10-26 17:44:01 -07001072 final class Args extends BroadcastReceiver.PendingResult implements Runnable {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001073 private Intent mCurIntent;
Dianne Hackborne829fef2010-10-26 17:44:01 -07001074 private final boolean mOrdered;
Dianne Hackborn17c77532016-06-22 16:49:14 -07001075 private boolean mDispatched;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001076
Dianne Hackborne829fef2010-10-26 17:44:01 -07001077 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001078 boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborne829fef2010-10-26 17:44:01 -07001079 super(resultCode, resultData, resultExtras,
riddle_hsu1f5ac4d2015-01-03 15:38:21 +08001080 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
1081 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
Dianne Hackborne829fef2010-10-26 17:44:01 -07001082 mCurIntent = intent;
1083 mOrdered = ordered;
1084 }
1085
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001086 public void run() {
Dianne Hackborne829fef2010-10-26 17:44:01 -07001087 final BroadcastReceiver receiver = mReceiver;
1088 final boolean ordered = mOrdered;
1089
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001090 if (ActivityThread.DEBUG_BROADCAST) {
1091 int seq = mCurIntent.getIntExtra("seq", -1);
1092 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
1093 + " seq=" + seq + " to " + mReceiver);
1094 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
Dianne Hackborne829fef2010-10-26 17:44:01 -07001095 + " mOrderedHint=" + ordered);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001096 }
1097
Dianne Hackborne829fef2010-10-26 17:44:01 -07001098 final IActivityManager mgr = ActivityManagerNative.getDefault();
1099 final Intent intent = mCurIntent;
Dianne Hackborn17c77532016-06-22 16:49:14 -07001100 if (intent == null) {
1101 Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
1102 }
1103
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001104 mCurIntent = null;
Dianne Hackborn17c77532016-06-22 16:49:14 -07001105 mDispatched = true;
1106 if (receiver == null || intent == null || mForgotten) {
Dianne Hackborne829fef2010-10-26 17:44:01 -07001107 if (mRegistered && ordered) {
1108 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1109 "Finishing null broadcast to " + mReceiver);
1110 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001111 }
1112 return;
1113 }
1114
Dianne Hackborn1ded0b12012-04-26 14:14:50 -07001115 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001116 try {
1117 ClassLoader cl = mReceiver.getClass().getClassLoader();
1118 intent.setExtrasClassLoader(cl);
Jeff Sharkeyd136e512016-03-09 22:30:56 -07001119 intent.prepareToEnterProcess();
Dianne Hackborne829fef2010-10-26 17:44:01 -07001120 setExtrasClassLoader(cl);
1121 receiver.setPendingResult(this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001122 receiver.onReceive(mContext, intent);
1123 } catch (Exception e) {
Dianne Hackborne829fef2010-10-26 17:44:01 -07001124 if (mRegistered && ordered) {
1125 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1126 "Finishing failed broadcast to " + mReceiver);
1127 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001128 }
1129 if (mInstrumentation == null ||
1130 !mInstrumentation.onException(mReceiver, e)) {
Dianne Hackborn1ded0b12012-04-26 14:14:50 -07001131 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001132 throw new RuntimeException(
1133 "Error receiving broadcast " + intent
1134 + " in " + mReceiver, e);
1135 }
1136 }
Dianne Hackborne829fef2010-10-26 17:44:01 -07001137
1138 if (receiver.getPendingResult() != null) {
1139 finish();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001140 }
Dianne Hackborn1ded0b12012-04-26 14:14:50 -07001141 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001142 }
1143 }
1144
1145 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
1146 Handler activityThread, Instrumentation instrumentation,
1147 boolean registered) {
1148 if (activityThread == null) {
1149 throw new NullPointerException("Handler must not be null");
1150 }
1151
1152 mIIntentReceiver = new InnerReceiver(this, !registered);
1153 mReceiver = receiver;
1154 mContext = context;
1155 mActivityThread = activityThread;
1156 mInstrumentation = instrumentation;
1157 mRegistered = registered;
1158 mLocation = new IntentReceiverLeaked(null);
1159 mLocation.fillInStackTrace();
1160 }
1161
1162 void validate(Context context, Handler activityThread) {
1163 if (mContext != context) {
1164 throw new IllegalStateException(
1165 "Receiver " + mReceiver +
1166 " registered with differing Context (was " +
1167 mContext + " now " + context + ")");
1168 }
1169 if (mActivityThread != activityThread) {
1170 throw new IllegalStateException(
1171 "Receiver " + mReceiver +
1172 " registered with differing handler (was " +
1173 mActivityThread + " now " + activityThread + ")");
1174 }
1175 }
1176
1177 IntentReceiverLeaked getLocation() {
1178 return mLocation;
1179 }
1180
1181 BroadcastReceiver getIntentReceiver() {
1182 return mReceiver;
1183 }
1184
1185 IIntentReceiver getIIntentReceiver() {
1186 return mIIntentReceiver;
1187 }
1188
1189 void setUnregisterLocation(RuntimeException ex) {
1190 mUnregisterLocation = ex;
1191 }
1192
1193 RuntimeException getUnregisterLocation() {
1194 return mUnregisterLocation;
1195 }
1196
Dianne Hackborn20e80982012-08-31 19:00:44 -07001197 public void performReceive(Intent intent, int resultCode, String data,
1198 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn41bfaf82016-06-08 16:33:29 -07001199 final Args args = new Args(intent, resultCode, data, extras, ordered,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001200 sticky, sendingUser);
Dianne Hackborn41bfaf82016-06-08 16:33:29 -07001201 if (intent == null) {
1202 Log.wtf(TAG, "Null intent received");
1203 } else {
1204 if (ActivityThread.DEBUG_BROADCAST) {
1205 int seq = intent.getIntExtra("seq", -1);
1206 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
1207 + " seq=" + seq + " to " + mReceiver);
1208 }
1209 }
1210 if (intent == null || !mActivityThread.post(args)) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001211 if (mRegistered && ordered) {
1212 IActivityManager mgr = ActivityManagerNative.getDefault();
Dianne Hackborne829fef2010-10-26 17:44:01 -07001213 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1214 "Finishing sync broadcast to " + mReceiver);
1215 args.sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001216 }
1217 }
1218 }
1219
1220 }
1221
1222 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1223 Context context, Handler handler, int flags) {
1224 synchronized (mServices) {
1225 LoadedApk.ServiceDispatcher sd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001226 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001227 if (map != null) {
1228 sd = map.get(c);
1229 }
1230 if (sd == null) {
1231 sd = new ServiceDispatcher(c, context, handler, flags);
1232 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001233 map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001234 mServices.put(context, map);
1235 }
1236 map.put(c, sd);
1237 } else {
1238 sd.validate(context, handler);
1239 }
1240 return sd.getIServiceConnection();
1241 }
1242 }
1243
1244 public final IServiceConnection forgetServiceDispatcher(Context context,
1245 ServiceConnection c) {
1246 synchronized (mServices) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001247 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001248 = mServices.get(context);
1249 LoadedApk.ServiceDispatcher sd = null;
1250 if (map != null) {
1251 sd = map.get(c);
1252 if (sd != null) {
1253 map.remove(c);
1254 sd.doForget();
1255 if (map.size() == 0) {
1256 mServices.remove(context);
1257 }
1258 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001259 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001260 = mUnboundServices.get(context);
1261 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001262 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001263 mUnboundServices.put(context, holder);
1264 }
1265 RuntimeException ex = new IllegalArgumentException(
1266 "Originally unbound here:");
1267 ex.fillInStackTrace();
1268 sd.setUnbindLocation(ex);
1269 holder.put(c, sd);
1270 }
1271 return sd.getIServiceConnection();
1272 }
1273 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001274 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001275 = mUnboundServices.get(context);
1276 if (holder != null) {
1277 sd = holder.get(c);
1278 if (sd != null) {
1279 RuntimeException ex = sd.getUnbindLocation();
1280 throw new IllegalArgumentException(
1281 "Unbinding Service " + c
1282 + " that was already unbound", ex);
1283 }
1284 }
1285 if (context == null) {
1286 throw new IllegalStateException("Unbinding Service " + c
1287 + " from Context that is no longer in use: " + context);
1288 } else {
1289 throw new IllegalArgumentException("Service not registered: " + c);
1290 }
1291 }
1292 }
1293
1294 static final class ServiceDispatcher {
1295 private final ServiceDispatcher.InnerConnection mIServiceConnection;
1296 private final ServiceConnection mConnection;
1297 private final Context mContext;
1298 private final Handler mActivityThread;
1299 private final ServiceConnectionLeaked mLocation;
1300 private final int mFlags;
1301
1302 private RuntimeException mUnbindLocation;
1303
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001304 private boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001305
1306 private static class ConnectionInfo {
1307 IBinder binder;
1308 IBinder.DeathRecipient deathMonitor;
1309 }
1310
1311 private static class InnerConnection extends IServiceConnection.Stub {
1312 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1313
1314 InnerConnection(LoadedApk.ServiceDispatcher sd) {
1315 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1316 }
1317
1318 public void connected(ComponentName name, IBinder service) throws RemoteException {
1319 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1320 if (sd != null) {
1321 sd.connected(name, service);
1322 }
1323 }
1324 }
1325
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001326 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1327 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001328
1329 ServiceDispatcher(ServiceConnection conn,
1330 Context context, Handler activityThread, int flags) {
1331 mIServiceConnection = new InnerConnection(this);
1332 mConnection = conn;
1333 mContext = context;
1334 mActivityThread = activityThread;
1335 mLocation = new ServiceConnectionLeaked(null);
1336 mLocation.fillInStackTrace();
1337 mFlags = flags;
1338 }
1339
1340 void validate(Context context, Handler activityThread) {
1341 if (mContext != context) {
1342 throw new RuntimeException(
1343 "ServiceConnection " + mConnection +
1344 " registered with differing Context (was " +
1345 mContext + " now " + context + ")");
1346 }
1347 if (mActivityThread != activityThread) {
1348 throw new RuntimeException(
1349 "ServiceConnection " + mConnection +
1350 " registered with differing handler (was " +
1351 mActivityThread + " now " + activityThread + ")");
1352 }
1353 }
1354
1355 void doForget() {
1356 synchronized(this) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001357 for (int i=0; i<mActiveConnections.size(); i++) {
1358 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001359 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1360 }
1361 mActiveConnections.clear();
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001362 mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001363 }
1364 }
1365
1366 ServiceConnectionLeaked getLocation() {
1367 return mLocation;
1368 }
1369
1370 ServiceConnection getServiceConnection() {
1371 return mConnection;
1372 }
1373
1374 IServiceConnection getIServiceConnection() {
1375 return mIServiceConnection;
1376 }
1377
1378 int getFlags() {
1379 return mFlags;
1380 }
1381
1382 void setUnbindLocation(RuntimeException ex) {
1383 mUnbindLocation = ex;
1384 }
1385
1386 RuntimeException getUnbindLocation() {
1387 return mUnbindLocation;
1388 }
1389
1390 public void connected(ComponentName name, IBinder service) {
1391 if (mActivityThread != null) {
1392 mActivityThread.post(new RunConnection(name, service, 0));
1393 } else {
1394 doConnected(name, service);
1395 }
1396 }
1397
1398 public void death(ComponentName name, IBinder service) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001399 if (mActivityThread != null) {
1400 mActivityThread.post(new RunConnection(name, service, 1));
1401 } else {
1402 doDeath(name, service);
1403 }
1404 }
1405
1406 public void doConnected(ComponentName name, IBinder service) {
1407 ServiceDispatcher.ConnectionInfo old;
1408 ServiceDispatcher.ConnectionInfo info;
1409
1410 synchronized (this) {
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001411 if (mForgotten) {
1412 // We unbound before receiving the connection; ignore
1413 // any connection received.
1414 return;
1415 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001416 old = mActiveConnections.get(name);
1417 if (old != null && old.binder == service) {
1418 // Huh, already have this one. Oh well!
1419 return;
1420 }
1421
1422 if (service != null) {
1423 // A new service is being connected... set it all up.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001424 info = new ConnectionInfo();
1425 info.binder = service;
1426 info.deathMonitor = new DeathMonitor(name, service);
1427 try {
1428 service.linkToDeath(info.deathMonitor, 0);
1429 mActiveConnections.put(name, info);
1430 } catch (RemoteException e) {
1431 // This service was dead before we got it... just
1432 // don't do anything with it.
1433 mActiveConnections.remove(name);
1434 return;
1435 }
1436
1437 } else {
1438 // The named service is being disconnected... clean up.
1439 mActiveConnections.remove(name);
1440 }
1441
1442 if (old != null) {
1443 old.binder.unlinkToDeath(old.deathMonitor, 0);
1444 }
1445 }
1446
Adrian Roosa9b43182016-07-21 13:20:38 -07001447 // If there was an old service, it is now disconnected.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001448 if (old != null) {
1449 mConnection.onServiceDisconnected(name);
1450 }
1451 // If there is a new service, it is now connected.
1452 if (service != null) {
1453 mConnection.onServiceConnected(name, service);
1454 }
1455 }
1456
1457 public void doDeath(ComponentName name, IBinder service) {
Adrian Roosa9b43182016-07-21 13:20:38 -07001458 synchronized (this) {
1459 ConnectionInfo old = mActiveConnections.get(name);
1460 if (old == null || old.binder != service) {
1461 // Death for someone different than who we last
1462 // reported... just ignore it.
1463 return;
1464 }
1465 mActiveConnections.remove(name);
1466 old.binder.unlinkToDeath(old.deathMonitor, 0);
1467 }
1468
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001469 mConnection.onServiceDisconnected(name);
1470 }
1471
1472 private final class RunConnection implements Runnable {
1473 RunConnection(ComponentName name, IBinder service, int command) {
1474 mName = name;
1475 mService = service;
1476 mCommand = command;
1477 }
1478
1479 public void run() {
1480 if (mCommand == 0) {
1481 doConnected(mName, mService);
1482 } else if (mCommand == 1) {
1483 doDeath(mName, mService);
1484 }
1485 }
1486
1487 final ComponentName mName;
1488 final IBinder mService;
1489 final int mCommand;
1490 }
1491
1492 private final class DeathMonitor implements IBinder.DeathRecipient
1493 {
1494 DeathMonitor(ComponentName name, IBinder service) {
1495 mName = name;
1496 mService = service;
1497 }
1498
1499 public void binderDied() {
1500 death(mName, mService);
1501 }
1502
1503 final ComponentName mName;
1504 final IBinder mService;
1505 }
1506 }
1507}