blob: afe9651d82f529c466fdfcc33a73946498ee0e7c [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
Calin Juravle9abb5012016-11-23 19:50:58 +000054import dalvik.system.BaseDexClassLoader;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +010055import dalvik.system.VMRuntime;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070056
57import java.io.File;
Calin Juravle2a727d72016-04-15 19:33:46 +010058import java.io.FileDescriptor;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070059import java.io.IOException;
60import java.io.InputStream;
61import java.lang.ref.WeakReference;
Adam Lesinski1e4663852014-08-15 14:47:28 -070062import java.lang.reflect.InvocationTargetException;
63import java.lang.reflect.Method;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070064import java.net.URL;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070065import java.util.ArrayList;
66import java.util.Collections;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070067import java.util.Enumeration;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060068import java.util.List;
Narayan Kamath20531682014-07-14 13:18:43 +010069import java.util.Objects;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070070
Calin Juravle2a727d72016-04-15 19:33:46 +010071import libcore.io.IoUtils;
72
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070073final class IntentReceiverLeaked extends AndroidRuntimeException {
74 public IntentReceiverLeaked(String msg) {
75 super(msg);
76 }
77}
78
79final class ServiceConnectionLeaked extends AndroidRuntimeException {
80 public ServiceConnectionLeaked(String msg) {
81 super(msg);
82 }
83}
84
85/**
86 * Local state maintained about a currently loaded .apk.
87 * @hide
88 */
Dianne Hackborn5fd21692011-06-07 14:09:47 -070089public final class LoadedApk {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070090
Amith Yamasani742a6712011-05-04 14:49:28 -070091 private static final String TAG = "LoadedApk";
92
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070093 private final ActivityThread mActivityThread;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070094 final String mPackageName;
Todd Kennedy39bfee52016-02-24 10:28:21 -080095 private ApplicationInfo mApplicationInfo;
96 private String mAppDir;
97 private String mResDir;
98 private String[] mSplitAppDirs;
99 private String[] mSplitResDirs;
100 private String[] mOverlayDirs;
101 private String[] mSharedLibraries;
102 private String mDataDir;
103 private String mLibDir;
104 private File mDataDirFile;
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600105 private File mDeviceProtectedDataDirFile;
106 private File mCredentialProtectedDataDirFile;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700107 private final ClassLoader mBaseClassLoader;
108 private final boolean mSecurityViolation;
109 private final boolean mIncludeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700110 private final boolean mRegisterPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700111 private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800112 /** WARNING: This may change. Don't hold external references to it. */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700113 Resources mResources;
114 private ClassLoader mClassLoader;
115 private Application mApplication;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700116
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700117 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
118 = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
119 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
120 = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
121 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
122 = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
123 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
124 = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700125
126 int mClientCount = 0;
127
128 Application getApplication() {
129 return mApplication;
130 }
131
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700132 /**
133 * Create information about a new .apk
134 *
135 * NOTE: This constructor is called with ActivityThread's lock held,
136 * so MUST NOT call back out to the activity manager.
137 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700138 public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
Jeff Browndefd4a62014-03-10 21:24:37 -0700139 CompatibilityInfo compatInfo, ClassLoader baseLoader,
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700140 boolean securityViolation, boolean includeCode, boolean registerPackage) {
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100141
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700142 mActivityThread = activityThread;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800143 setApplicationInfo(aInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700144 mPackageName = aInfo.packageName;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700145 mBaseClassLoader = baseLoader;
146 mSecurityViolation = securityViolation;
147 mIncludeCode = includeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700148 mRegisterPackage = registerPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700149 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700150 }
151
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100152 private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) {
153 // If we're dealing with a multi-arch application that has both
154 // 32 and 64 bit shared libraries, we might need to choose the secondary
155 // depending on what the current runtime's instruction set is.
156 if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
157 final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
jgu214741cd92014-12-17 17:23:29 -0500158
159 // Get the instruction set that the libraries of secondary Abi is supported.
160 // In presence of a native bridge this might be different than the one secondary Abi used.
161 String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
162 final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
163 secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100164
165 // If the runtimeIsa is the same as the primary isa, then we do nothing.
166 // Everything will be set up correctly because info.nativeLibraryDir will
167 // correspond to the right ISA.
168 if (runtimeIsa.equals(secondaryIsa)) {
169 final ApplicationInfo modified = new ApplicationInfo(info);
170 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
Dmitriy Ivanove56b3f62015-06-05 22:00:13 -0700171 modified.primaryCpuAbi = modified.secondaryCpuAbi;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100172 return modified;
173 }
174 }
175
176 return info;
177 }
178
Jeff Browndefd4a62014-03-10 21:24:37 -0700179 /**
180 * Create information about the system package.
181 * Must call {@link #installSystemApplicationInfo} later.
182 */
183 LoadedApk(ActivityThread activityThread) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700184 mActivityThread = activityThread;
Jeff Browndefd4a62014-03-10 21:24:37 -0700185 mApplicationInfo = new ApplicationInfo();
186 mApplicationInfo.packageName = "android";
187 mPackageName = "android";
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700188 mAppDir = null;
189 mResDir = null;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700190 mSplitAppDirs = null;
191 mSplitResDirs = null;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100192 mOverlayDirs = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700193 mSharedLibraries = null;
194 mDataDir = null;
195 mDataDirFile = null;
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600196 mDeviceProtectedDataDirFile = null;
197 mCredentialProtectedDataDirFile = null;
Kenny Root85387d72010-08-26 10:13:11 -0700198 mLibDir = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700199 mBaseClassLoader = null;
200 mSecurityViolation = false;
201 mIncludeCode = true;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700202 mRegisterPackage = false;
Jeff Browndefd4a62014-03-10 21:24:37 -0700203 mClassLoader = ClassLoader.getSystemClassLoader();
204 mResources = Resources.getSystem();
205 }
206
207 /**
208 * Sets application info about the system package.
209 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100210 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
Jeff Browndefd4a62014-03-10 21:24:37 -0700211 assert info.packageName.equals("android");
212 mApplicationInfo = info;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100213 mClassLoader = classLoader;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700214 }
215
216 public String getPackageName() {
217 return mPackageName;
218 }
219
220 public ApplicationInfo getApplicationInfo() {
221 return mApplicationInfo;
222 }
223
Jeff Sharkey369f5092016-02-29 11:16:21 -0700224 public int getTargetSdkVersion() {
225 return mApplicationInfo.targetSdkVersion;
226 }
227
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700228 public boolean isSecurityViolation() {
229 return mSecurityViolation;
230 }
231
Craig Mautner48d0d182013-06-11 07:53:06 -0700232 public CompatibilityInfo getCompatibilityInfo() {
233 return mDisplayAdjustments.getCompatibilityInfo();
234 }
235
236 public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
237 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
238 }
239
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700240 /**
241 * Gets the array of shared libraries that are listed as
242 * used by the given package.
243 *
244 * @param packageName the name of the package (note: not its
245 * file name)
246 * @return null-ok; the array of shared libraries, each one
247 * a fully-qualified path
248 */
249 private static String[] getLibrariesFor(String packageName) {
250 ApplicationInfo ai = null;
251 try {
252 ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700253 PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700254 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700255 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700256 }
257
258 if (ai == null) {
259 return null;
260 }
261
262 return ai.sharedLibraryFiles;
263 }
264
Todd Kennedy39bfee52016-02-24 10:28:21 -0800265 public void updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths) {
266 setApplicationInfo(aInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700267
Todd Kennedy39bfee52016-02-24 10:28:21 -0800268 final List<String> newPaths = new ArrayList<>();
269 makePaths(mActivityThread, aInfo, newPaths, null /*libPaths*/);
270 final List<String> addedPaths = new ArrayList<>(newPaths.size());
271
272 if (oldPaths != null) {
273 for (String path : newPaths) {
274 final String apkName = path.substring(path.lastIndexOf(File.separator));
275 boolean match = false;
276 for (String oldPath : oldPaths) {
277 final String oldApkName = oldPath.substring(path.lastIndexOf(File.separator));
278 if (apkName.equals(oldApkName)) {
279 match = true;
280 break;
281 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700282 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800283 if (!match) {
284 addedPaths.add(path);
285 }
286 }
287 } else {
288 addedPaths.addAll(newPaths);
289 }
290 synchronized (this) {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700291 createOrUpdateClassLoaderLocked(addedPaths);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800292 if (mResources != null) {
Adam Lesinski082614c2016-03-04 14:33:47 -0800293 mResources = mActivityThread.getTopLevelResources(mResDir, mSplitResDirs,
Todd Kennedy39bfee52016-02-24 10:28:21 -0800294 mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
Adam Lesinski082614c2016-03-04 14:33:47 -0800295 this);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800296 }
297 }
298 }
299
300 private void setApplicationInfo(ApplicationInfo aInfo) {
301 final int myUid = Process.myUid();
302 aInfo = adjustNativeLibraryPaths(aInfo);
303 mApplicationInfo = aInfo;
304 mAppDir = aInfo.sourceDir;
305 mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
306 mSplitAppDirs = aInfo.splitSourceDirs;
307 mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
308 mOverlayDirs = aInfo.resourceDirs;
309 mSharedLibraries = aInfo.sharedLibraryFiles;
310 mDataDir = aInfo.dataDir;
311 mLibDir = aInfo.nativeLibraryDir;
312 mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600313 mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir);
314 mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800315 }
316
317 public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
318 List<String> outZipPaths, List<String> outLibPaths) {
319 final String appDir = aInfo.sourceDir;
320 final String[] splitAppDirs = aInfo.splitSourceDirs;
321 final String libDir = aInfo.nativeLibraryDir;
322 final String[] sharedLibraries = aInfo.sharedLibraryFiles;
323
324 outZipPaths.clear();
325 outZipPaths.add(appDir);
326 if (splitAppDirs != null) {
327 Collections.addAll(outZipPaths, splitAppDirs);
328 }
329
330 if (outLibPaths != null) {
331 outLibPaths.clear();
332 }
333
334 /*
335 * The following is a bit of a hack to inject
336 * instrumentation into the system: If the app
337 * being started matches one of the instrumentation names,
338 * then we combine both the "instrumentation" and
339 * "instrumented" app into the path, along with the
340 * concatenation of both apps' shared library lists.
341 */
342
Todd Kennedy39bfee52016-02-24 10:28:21 -0800343 String[] instrumentationLibs = null;
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100344 // activityThread will be null when called from the WebView zygote; just assume
345 // no instrumentation applies in this case.
346 if (activityThread != null) {
347 String instrumentationPackageName = activityThread.mInstrumentationPackageName;
348 String instrumentationAppDir = activityThread.mInstrumentationAppDir;
349 String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
350 String instrumentationLibDir = activityThread.mInstrumentationLibDir;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800351
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100352 String instrumentedAppDir = activityThread.mInstrumentedAppDir;
353 String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
354 String instrumentedLibDir = activityThread.mInstrumentedLibDir;
355
356 if (appDir.equals(instrumentationAppDir)
357 || appDir.equals(instrumentedAppDir)) {
358 outZipPaths.clear();
359 outZipPaths.add(instrumentationAppDir);
360 if (instrumentationSplitAppDirs != null) {
361 Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
Jeff Haoc7b94822016-03-16 15:56:07 -0700362 }
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100363 if (!instrumentationAppDir.equals(instrumentedAppDir)) {
364 outZipPaths.add(instrumentedAppDir);
365 if (instrumentedSplitAppDirs != null) {
366 Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
367 }
Jeff Haoc7b94822016-03-16 15:56:07 -0700368 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800369
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100370 if (outLibPaths != null) {
371 outLibPaths.add(instrumentationLibDir);
372 if (!instrumentationLibDir.equals(instrumentedLibDir)) {
373 outLibPaths.add(instrumentedLibDir);
374 }
375 }
376
377 if (!instrumentedAppDir.equals(instrumentationAppDir)) {
378 instrumentationLibs = getLibrariesFor(instrumentationPackageName);
379 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800380 }
381 }
382
383 if (outLibPaths != null) {
384 if (outLibPaths.isEmpty()) {
385 outLibPaths.add(libDir);
386 }
387
388 // Add path to libraries in apk for current abi. Do this now because more entries
389 // will be added to zipPaths that shouldn't be part of the library path.
390 if (aInfo.primaryCpuAbi != null) {
Alex Light20ed24f2016-04-20 14:07:43 -0700391 // Add fake libs into the library search path if we target prior to N.
392 if (aInfo.targetSdkVersion <= 23) {
393 outLibPaths.add("/system/fake-libs" +
394 (VMRuntime.is64BitAbi(aInfo.primaryCpuAbi) ? "64" : ""));
395 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800396 for (String apk : outZipPaths) {
397 outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
398 }
399 }
400
401 if (aInfo.isSystemApp() && !aInfo.isUpdatedSystemApp()) {
402 // Add path to system libraries to libPaths;
403 // Access to system libs should be limited
404 // to bundled applications; this is why updated
405 // system apps are not included.
406 outLibPaths.add(System.getProperty("java.library.path"));
407 }
408 }
409
410 if (sharedLibraries != null) {
411 for (String lib : sharedLibraries) {
412 if (!outZipPaths.contains(lib)) {
413 outZipPaths.add(0, lib);
414 }
415 }
416 }
417
418 if (instrumentationLibs != null) {
419 for (String lib : instrumentationLibs) {
420 if (!outZipPaths.contains(lib)) {
421 outZipPaths.add(0, lib);
422 }
423 }
424 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800425 }
426
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700427 private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
428 if (mPackageName.equals("android")) {
Calin Juravle430ef452016-04-22 17:43:07 +0100429 // Note: This branch is taken for system server and we don't need to setup
430 // jit profiling support.
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700431 if (mClassLoader != null) {
432 // nothing to update
433 return;
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800434 }
435
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700436 if (mBaseClassLoader != null) {
437 mClassLoader = mBaseClassLoader;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800438 } else {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700439 mClassLoader = ClassLoader.getSystemClassLoader();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800440 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700441
442 return;
443 }
444
445 // Avoid the binder call when the package is the current application package.
446 // The activity manager will perform ensure that dexopt is performed before
447 // spinning up the process.
448 if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
449 VMRuntime.getRuntime().vmInstructionSet();
450 try {
Brian Carlstromca82e612016-04-19 23:16:08 -0700451 ActivityThread.getPackageManager().notifyPackageUse(mPackageName,
452 PackageManager.NOTIFY_PACKAGE_USE_CROSS_PACKAGE);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700453 } catch (RemoteException re) {
454 throw re.rethrowFromSystemServer();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800455 }
456 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700457
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700458 if (mRegisterPackage) {
459 try {
460 ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
461 } catch (RemoteException e) {
462 throw e.rethrowFromSystemServer();
463 }
464 }
465
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700466 // Lists for the elements of zip/code and native libraries.
467 //
468 // Both lists are usually not empty. We expect on average one APK for the zip component,
469 // but shared libraries and splits are not uncommon. We expect at least three elements
470 // for native libraries (app-based, system, vendor). As such, give both some breathing
471 // space and initialize to a small value (instead of incurring growth code).
472 final List<String> zipPaths = new ArrayList<>(10);
473 final List<String> libPaths = new ArrayList<>(10);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700474 makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
Narayan Kamath8995b002016-05-11 20:31:09 +0100475
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700476 final boolean isBundledApp = mApplicationInfo.isSystemApp()
477 && !mApplicationInfo.isUpdatedSystemApp();
Dimitry Ivanovbf3b5f72016-05-03 11:34:58 -0700478
Dimitry Ivanoveb96b002016-05-10 10:51:40 -0700479 String libraryPermittedPath = mDataDir;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700480 if (isBundledApp) {
481 // This is necessary to grant bundled apps access to
482 // libraries located in subdirectories of /system/lib
483 libraryPermittedPath += File.pathSeparator +
484 System.getProperty("java.library.path");
485 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700486
487 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
488
Narayan Kamath8995b002016-05-11 20:31:09 +0100489 // If we're not asked to include code, we construct a classloader that has
490 // no code path included. We still need to set up the library search paths
491 // and permitted path because NativeActivity relies on it (it attempts to
492 // call System.loadLibrary() on a classloader from a LoadedApk with
493 // mIncludeCode == false).
494 if (!mIncludeCode) {
495 if (mClassLoader == null) {
496 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
497 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
498 "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
499 librarySearchPath, libraryPermittedPath, mBaseClassLoader);
500 StrictMode.setThreadPolicy(oldPolicy);
501 }
502
503 return;
504 }
505
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700506 /*
Narayan Kamath8995b002016-05-11 20:31:09 +0100507 * With all the combination done (if necessary, actually create the java class
508 * loader and set up JIT profiling support if necessary.
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700509 *
510 * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils.
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700511 */
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700512 final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
513 TextUtils.join(File.pathSeparator, zipPaths);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700514
515 if (ActivityThread.localLOGV)
516 Slog.v(ActivityThread.TAG, "Class path: " + zip +
517 ", JNI path: " + librarySearchPath);
518
Calin Juravle430ef452016-04-22 17:43:07 +0100519 boolean needToSetupJitProfiles = false;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700520 if (mClassLoader == null) {
521 // Temporarily disable logging of disk reads on the Looper thread
522 // as this is early and necessary.
523 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
524
525 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
526 mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
527 libraryPermittedPath, mBaseClassLoader);
528
529 StrictMode.setThreadPolicy(oldPolicy);
Calin Juravle430ef452016-04-22 17:43:07 +0100530 // Setup the class loader paths for profiling.
531 needToSetupJitProfiles = true;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700532 }
533
534 if (addedPaths != null && addedPaths.size() > 0) {
535 final String add = TextUtils.join(File.pathSeparator, addedPaths);
536 ApplicationLoaders.getDefault().addPath(mClassLoader, add);
Calin Juravle430ef452016-04-22 17:43:07 +0100537 // Setup the new code paths for profiling.
538 needToSetupJitProfiles = true;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700539 }
Calin Juravle2a727d72016-04-15 19:33:46 +0100540
541 // Setup jit profile support.
Narayan Kamath2d4a2222016-04-25 19:16:56 +0100542 //
Calin Juravle2a727d72016-04-15 19:33:46 +0100543 // It is ok to call this multiple times if the application gets updated with new splits.
544 // The runtime only keeps track of unique code paths and can handle re-registration of
545 // the same code path. There's no need to pass `addedPaths` since any new code paths
546 // are already in `mApplicationInfo`.
Narayan Kamath2d4a2222016-04-25 19:16:56 +0100547 //
548 // It is NOT ok to call this function from the system_server (for any of the packages it
549 // loads code from) so we explicitly disallow it there.
550 if (needToSetupJitProfiles && !ActivityThread.isSystem()) {
Calin Juravle430ef452016-04-22 17:43:07 +0100551 setupJitProfileSupport();
Calin Juravle430ef452016-04-22 17:43:07 +0100552 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800553 }
554
555 public ClassLoader getClassLoader() {
556 synchronized (this) {
557 if (mClassLoader == null) {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700558 createOrUpdateClassLoaderLocked(null /*addedPaths*/);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800559 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700560 return mClassLoader;
561 }
562 }
563
Calin Juravle2a727d72016-04-15 19:33:46 +0100564 // Keep in sync with installd (frameworks/native/cmds/installd/commands.cpp).
565 private static File getPrimaryProfileFile(String packageName) {
566 File profileDir = Environment.getDataProfilesDePackageDirectory(
567 UserHandle.myUserId(), packageName);
568 return new File(profileDir, "primary.prof");
569 }
570
571 private void setupJitProfileSupport() {
572 if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
573 return;
574 }
Calin Juravle126f7802016-05-24 15:23:47 +0100575 // Only set up profile support if the loaded apk has the same uid as the
576 // current process.
577 // Currently, we do not support profiling across different apps.
578 // (e.g. application's uid might be different when the code is
579 // loaded by another app via createApplicationContext)
580 if (mApplicationInfo.uid != Process.myUid()) {
581 return;
582 }
583
Calin Juravle2a727d72016-04-15 19:33:46 +0100584 final List<String> codePaths = new ArrayList<>();
585 if ((mApplicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
586 codePaths.add(mApplicationInfo.sourceDir);
587 }
588 if (mApplicationInfo.splitSourceDirs != null) {
589 Collections.addAll(codePaths, mApplicationInfo.splitSourceDirs);
590 }
591
592 if (codePaths.isEmpty()) {
593 // If there are no code paths there's no need to setup a profile file and register with
594 // the runtime,
595 return;
596 }
597
598 final File profileFile = getPrimaryProfileFile(mPackageName);
Calin Juravle2a727d72016-04-15 19:33:46 +0100599 final File foreignDexProfilesFile =
600 Environment.getDataProfilesDeForeignDexDirectory(UserHandle.myUserId());
Calin Juravle126f7802016-05-24 15:23:47 +0100601
602 VMRuntime.registerAppInfo(profileFile.getPath(), mApplicationInfo.dataDir,
603 codePaths.toArray(new String[codePaths.size()]), foreignDexProfilesFile.getPath());
Calin Juravle9abb5012016-11-23 19:50:58 +0000604
605 // Setup the reporter to notify package manager of any relevant dex loads.
606 // At this point the primary apk is loaded and will not be reported.
607 // Anything loaded from now on will be tracked as a potential secondary
608 // or foreign dex file. The goal is to enable:
609 // 1) monitoring and compilation of secondary dex file
610 // 2) track foreign dex file usage (used to determined the
611 // compilation filter of apks).
612 if (BaseDexClassLoader.getReporter() != DexLoadReporter.INSTANCE) {
613 // Set the dex load reporter if not already set.
614 // Note that during the app's life cycle different LoadedApks may be
615 // created and loaded (e.g. if two different apps share the same runtime).
616 BaseDexClassLoader.setReporter(DexLoadReporter.INSTANCE);
617 }
618 }
619
620 private static class DexLoadReporter implements BaseDexClassLoader.Reporter {
621 private static final DexLoadReporter INSTANCE = new DexLoadReporter();
622
623 private DexLoadReporter() {}
624
625 @Override
626 public void report(List<String> dexPaths) {
627 if (dexPaths.isEmpty()) {
628 return;
629 }
630 String packageName = ActivityThread.currentPackageName();
631 try {
632 ActivityThread.getPackageManager().notifyDexLoad(
633 packageName, dexPaths, VMRuntime.getRuntime().vmInstructionSet());
634 } catch (RemoteException re) {
635 Slog.e(TAG, "Failed to notify PM about dex load for package " + packageName, re);
636 }
637 }
Calin Juravle2a727d72016-04-15 19:33:46 +0100638 }
639
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700640 /**
641 * Setup value for Thread.getContextClassLoader(). If the
642 * package will not run in in a VM with other packages, we set
643 * the Java context ClassLoader to the
644 * PackageInfo.getClassLoader value. However, if this VM can
645 * contain multiple packages, we intead set the Java context
646 * ClassLoader to a proxy that will warn about the use of Java
647 * context ClassLoaders and then fall through to use the
648 * system ClassLoader.
649 *
650 * <p> Note that this is similar to but not the same as the
651 * android.content.Context.getClassLoader(). While both
652 * context class loaders are typically set to the
653 * PathClassLoader used to load the package archive in the
654 * single application per VM case, a single Android process
655 * may contain several Contexts executing on one thread with
656 * their own logical ClassLoaders while the Java context
657 * ClassLoader is a thread local. This is why in the case when
658 * we have multiple packages per VM we do not set the Java
659 * context ClassLoader to an arbitrary but instead warn the
660 * user to set their own if we detect that they are using a
661 * Java library that expects it to be set.
662 */
663 private void initializeJavaContextClassLoader() {
664 IPackageManager pm = ActivityThread.getPackageManager();
665 android.content.pm.PackageInfo pi;
666 try {
Jeff Sharkeyc7bacab2016-02-09 15:56:11 -0700667 pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
668 UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700669 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700670 throw e.rethrowFromSystemServer();
Dianne Hackborn208d9372013-02-25 13:17:54 -0800671 }
672 if (pi == null) {
673 throw new IllegalStateException("Unable to get package info for "
674 + mPackageName + "; is package not installed?");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700675 }
676 /*
677 * Two possible indications that this package could be
678 * sharing its virtual machine with other packages:
679 *
680 * 1.) the sharedUserId attribute is set in the manifest,
681 * indicating a request to share a VM with other
682 * packages with the same sharedUserId.
683 *
684 * 2.) the application element of the manifest has an
685 * attribute specifying a non-default process name,
686 * indicating the desire to run in another packages VM.
687 */
688 boolean sharedUserIdSet = (pi.sharedUserId != null);
689 boolean processNameNotDefault =
690 (pi.applicationInfo != null &&
691 !mPackageName.equals(pi.applicationInfo.processName));
692 boolean sharable = (sharedUserIdSet || processNameNotDefault);
693 ClassLoader contextClassLoader =
694 (sharable)
695 ? new WarningContextClassLoader()
696 : mClassLoader;
697 Thread.currentThread().setContextClassLoader(contextClassLoader);
698 }
699
700 private static class WarningContextClassLoader extends ClassLoader {
701
702 private static boolean warned = false;
703
704 private void warn(String methodName) {
705 if (warned) {
706 return;
707 }
708 warned = true;
709 Thread.currentThread().setContextClassLoader(getParent());
710 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
711 "The class loader returned by " +
712 "Thread.getContextClassLoader() may fail for processes " +
713 "that host multiple applications. You should explicitly " +
714 "specify a context class loader. For example: " +
715 "Thread.setContextClassLoader(getClass().getClassLoader());");
716 }
717
718 @Override public URL getResource(String resName) {
719 warn("getResource");
720 return getParent().getResource(resName);
721 }
722
723 @Override public Enumeration<URL> getResources(String resName) throws IOException {
724 warn("getResources");
725 return getParent().getResources(resName);
726 }
727
728 @Override public InputStream getResourceAsStream(String resName) {
729 warn("getResourceAsStream");
730 return getParent().getResourceAsStream(resName);
731 }
732
733 @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
734 warn("loadClass");
735 return getParent().loadClass(className);
736 }
737
738 @Override public void setClassAssertionStatus(String cname, boolean enable) {
739 warn("setClassAssertionStatus");
740 getParent().setClassAssertionStatus(cname, enable);
741 }
742
743 @Override public void setPackageAssertionStatus(String pname, boolean enable) {
744 warn("setPackageAssertionStatus");
745 getParent().setPackageAssertionStatus(pname, enable);
746 }
747
748 @Override public void setDefaultAssertionStatus(boolean enable) {
749 warn("setDefaultAssertionStatus");
750 getParent().setDefaultAssertionStatus(enable);
751 }
752
753 @Override public void clearAssertionStatus() {
754 warn("clearAssertionStatus");
755 getParent().clearAssertionStatus();
756 }
757 }
758
759 public String getAppDir() {
760 return mAppDir;
761 }
762
Brian Carlstromd893a892012-04-01 21:30:26 -0700763 public String getLibDir() {
764 return mLibDir;
765 }
766
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700767 public String getResDir() {
768 return mResDir;
769 }
770
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700771 public String[] getSplitAppDirs() {
772 return mSplitAppDirs;
773 }
774
775 public String[] getSplitResDirs() {
776 return mSplitResDirs;
777 }
778
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100779 public String[] getOverlayDirs() {
780 return mOverlayDirs;
781 }
782
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700783 public String getDataDir() {
784 return mDataDir;
785 }
786
787 public File getDataDirFile() {
788 return mDataDirFile;
789 }
790
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600791 public File getDeviceProtectedDataDirFile() {
792 return mDeviceProtectedDataDirFile;
Jeff Sharkey15447792015-11-05 16:18:51 -0800793 }
794
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600795 public File getCredentialProtectedDataDirFile() {
796 return mCredentialProtectedDataDirFile;
Jeff Sharkey15447792015-11-05 16:18:51 -0800797 }
798
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700799 public AssetManager getAssets(ActivityThread mainThread) {
800 return getResources(mainThread).getAssets();
801 }
802
803 public Resources getResources(ActivityThread mainThread) {
804 if (mResources == null) {
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700805 mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
Adam Lesinski082614c2016-03-04 14:33:47 -0800806 mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700807 }
808 return mResources;
809 }
810
811 public Application makeApplication(boolean forceDefaultAppClass,
812 Instrumentation instrumentation) {
813 if (mApplication != null) {
814 return mApplication;
815 }
816
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700817 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
818
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700819 Application app = null;
820
821 String appClass = mApplicationInfo.className;
822 if (forceDefaultAppClass || (appClass == null)) {
823 appClass = "android.app.Application";
824 }
825
826 try {
827 java.lang.ClassLoader cl = getClassLoader();
Narayan Kamath8091edb2014-10-15 11:38:44 +0100828 if (!mPackageName.equals("android")) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700829 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
830 "initializeJavaContextClassLoader");
Narayan Kamath8091edb2014-10-15 11:38:44 +0100831 initializeJavaContextClassLoader();
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700832 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Narayan Kamath8091edb2014-10-15 11:38:44 +0100833 }
Jeff Browndefd4a62014-03-10 21:24:37 -0700834 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700835 app = mActivityThread.mInstrumentation.newApplication(
836 cl, appClass, appContext);
837 appContext.setOuterContext(app);
838 } catch (Exception e) {
839 if (!mActivityThread.mInstrumentation.onException(app, e)) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700840 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700841 throw new RuntimeException(
842 "Unable to instantiate application " + appClass
843 + ": " + e.toString(), e);
844 }
845 }
846 mActivityThread.mAllApplications.add(app);
847 mApplication = app;
848
849 if (instrumentation != null) {
850 try {
851 instrumentation.callApplicationOnCreate(app);
852 } catch (Exception e) {
853 if (!instrumentation.onException(app, e)) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700854 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700855 throw new RuntimeException(
856 "Unable to create application " + app.getClass().getName()
857 + ": " + e.toString(), e);
858 }
859 }
860 }
Adam Lesinskide898ff2014-01-29 18:20:45 -0800861
862 // Rewrite the R 'constants' for all library apks.
863 SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
864 .getAssignedPackageIdentifiers();
865 final int N = packageIdentifiers.size();
866 for (int i = 0; i < N; i++) {
867 final int id = packageIdentifiers.keyAt(i);
868 if (id == 0x01 || id == 0x7f) {
869 continue;
870 }
871
872 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
873 }
874
Andreas Gampe4c8e5422016-05-18 11:58:47 -0700875 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
876
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700877 return app;
878 }
879
Adam Lesinskide898ff2014-01-29 18:20:45 -0800880 private void rewriteRValues(ClassLoader cl, String packageName, int id) {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700881 final Class<?> rClazz;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800882 try {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700883 rClazz = cl.loadClass(packageName + ".R");
884 } catch (ClassNotFoundException e) {
885 // This is not necessarily an error, as some packages do not ship with resources
886 // (or they do not need rewriting).
Adam Lesinski1e4663852014-08-15 14:47:28 -0700887 Log.i(TAG, "No resource references to update in package " + packageName);
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700888 return;
889 }
890
Adam Lesinski1e4663852014-08-15 14:47:28 -0700891 final Method callback;
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700892 try {
Adam Lesinski1e4663852014-08-15 14:47:28 -0700893 callback = rClazz.getMethod("onResourcesLoaded", int.class);
894 } catch (NoSuchMethodException e) {
895 // No rewriting to be done.
896 return;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800897 }
Adam Lesinski1e4663852014-08-15 14:47:28 -0700898
899 Throwable cause;
900 try {
901 callback.invoke(null, id);
902 return;
903 } catch (IllegalAccessException e) {
904 cause = e;
905 } catch (InvocationTargetException e) {
906 cause = e.getCause();
907 }
908
909 throw new RuntimeException("Failed to rewrite resource references for " + packageName,
910 cause);
Adam Lesinskide898ff2014-01-29 18:20:45 -0800911 }
912
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700913 public void removeContextRegistrations(Context context,
914 String who, String what) {
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800915 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800916 synchronized (mReceivers) {
917 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
918 mReceivers.remove(context);
919 if (rmap != null) {
920 for (int i = 0; i < rmap.size(); i++) {
921 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
922 IntentReceiverLeaked leak = new IntentReceiverLeaked(
923 what + " " + who + " has leaked IntentReceiver "
924 + rd.getIntentReceiver() + " that was " +
925 "originally registered here. Are you missing a " +
926 "call to unregisterReceiver()?");
927 leak.setStackTrace(rd.getLocation().getStackTrace());
928 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
929 if (reportRegistrationLeaks) {
930 StrictMode.onIntentReceiverLeaked(leak);
931 }
932 try {
933 ActivityManagerNative.getDefault().unregisterReceiver(
934 rd.getIIntentReceiver());
935 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700936 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800937 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700938 }
939 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800940 mUnregisteredReceivers.remove(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700941 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800942
943 synchronized (mServices) {
944 //Slog.i(TAG, "Receiver registrations: " + mReceivers);
945 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
946 mServices.remove(context);
947 if (smap != null) {
948 for (int i = 0; i < smap.size(); i++) {
949 LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
950 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
951 what + " " + who + " has leaked ServiceConnection "
952 + sd.getServiceConnection() + " that was originally bound here");
953 leak.setStackTrace(sd.getLocation().getStackTrace());
954 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
955 if (reportRegistrationLeaks) {
956 StrictMode.onServiceConnectionLeaked(leak);
957 }
958 try {
959 ActivityManagerNative.getDefault().unbindService(
960 sd.getIServiceConnection());
961 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700962 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800963 }
964 sd.doForget();
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800965 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700966 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800967 mUnboundServices.remove(context);
968 //Slog.i(TAG, "Service registrations: " + mServices);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700969 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700970 }
971
972 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
973 Context context, Handler handler,
974 Instrumentation instrumentation, boolean registered) {
975 synchronized (mReceivers) {
976 LoadedApk.ReceiverDispatcher rd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700977 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700978 if (registered) {
979 map = mReceivers.get(context);
980 if (map != null) {
981 rd = map.get(r);
982 }
983 }
984 if (rd == null) {
985 rd = new ReceiverDispatcher(r, context, handler,
986 instrumentation, registered);
987 if (registered) {
988 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700989 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700990 mReceivers.put(context, map);
991 }
992 map.put(r, rd);
993 }
994 } else {
995 rd.validate(context, handler);
996 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800997 rd.mForgotten = false;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700998 return rd.getIIntentReceiver();
999 }
1000 }
1001
1002 public IIntentReceiver forgetReceiverDispatcher(Context context,
1003 BroadcastReceiver r) {
1004 synchronized (mReceivers) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001005 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001006 LoadedApk.ReceiverDispatcher rd = null;
1007 if (map != null) {
1008 rd = map.get(r);
1009 if (rd != null) {
1010 map.remove(r);
1011 if (map.size() == 0) {
1012 mReceivers.remove(context);
1013 }
1014 if (r.getDebugUnregister()) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001015 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001016 = mUnregisteredReceivers.get(context);
1017 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001018 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001019 mUnregisteredReceivers.put(context, holder);
1020 }
1021 RuntimeException ex = new IllegalArgumentException(
1022 "Originally unregistered here:");
1023 ex.fillInStackTrace();
1024 rd.setUnregisterLocation(ex);
1025 holder.put(r, rd);
1026 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -08001027 rd.mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001028 return rd.getIIntentReceiver();
1029 }
1030 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001031 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001032 = mUnregisteredReceivers.get(context);
1033 if (holder != null) {
1034 rd = holder.get(r);
1035 if (rd != null) {
1036 RuntimeException ex = rd.getUnregisterLocation();
1037 throw new IllegalArgumentException(
1038 "Unregistering Receiver " + r
1039 + " that was already unregistered", ex);
1040 }
1041 }
1042 if (context == null) {
1043 throw new IllegalStateException("Unbinding Receiver " + r
1044 + " from Context that is no longer in use: " + context);
1045 } else {
1046 throw new IllegalArgumentException("Receiver not registered: " + r);
1047 }
1048
1049 }
1050 }
1051
1052 static final class ReceiverDispatcher {
1053
1054 final static class InnerReceiver extends IIntentReceiver.Stub {
1055 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
1056 final LoadedApk.ReceiverDispatcher mStrongRef;
1057
1058 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
1059 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
1060 mStrongRef = strong ? rd : null;
1061 }
Jeff Sharkeyd136e512016-03-09 22:30:56 -07001062
1063 @Override
Dianne Hackborn20e80982012-08-31 19:00:44 -07001064 public void performReceive(Intent intent, int resultCode, String data,
1065 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn26756162016-05-17 13:40:44 -07001066 final LoadedApk.ReceiverDispatcher rd;
1067 if (intent == null) {
1068 Log.wtf(TAG, "Null intent received");
1069 rd = null;
1070 } else {
1071 rd = mDispatcher.get();
1072 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001073 if (ActivityThread.DEBUG_BROADCAST) {
1074 int seq = intent.getIntExtra("seq", -1);
Dianne Hackborn26756162016-05-17 13:40:44 -07001075 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
1076 + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001077 }
1078 if (rd != null) {
1079 rd.performReceive(intent, resultCode, data, extras,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001080 ordered, sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001081 } else {
1082 // The activity manager dispatched a broadcast to a registered
1083 // receiver in this process, but before it could be delivered the
1084 // receiver was unregistered. Acknowledge the broadcast on its
1085 // behalf so that the system's broadcast sequence can continue.
1086 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1087 "Finishing broadcast to unregistered receiver");
1088 IActivityManager mgr = ActivityManagerNative.getDefault();
1089 try {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001090 if (extras != null) {
1091 extras.setAllowFds(false);
1092 }
riddle_hsu1f5ac4d2015-01-03 15:38:21 +08001093 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001094 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001095 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001096 }
1097 }
1098 }
1099 }
1100
1101 final IIntentReceiver.Stub mIIntentReceiver;
1102 final BroadcastReceiver mReceiver;
1103 final Context mContext;
1104 final Handler mActivityThread;
1105 final Instrumentation mInstrumentation;
1106 final boolean mRegistered;
1107 final IntentReceiverLeaked mLocation;
1108 RuntimeException mUnregisterLocation;
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -08001109 boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001110
Dianne Hackborne829fef2010-10-26 17:44:01 -07001111 final class Args extends BroadcastReceiver.PendingResult implements Runnable {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001112 private Intent mCurIntent;
Dianne Hackborne829fef2010-10-26 17:44:01 -07001113 private final boolean mOrdered;
Dianne Hackborn17c77532016-06-22 16:49:14 -07001114 private boolean mDispatched;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001115
Dianne Hackborne829fef2010-10-26 17:44:01 -07001116 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001117 boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborne829fef2010-10-26 17:44:01 -07001118 super(resultCode, resultData, resultExtras,
riddle_hsu1f5ac4d2015-01-03 15:38:21 +08001119 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
1120 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
Dianne Hackborne829fef2010-10-26 17:44:01 -07001121 mCurIntent = intent;
1122 mOrdered = ordered;
1123 }
1124
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001125 public void run() {
Dianne Hackborne829fef2010-10-26 17:44:01 -07001126 final BroadcastReceiver receiver = mReceiver;
1127 final boolean ordered = mOrdered;
1128
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001129 if (ActivityThread.DEBUG_BROADCAST) {
1130 int seq = mCurIntent.getIntExtra("seq", -1);
1131 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
1132 + " seq=" + seq + " to " + mReceiver);
1133 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
Dianne Hackborne829fef2010-10-26 17:44:01 -07001134 + " mOrderedHint=" + ordered);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001135 }
1136
Dianne Hackborne829fef2010-10-26 17:44:01 -07001137 final IActivityManager mgr = ActivityManagerNative.getDefault();
1138 final Intent intent = mCurIntent;
Dianne Hackborn17c77532016-06-22 16:49:14 -07001139 if (intent == null) {
1140 Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
1141 }
1142
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001143 mCurIntent = null;
Dianne Hackborn17c77532016-06-22 16:49:14 -07001144 mDispatched = true;
1145 if (receiver == null || intent == null || mForgotten) {
Dianne Hackborne829fef2010-10-26 17:44:01 -07001146 if (mRegistered && ordered) {
1147 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1148 "Finishing null broadcast to " + mReceiver);
1149 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001150 }
1151 return;
1152 }
1153
Dianne Hackborn1ded0b12012-04-26 14:14:50 -07001154 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001155 try {
1156 ClassLoader cl = mReceiver.getClass().getClassLoader();
1157 intent.setExtrasClassLoader(cl);
Jeff Sharkeyd136e512016-03-09 22:30:56 -07001158 intent.prepareToEnterProcess();
Dianne Hackborne829fef2010-10-26 17:44:01 -07001159 setExtrasClassLoader(cl);
1160 receiver.setPendingResult(this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001161 receiver.onReceive(mContext, intent);
1162 } catch (Exception e) {
Dianne Hackborne829fef2010-10-26 17:44:01 -07001163 if (mRegistered && ordered) {
1164 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1165 "Finishing failed broadcast to " + mReceiver);
1166 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001167 }
1168 if (mInstrumentation == null ||
1169 !mInstrumentation.onException(mReceiver, e)) {
Dianne Hackborn1ded0b12012-04-26 14:14:50 -07001170 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001171 throw new RuntimeException(
1172 "Error receiving broadcast " + intent
1173 + " in " + mReceiver, e);
1174 }
1175 }
Dianne Hackborne829fef2010-10-26 17:44:01 -07001176
1177 if (receiver.getPendingResult() != null) {
1178 finish();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001179 }
Dianne Hackborn1ded0b12012-04-26 14:14:50 -07001180 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001181 }
1182 }
1183
1184 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
1185 Handler activityThread, Instrumentation instrumentation,
1186 boolean registered) {
1187 if (activityThread == null) {
1188 throw new NullPointerException("Handler must not be null");
1189 }
1190
1191 mIIntentReceiver = new InnerReceiver(this, !registered);
1192 mReceiver = receiver;
1193 mContext = context;
1194 mActivityThread = activityThread;
1195 mInstrumentation = instrumentation;
1196 mRegistered = registered;
1197 mLocation = new IntentReceiverLeaked(null);
1198 mLocation.fillInStackTrace();
1199 }
1200
1201 void validate(Context context, Handler activityThread) {
1202 if (mContext != context) {
1203 throw new IllegalStateException(
1204 "Receiver " + mReceiver +
1205 " registered with differing Context (was " +
1206 mContext + " now " + context + ")");
1207 }
1208 if (mActivityThread != activityThread) {
1209 throw new IllegalStateException(
1210 "Receiver " + mReceiver +
1211 " registered with differing handler (was " +
1212 mActivityThread + " now " + activityThread + ")");
1213 }
1214 }
1215
1216 IntentReceiverLeaked getLocation() {
1217 return mLocation;
1218 }
1219
1220 BroadcastReceiver getIntentReceiver() {
1221 return mReceiver;
1222 }
1223
1224 IIntentReceiver getIIntentReceiver() {
1225 return mIIntentReceiver;
1226 }
1227
1228 void setUnregisterLocation(RuntimeException ex) {
1229 mUnregisterLocation = ex;
1230 }
1231
1232 RuntimeException getUnregisterLocation() {
1233 return mUnregisterLocation;
1234 }
1235
Dianne Hackborn20e80982012-08-31 19:00:44 -07001236 public void performReceive(Intent intent, int resultCode, String data,
1237 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn41bfaf82016-06-08 16:33:29 -07001238 final Args args = new Args(intent, resultCode, data, extras, ordered,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001239 sticky, sendingUser);
Dianne Hackborn41bfaf82016-06-08 16:33:29 -07001240 if (intent == null) {
1241 Log.wtf(TAG, "Null intent received");
1242 } else {
1243 if (ActivityThread.DEBUG_BROADCAST) {
1244 int seq = intent.getIntExtra("seq", -1);
1245 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
1246 + " seq=" + seq + " to " + mReceiver);
1247 }
1248 }
1249 if (intent == null || !mActivityThread.post(args)) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001250 if (mRegistered && ordered) {
1251 IActivityManager mgr = ActivityManagerNative.getDefault();
Dianne Hackborne829fef2010-10-26 17:44:01 -07001252 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1253 "Finishing sync broadcast to " + mReceiver);
1254 args.sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001255 }
1256 }
1257 }
1258
1259 }
1260
1261 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1262 Context context, Handler handler, int flags) {
1263 synchronized (mServices) {
1264 LoadedApk.ServiceDispatcher sd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001265 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001266 if (map != null) {
1267 sd = map.get(c);
1268 }
1269 if (sd == null) {
1270 sd = new ServiceDispatcher(c, context, handler, flags);
1271 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001272 map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001273 mServices.put(context, map);
1274 }
1275 map.put(c, sd);
1276 } else {
1277 sd.validate(context, handler);
1278 }
1279 return sd.getIServiceConnection();
1280 }
1281 }
1282
1283 public final IServiceConnection forgetServiceDispatcher(Context context,
1284 ServiceConnection c) {
1285 synchronized (mServices) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001286 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001287 = mServices.get(context);
1288 LoadedApk.ServiceDispatcher sd = null;
1289 if (map != null) {
1290 sd = map.get(c);
1291 if (sd != null) {
1292 map.remove(c);
1293 sd.doForget();
1294 if (map.size() == 0) {
1295 mServices.remove(context);
1296 }
1297 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001298 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001299 = mUnboundServices.get(context);
1300 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001301 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001302 mUnboundServices.put(context, holder);
1303 }
1304 RuntimeException ex = new IllegalArgumentException(
1305 "Originally unbound here:");
1306 ex.fillInStackTrace();
1307 sd.setUnbindLocation(ex);
1308 holder.put(c, sd);
1309 }
1310 return sd.getIServiceConnection();
1311 }
1312 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001313 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001314 = mUnboundServices.get(context);
1315 if (holder != null) {
1316 sd = holder.get(c);
1317 if (sd != null) {
1318 RuntimeException ex = sd.getUnbindLocation();
1319 throw new IllegalArgumentException(
1320 "Unbinding Service " + c
1321 + " that was already unbound", ex);
1322 }
1323 }
1324 if (context == null) {
1325 throw new IllegalStateException("Unbinding Service " + c
1326 + " from Context that is no longer in use: " + context);
1327 } else {
1328 throw new IllegalArgumentException("Service not registered: " + c);
1329 }
1330 }
1331 }
1332
1333 static final class ServiceDispatcher {
1334 private final ServiceDispatcher.InnerConnection mIServiceConnection;
1335 private final ServiceConnection mConnection;
1336 private final Context mContext;
1337 private final Handler mActivityThread;
1338 private final ServiceConnectionLeaked mLocation;
1339 private final int mFlags;
1340
1341 private RuntimeException mUnbindLocation;
1342
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001343 private boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001344
1345 private static class ConnectionInfo {
1346 IBinder binder;
1347 IBinder.DeathRecipient deathMonitor;
1348 }
1349
1350 private static class InnerConnection extends IServiceConnection.Stub {
1351 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1352
1353 InnerConnection(LoadedApk.ServiceDispatcher sd) {
1354 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1355 }
1356
1357 public void connected(ComponentName name, IBinder service) throws RemoteException {
1358 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1359 if (sd != null) {
1360 sd.connected(name, service);
1361 }
1362 }
1363 }
1364
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001365 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1366 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001367
1368 ServiceDispatcher(ServiceConnection conn,
1369 Context context, Handler activityThread, int flags) {
1370 mIServiceConnection = new InnerConnection(this);
1371 mConnection = conn;
1372 mContext = context;
1373 mActivityThread = activityThread;
1374 mLocation = new ServiceConnectionLeaked(null);
1375 mLocation.fillInStackTrace();
1376 mFlags = flags;
1377 }
1378
1379 void validate(Context context, Handler activityThread) {
1380 if (mContext != context) {
1381 throw new RuntimeException(
1382 "ServiceConnection " + mConnection +
1383 " registered with differing Context (was " +
1384 mContext + " now " + context + ")");
1385 }
1386 if (mActivityThread != activityThread) {
1387 throw new RuntimeException(
1388 "ServiceConnection " + mConnection +
1389 " registered with differing handler (was " +
1390 mActivityThread + " now " + activityThread + ")");
1391 }
1392 }
1393
1394 void doForget() {
1395 synchronized(this) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001396 for (int i=0; i<mActiveConnections.size(); i++) {
1397 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001398 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1399 }
1400 mActiveConnections.clear();
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001401 mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001402 }
1403 }
1404
1405 ServiceConnectionLeaked getLocation() {
1406 return mLocation;
1407 }
1408
1409 ServiceConnection getServiceConnection() {
1410 return mConnection;
1411 }
1412
1413 IServiceConnection getIServiceConnection() {
1414 return mIServiceConnection;
1415 }
1416
1417 int getFlags() {
1418 return mFlags;
1419 }
1420
1421 void setUnbindLocation(RuntimeException ex) {
1422 mUnbindLocation = ex;
1423 }
1424
1425 RuntimeException getUnbindLocation() {
1426 return mUnbindLocation;
1427 }
1428
1429 public void connected(ComponentName name, IBinder service) {
1430 if (mActivityThread != null) {
1431 mActivityThread.post(new RunConnection(name, service, 0));
1432 } else {
1433 doConnected(name, service);
1434 }
1435 }
1436
1437 public void death(ComponentName name, IBinder service) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001438 if (mActivityThread != null) {
1439 mActivityThread.post(new RunConnection(name, service, 1));
1440 } else {
1441 doDeath(name, service);
1442 }
1443 }
1444
1445 public void doConnected(ComponentName name, IBinder service) {
1446 ServiceDispatcher.ConnectionInfo old;
1447 ServiceDispatcher.ConnectionInfo info;
1448
1449 synchronized (this) {
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001450 if (mForgotten) {
1451 // We unbound before receiving the connection; ignore
1452 // any connection received.
1453 return;
1454 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001455 old = mActiveConnections.get(name);
1456 if (old != null && old.binder == service) {
1457 // Huh, already have this one. Oh well!
1458 return;
1459 }
1460
1461 if (service != null) {
1462 // A new service is being connected... set it all up.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001463 info = new ConnectionInfo();
1464 info.binder = service;
1465 info.deathMonitor = new DeathMonitor(name, service);
1466 try {
1467 service.linkToDeath(info.deathMonitor, 0);
1468 mActiveConnections.put(name, info);
1469 } catch (RemoteException e) {
1470 // This service was dead before we got it... just
1471 // don't do anything with it.
1472 mActiveConnections.remove(name);
1473 return;
1474 }
1475
1476 } else {
1477 // The named service is being disconnected... clean up.
1478 mActiveConnections.remove(name);
1479 }
1480
1481 if (old != null) {
1482 old.binder.unlinkToDeath(old.deathMonitor, 0);
1483 }
1484 }
1485
Adrian Roosa9b43182016-07-21 13:20:38 -07001486 // If there was an old service, it is now disconnected.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001487 if (old != null) {
1488 mConnection.onServiceDisconnected(name);
1489 }
1490 // If there is a new service, it is now connected.
1491 if (service != null) {
1492 mConnection.onServiceConnected(name, service);
1493 }
1494 }
1495
1496 public void doDeath(ComponentName name, IBinder service) {
Adrian Roosa9b43182016-07-21 13:20:38 -07001497 synchronized (this) {
1498 ConnectionInfo old = mActiveConnections.get(name);
1499 if (old == null || old.binder != service) {
1500 // Death for someone different than who we last
1501 // reported... just ignore it.
1502 return;
1503 }
1504 mActiveConnections.remove(name);
1505 old.binder.unlinkToDeath(old.deathMonitor, 0);
1506 }
1507
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001508 mConnection.onServiceDisconnected(name);
1509 }
1510
1511 private final class RunConnection implements Runnable {
1512 RunConnection(ComponentName name, IBinder service, int command) {
1513 mName = name;
1514 mService = service;
1515 mCommand = command;
1516 }
1517
1518 public void run() {
1519 if (mCommand == 0) {
1520 doConnected(mName, mService);
1521 } else if (mCommand == 1) {
1522 doDeath(mName, mService);
1523 }
1524 }
1525
1526 final ComponentName mName;
1527 final IBinder mService;
1528 final int mCommand;
1529 }
1530
1531 private final class DeathMonitor implements IBinder.DeathRecipient
1532 {
1533 DeathMonitor(ComponentName name, IBinder service) {
1534 mName = name;
1535 mService = service;
1536 }
1537
1538 public void binderDied() {
1539 death(mName, mService);
1540 }
1541
1542 final ComponentName mName;
1543 final IBinder mService;
1544 }
1545 }
1546}