blob: b8fc323089617323b7cdc9b1db899266928b283d [file] [log] [blame]
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070019import android.text.TextUtils;
Dianne Hackbornadd005c2013-07-17 18:43:12 -070020import android.util.ArrayMap;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070021import android.content.BroadcastReceiver;
22import android.content.ComponentName;
23import android.content.Context;
24import android.content.IIntentReceiver;
25import android.content.Intent;
26import android.content.ServiceConnection;
27import android.content.pm.ApplicationInfo;
28import android.content.pm.IPackageManager;
29import android.content.pm.PackageManager;
30import android.content.res.AssetManager;
31import android.content.res.CompatibilityInfo;
32import android.content.res.Resources;
33import android.os.Bundle;
Jeff Sharkey15447792015-11-05 16:18:51 -080034import android.os.FileUtils;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070035import android.os.Handler;
36import android.os.IBinder;
37import android.os.Process;
38import android.os.RemoteException;
Brad Fitzpatrick624d50f2010-11-09 14:25:12 -080039import android.os.StrictMode;
Dianne Hackborn1ded0b12012-04-26 14:14:50 -070040import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070041import android.os.UserHandle;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070042import android.util.AndroidRuntimeException;
Adam Lesinski2cb761e2014-08-15 13:59:02 -070043import android.util.Log;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070044import android.util.Slog;
Adam Lesinskide898ff2014-01-29 18:20:45 -080045import android.util.SparseArray;
Craig Mautner48d0d182013-06-11 07:53:06 -070046import android.view.DisplayAdjustments;
Jeff Browna492c3a2012-08-23 19:48:44 -070047import android.view.Display;
jgu214741cd92014-12-17 17:23:29 -050048import android.os.SystemProperties;
Jeff Sharkeyb9f36742015-04-08 21:02:14 -070049
Narayan Kamath7dba6eb2014-07-16 08:53:30 +010050import dalvik.system.VMRuntime;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070051
52import java.io.File;
53import java.io.IOException;
54import java.io.InputStream;
55import java.lang.ref.WeakReference;
Adam Lesinski1e4663852014-08-15 14:47:28 -070056import java.lang.reflect.InvocationTargetException;
57import java.lang.reflect.Method;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070058import java.net.URL;
Dmitriy Ivanove56b3f62015-06-05 22:00:13 -070059import java.util.List;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070060import java.util.ArrayList;
Todd Kennedy39bfee52016-02-24 10:28:21 -080061import java.util.Arrays;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070062import java.util.Collections;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070063import java.util.Enumeration;
Narayan Kamath20531682014-07-14 13:18:43 +010064import java.util.Objects;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070065
66final class IntentReceiverLeaked extends AndroidRuntimeException {
67 public IntentReceiverLeaked(String msg) {
68 super(msg);
69 }
70}
71
72final class ServiceConnectionLeaked extends AndroidRuntimeException {
73 public ServiceConnectionLeaked(String msg) {
74 super(msg);
75 }
76}
77
78/**
79 * Local state maintained about a currently loaded .apk.
80 * @hide
81 */
Dianne Hackborn5fd21692011-06-07 14:09:47 -070082public final class LoadedApk {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070083
Amith Yamasani742a6712011-05-04 14:49:28 -070084 private static final String TAG = "LoadedApk";
85
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070086 private final ActivityThread mActivityThread;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070087 final String mPackageName;
Todd Kennedy39bfee52016-02-24 10:28:21 -080088 private ApplicationInfo mApplicationInfo;
89 private String mAppDir;
90 private String mResDir;
91 private String[] mSplitAppDirs;
92 private String[] mSplitResDirs;
93 private String[] mOverlayDirs;
94 private String[] mSharedLibraries;
95 private String mDataDir;
96 private String mLibDir;
97 private File mDataDirFile;
98 private File mDeviceEncryptedDataDirFile;
99 private File mCredentialEncryptedDataDirFile;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700100 private final ClassLoader mBaseClassLoader;
101 private final boolean mSecurityViolation;
102 private final boolean mIncludeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700103 private final boolean mRegisterPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700104 private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800105 /** WARNING: This may change. Don't hold external references to it. */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700106 Resources mResources;
107 private ClassLoader mClassLoader;
108 private Application mApplication;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700109
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700110 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
111 = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
112 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
113 = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
114 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
115 = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
116 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
117 = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700118
119 int mClientCount = 0;
120
121 Application getApplication() {
122 return mApplication;
123 }
124
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700125 /**
126 * Create information about a new .apk
127 *
128 * NOTE: This constructor is called with ActivityThread's lock held,
129 * so MUST NOT call back out to the activity manager.
130 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700131 public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
Jeff Browndefd4a62014-03-10 21:24:37 -0700132 CompatibilityInfo compatInfo, ClassLoader baseLoader,
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700133 boolean securityViolation, boolean includeCode, boolean registerPackage) {
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100134
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700135 mActivityThread = activityThread;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800136 setApplicationInfo(aInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700137 mPackageName = aInfo.packageName;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700138 mBaseClassLoader = baseLoader;
139 mSecurityViolation = securityViolation;
140 mIncludeCode = includeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700141 mRegisterPackage = registerPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700142 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700143 }
144
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100145 private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) {
146 // If we're dealing with a multi-arch application that has both
147 // 32 and 64 bit shared libraries, we might need to choose the secondary
148 // depending on what the current runtime's instruction set is.
149 if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
150 final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
jgu214741cd92014-12-17 17:23:29 -0500151
152 // Get the instruction set that the libraries of secondary Abi is supported.
153 // In presence of a native bridge this might be different than the one secondary Abi used.
154 String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
155 final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
156 secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100157
158 // If the runtimeIsa is the same as the primary isa, then we do nothing.
159 // Everything will be set up correctly because info.nativeLibraryDir will
160 // correspond to the right ISA.
161 if (runtimeIsa.equals(secondaryIsa)) {
162 final ApplicationInfo modified = new ApplicationInfo(info);
163 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
Dmitriy Ivanove56b3f62015-06-05 22:00:13 -0700164 modified.primaryCpuAbi = modified.secondaryCpuAbi;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100165 return modified;
166 }
167 }
168
169 return info;
170 }
171
Jeff Browndefd4a62014-03-10 21:24:37 -0700172 /**
173 * Create information about the system package.
174 * Must call {@link #installSystemApplicationInfo} later.
175 */
176 LoadedApk(ActivityThread activityThread) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700177 mActivityThread = activityThread;
Jeff Browndefd4a62014-03-10 21:24:37 -0700178 mApplicationInfo = new ApplicationInfo();
179 mApplicationInfo.packageName = "android";
180 mPackageName = "android";
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700181 mAppDir = null;
182 mResDir = null;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700183 mSplitAppDirs = null;
184 mSplitResDirs = null;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100185 mOverlayDirs = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700186 mSharedLibraries = null;
187 mDataDir = null;
188 mDataDirFile = null;
Jeff Sharkey15447792015-11-05 16:18:51 -0800189 mDeviceEncryptedDataDirFile = null;
190 mCredentialEncryptedDataDirFile = null;
Kenny Root85387d72010-08-26 10:13:11 -0700191 mLibDir = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700192 mBaseClassLoader = null;
193 mSecurityViolation = false;
194 mIncludeCode = true;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700195 mRegisterPackage = false;
Jeff Browndefd4a62014-03-10 21:24:37 -0700196 mClassLoader = ClassLoader.getSystemClassLoader();
197 mResources = Resources.getSystem();
198 }
199
200 /**
201 * Sets application info about the system package.
202 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100203 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
Jeff Browndefd4a62014-03-10 21:24:37 -0700204 assert info.packageName.equals("android");
205 mApplicationInfo = info;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100206 mClassLoader = classLoader;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700207 }
208
209 public String getPackageName() {
210 return mPackageName;
211 }
212
213 public ApplicationInfo getApplicationInfo() {
214 return mApplicationInfo;
215 }
216
Jeff Sharkey369f5092016-02-29 11:16:21 -0700217 public int getTargetSdkVersion() {
218 return mApplicationInfo.targetSdkVersion;
219 }
220
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700221 public boolean isSecurityViolation() {
222 return mSecurityViolation;
223 }
224
Craig Mautner48d0d182013-06-11 07:53:06 -0700225 public CompatibilityInfo getCompatibilityInfo() {
226 return mDisplayAdjustments.getCompatibilityInfo();
227 }
228
229 public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
230 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
231 }
232
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700233 /**
234 * Gets the array of shared libraries that are listed as
235 * used by the given package.
236 *
237 * @param packageName the name of the package (note: not its
238 * file name)
239 * @return null-ok; the array of shared libraries, each one
240 * a fully-qualified path
241 */
242 private static String[] getLibrariesFor(String packageName) {
243 ApplicationInfo ai = null;
244 try {
245 ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700246 PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700247 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700248 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700249 }
250
251 if (ai == null) {
252 return null;
253 }
254
255 return ai.sharedLibraryFiles;
256 }
257
Todd Kennedy39bfee52016-02-24 10:28:21 -0800258 public void updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths) {
259 setApplicationInfo(aInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700260
Todd Kennedy39bfee52016-02-24 10:28:21 -0800261 final List<String> newPaths = new ArrayList<>();
262 makePaths(mActivityThread, aInfo, newPaths, null /*libPaths*/);
263 final List<String> addedPaths = new ArrayList<>(newPaths.size());
264
265 if (oldPaths != null) {
266 for (String path : newPaths) {
267 final String apkName = path.substring(path.lastIndexOf(File.separator));
268 boolean match = false;
269 for (String oldPath : oldPaths) {
270 final String oldApkName = oldPath.substring(path.lastIndexOf(File.separator));
271 if (apkName.equals(oldApkName)) {
272 match = true;
273 break;
274 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700275 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800276 if (!match) {
277 addedPaths.add(path);
278 }
279 }
280 } else {
281 addedPaths.addAll(newPaths);
282 }
283 synchronized (this) {
284 mClassLoader = createOrUpdateClassLoaderLocked(addedPaths);
285 if (mResources != null) {
Adam Lesinski082614c2016-03-04 14:33:47 -0800286 mResources = mActivityThread.getTopLevelResources(mResDir, mSplitResDirs,
Todd Kennedy39bfee52016-02-24 10:28:21 -0800287 mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
Adam Lesinski082614c2016-03-04 14:33:47 -0800288 this);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800289 }
290 }
291 }
292
293 private void setApplicationInfo(ApplicationInfo aInfo) {
294 final int myUid = Process.myUid();
295 aInfo = adjustNativeLibraryPaths(aInfo);
296 mApplicationInfo = aInfo;
297 mAppDir = aInfo.sourceDir;
298 mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
299 mSplitAppDirs = aInfo.splitSourceDirs;
300 mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
301 mOverlayDirs = aInfo.resourceDirs;
302 mSharedLibraries = aInfo.sharedLibraryFiles;
303 mDataDir = aInfo.dataDir;
304 mLibDir = aInfo.nativeLibraryDir;
305 mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
306 mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
307 mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
308 }
309
310 public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
311 List<String> outZipPaths, List<String> outLibPaths) {
312 final String appDir = aInfo.sourceDir;
313 final String[] splitAppDirs = aInfo.splitSourceDirs;
314 final String libDir = aInfo.nativeLibraryDir;
315 final String[] sharedLibraries = aInfo.sharedLibraryFiles;
316
317 outZipPaths.clear();
318 outZipPaths.add(appDir);
319 if (splitAppDirs != null) {
320 Collections.addAll(outZipPaths, splitAppDirs);
321 }
322
323 if (outLibPaths != null) {
324 outLibPaths.clear();
325 }
326
327 /*
328 * The following is a bit of a hack to inject
329 * instrumentation into the system: If the app
330 * being started matches one of the instrumentation names,
331 * then we combine both the "instrumentation" and
332 * "instrumented" app into the path, along with the
333 * concatenation of both apps' shared library lists.
334 */
335
336 String instrumentationPackageName = activityThread.mInstrumentationPackageName;
337 String instrumentationAppDir = activityThread.mInstrumentationAppDir;
338 String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
339 String instrumentationLibDir = activityThread.mInstrumentationLibDir;
340
341 String instrumentedAppDir = activityThread.mInstrumentedAppDir;
342 String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
343 String instrumentedLibDir = activityThread.mInstrumentedLibDir;
344 String[] instrumentationLibs = null;
345
346 if (appDir.equals(instrumentationAppDir)
347 || appDir.equals(instrumentedAppDir)) {
348 outZipPaths.clear();
349 outZipPaths.add(instrumentationAppDir);
350 if (instrumentationSplitAppDirs != null) {
351 Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
352 }
353 outZipPaths.add(instrumentedAppDir);
354 if (instrumentedSplitAppDirs != null) {
355 Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700356 }
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800357
Todd Kennedy39bfee52016-02-24 10:28:21 -0800358 if (outLibPaths != null) {
359 outLibPaths.add(instrumentationLibDir);
360 outLibPaths.add(instrumentedLibDir);
361 }
362
363 if (!instrumentedAppDir.equals(instrumentationAppDir)) {
364 instrumentationLibs = getLibrariesFor(instrumentationPackageName);
365 }
366 }
367
368 if (outLibPaths != null) {
369 if (outLibPaths.isEmpty()) {
370 outLibPaths.add(libDir);
371 }
372
373 // Add path to libraries in apk for current abi. Do this now because more entries
374 // will be added to zipPaths that shouldn't be part of the library path.
375 if (aInfo.primaryCpuAbi != null) {
376 for (String apk : outZipPaths) {
377 outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
378 }
379 }
380
381 if (aInfo.isSystemApp() && !aInfo.isUpdatedSystemApp()) {
382 // Add path to system libraries to libPaths;
383 // Access to system libs should be limited
384 // to bundled applications; this is why updated
385 // system apps are not included.
386 outLibPaths.add(System.getProperty("java.library.path"));
387 }
388 }
389
390 if (sharedLibraries != null) {
391 for (String lib : sharedLibraries) {
392 if (!outZipPaths.contains(lib)) {
393 outZipPaths.add(0, lib);
394 }
395 }
396 }
397
398 if (instrumentationLibs != null) {
399 for (String lib : instrumentationLibs) {
400 if (!outZipPaths.contains(lib)) {
401 outZipPaths.add(0, lib);
402 }
403 }
404 }
405
406 final String zip = TextUtils.join(File.pathSeparator, outZipPaths);
407 }
408
409 private ClassLoader createOrUpdateClassLoaderLocked(List<String> addedPaths) {
410 final ClassLoader classLoader;
411 if (mIncludeCode && !mPackageName.equals("android")) {
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800412 // Avoid the binder call when the package is the current application package.
413 // The activity manager will perform ensure that dexopt is performed before
414 // spinning up the process.
415 if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
Todd Kennedy39bfee52016-02-24 10:28:21 -0800416 VMRuntime.getRuntime().vmInstructionSet();
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800417 try {
418 ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
419 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700420 throw re.rethrowFromSystemServer();
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800421 }
422 }
423
424 final List<String> zipPaths = new ArrayList<>();
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800425 final List<String> libPaths = new ArrayList<>();
426
427 if (mRegisterPackage) {
428 try {
429 ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
430 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700431 throw e.rethrowFromSystemServer();
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800432 }
433 }
434
Todd Kennedy39bfee52016-02-24 10:28:21 -0800435 makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
436 final String zip = TextUtils.join(File.pathSeparator, zipPaths);
437 final boolean isBundledApp = mApplicationInfo.isSystemApp()
438 && !mApplicationInfo.isUpdatedSystemApp();
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800439 String libraryPermittedPath = mDataDir;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800440 if (isBundledApp) {
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800441 // This is necessary to grant bundled apps access to
442 // libraries located in subdirectories of /system/lib
443 libraryPermittedPath += File.pathSeparator +
444 System.getProperty("java.library.path");
445 }
446 // DO NOT SHIP: this is a workaround for apps loading native libraries
447 // provided by 3rd party apps using absolute path instead of corresponding
448 // classloader; see http://b/26954419 for example.
449 if (mApplicationInfo.targetSdkVersion <= 23) {
450 libraryPermittedPath += File.pathSeparator + "/data/app";
451 }
452 // -----------------------------------------------------------------------------
453
454 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
455
456 /*
457 * With all the combination done (if necessary, actually
458 * create the class loader.
459 */
460
461 if (ActivityThread.localLOGV)
462 Slog.v(ActivityThread.TAG, "Class path: " + zip +
463 ", JNI path: " + librarySearchPath);
464
Todd Kennedy39bfee52016-02-24 10:28:21 -0800465 if (mClassLoader == null) {
466 // Temporarily disable logging of disk reads on the Looper thread
467 // as this is early and necessary.
468 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800469
Todd Kennedy39bfee52016-02-24 10:28:21 -0800470 classLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
471 mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
472 libraryPermittedPath, mBaseClassLoader);
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800473
Todd Kennedy39bfee52016-02-24 10:28:21 -0800474 StrictMode.setThreadPolicy(oldPolicy);
475 } else if (addedPaths != null && addedPaths.size() > 0) {
476 final String add = TextUtils.join(File.pathSeparator, addedPaths);
477 ApplicationLoaders.getDefault().addPath(mClassLoader, add);
478 classLoader = mClassLoader;
479 } else {
480 classLoader = mClassLoader;
481 }
482 } else {
483 if (mClassLoader == null) {
484 if (mBaseClassLoader == null) {
485 classLoader = ClassLoader.getSystemClassLoader();
486 } else {
487 classLoader = mBaseClassLoader;
488 }
489 } else {
490 classLoader = mClassLoader;
491 }
492 }
493 return classLoader;
494 }
495
496 public ClassLoader getClassLoader() {
497 synchronized (this) {
498 if (mClassLoader == null) {
499 mClassLoader = createOrUpdateClassLoaderLocked(null /*addedPaths*/);
500 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700501 return mClassLoader;
502 }
503 }
504
505 /**
506 * Setup value for Thread.getContextClassLoader(). If the
507 * package will not run in in a VM with other packages, we set
508 * the Java context ClassLoader to the
509 * PackageInfo.getClassLoader value. However, if this VM can
510 * contain multiple packages, we intead set the Java context
511 * ClassLoader to a proxy that will warn about the use of Java
512 * context ClassLoaders and then fall through to use the
513 * system ClassLoader.
514 *
515 * <p> Note that this is similar to but not the same as the
516 * android.content.Context.getClassLoader(). While both
517 * context class loaders are typically set to the
518 * PathClassLoader used to load the package archive in the
519 * single application per VM case, a single Android process
520 * may contain several Contexts executing on one thread with
521 * their own logical ClassLoaders while the Java context
522 * ClassLoader is a thread local. This is why in the case when
523 * we have multiple packages per VM we do not set the Java
524 * context ClassLoader to an arbitrary but instead warn the
525 * user to set their own if we detect that they are using a
526 * Java library that expects it to be set.
527 */
528 private void initializeJavaContextClassLoader() {
529 IPackageManager pm = ActivityThread.getPackageManager();
530 android.content.pm.PackageInfo pi;
531 try {
Jeff Sharkeyc7bacab2016-02-09 15:56:11 -0700532 pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
533 UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700534 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700535 throw e.rethrowFromSystemServer();
Dianne Hackborn208d9372013-02-25 13:17:54 -0800536 }
537 if (pi == null) {
538 throw new IllegalStateException("Unable to get package info for "
539 + mPackageName + "; is package not installed?");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700540 }
541 /*
542 * Two possible indications that this package could be
543 * sharing its virtual machine with other packages:
544 *
545 * 1.) the sharedUserId attribute is set in the manifest,
546 * indicating a request to share a VM with other
547 * packages with the same sharedUserId.
548 *
549 * 2.) the application element of the manifest has an
550 * attribute specifying a non-default process name,
551 * indicating the desire to run in another packages VM.
552 */
553 boolean sharedUserIdSet = (pi.sharedUserId != null);
554 boolean processNameNotDefault =
555 (pi.applicationInfo != null &&
556 !mPackageName.equals(pi.applicationInfo.processName));
557 boolean sharable = (sharedUserIdSet || processNameNotDefault);
558 ClassLoader contextClassLoader =
559 (sharable)
560 ? new WarningContextClassLoader()
561 : mClassLoader;
562 Thread.currentThread().setContextClassLoader(contextClassLoader);
563 }
564
565 private static class WarningContextClassLoader extends ClassLoader {
566
567 private static boolean warned = false;
568
569 private void warn(String methodName) {
570 if (warned) {
571 return;
572 }
573 warned = true;
574 Thread.currentThread().setContextClassLoader(getParent());
575 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
576 "The class loader returned by " +
577 "Thread.getContextClassLoader() may fail for processes " +
578 "that host multiple applications. You should explicitly " +
579 "specify a context class loader. For example: " +
580 "Thread.setContextClassLoader(getClass().getClassLoader());");
581 }
582
583 @Override public URL getResource(String resName) {
584 warn("getResource");
585 return getParent().getResource(resName);
586 }
587
588 @Override public Enumeration<URL> getResources(String resName) throws IOException {
589 warn("getResources");
590 return getParent().getResources(resName);
591 }
592
593 @Override public InputStream getResourceAsStream(String resName) {
594 warn("getResourceAsStream");
595 return getParent().getResourceAsStream(resName);
596 }
597
598 @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
599 warn("loadClass");
600 return getParent().loadClass(className);
601 }
602
603 @Override public void setClassAssertionStatus(String cname, boolean enable) {
604 warn("setClassAssertionStatus");
605 getParent().setClassAssertionStatus(cname, enable);
606 }
607
608 @Override public void setPackageAssertionStatus(String pname, boolean enable) {
609 warn("setPackageAssertionStatus");
610 getParent().setPackageAssertionStatus(pname, enable);
611 }
612
613 @Override public void setDefaultAssertionStatus(boolean enable) {
614 warn("setDefaultAssertionStatus");
615 getParent().setDefaultAssertionStatus(enable);
616 }
617
618 @Override public void clearAssertionStatus() {
619 warn("clearAssertionStatus");
620 getParent().clearAssertionStatus();
621 }
622 }
623
624 public String getAppDir() {
625 return mAppDir;
626 }
627
Brian Carlstromd893a892012-04-01 21:30:26 -0700628 public String getLibDir() {
629 return mLibDir;
630 }
631
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700632 public String getResDir() {
633 return mResDir;
634 }
635
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700636 public String[] getSplitAppDirs() {
637 return mSplitAppDirs;
638 }
639
640 public String[] getSplitResDirs() {
641 return mSplitResDirs;
642 }
643
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100644 public String[] getOverlayDirs() {
645 return mOverlayDirs;
646 }
647
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700648 public String getDataDir() {
649 return mDataDir;
650 }
651
652 public File getDataDirFile() {
653 return mDataDirFile;
654 }
655
Jeff Sharkey15447792015-11-05 16:18:51 -0800656 public File getDeviceEncryptedDataDirFile() {
657 return mDeviceEncryptedDataDirFile;
658 }
659
660 public File getCredentialEncryptedDataDirFile() {
661 return mCredentialEncryptedDataDirFile;
662 }
663
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700664 public AssetManager getAssets(ActivityThread mainThread) {
665 return getResources(mainThread).getAssets();
666 }
667
668 public Resources getResources(ActivityThread mainThread) {
669 if (mResources == null) {
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700670 mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
Adam Lesinski082614c2016-03-04 14:33:47 -0800671 mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700672 }
673 return mResources;
674 }
675
676 public Application makeApplication(boolean forceDefaultAppClass,
677 Instrumentation instrumentation) {
678 if (mApplication != null) {
679 return mApplication;
680 }
681
682 Application app = null;
683
684 String appClass = mApplicationInfo.className;
685 if (forceDefaultAppClass || (appClass == null)) {
686 appClass = "android.app.Application";
687 }
688
689 try {
690 java.lang.ClassLoader cl = getClassLoader();
Narayan Kamath8091edb2014-10-15 11:38:44 +0100691 if (!mPackageName.equals("android")) {
692 initializeJavaContextClassLoader();
693 }
Jeff Browndefd4a62014-03-10 21:24:37 -0700694 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700695 app = mActivityThread.mInstrumentation.newApplication(
696 cl, appClass, appContext);
697 appContext.setOuterContext(app);
698 } catch (Exception e) {
699 if (!mActivityThread.mInstrumentation.onException(app, e)) {
700 throw new RuntimeException(
701 "Unable to instantiate application " + appClass
702 + ": " + e.toString(), e);
703 }
704 }
705 mActivityThread.mAllApplications.add(app);
706 mApplication = app;
707
708 if (instrumentation != null) {
709 try {
710 instrumentation.callApplicationOnCreate(app);
711 } catch (Exception e) {
712 if (!instrumentation.onException(app, e)) {
713 throw new RuntimeException(
714 "Unable to create application " + app.getClass().getName()
715 + ": " + e.toString(), e);
716 }
717 }
718 }
Adam Lesinskide898ff2014-01-29 18:20:45 -0800719
720 // Rewrite the R 'constants' for all library apks.
721 SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
722 .getAssignedPackageIdentifiers();
723 final int N = packageIdentifiers.size();
724 for (int i = 0; i < N; i++) {
725 final int id = packageIdentifiers.keyAt(i);
726 if (id == 0x01 || id == 0x7f) {
727 continue;
728 }
729
730 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
731 }
732
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700733 return app;
734 }
735
Adam Lesinskide898ff2014-01-29 18:20:45 -0800736 private void rewriteRValues(ClassLoader cl, String packageName, int id) {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700737 final Class<?> rClazz;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800738 try {
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700739 rClazz = cl.loadClass(packageName + ".R");
740 } catch (ClassNotFoundException e) {
741 // This is not necessarily an error, as some packages do not ship with resources
742 // (or they do not need rewriting).
Adam Lesinski1e4663852014-08-15 14:47:28 -0700743 Log.i(TAG, "No resource references to update in package " + packageName);
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700744 return;
745 }
746
Adam Lesinski1e4663852014-08-15 14:47:28 -0700747 final Method callback;
Adam Lesinski2cb761e2014-08-15 13:59:02 -0700748 try {
Adam Lesinski1e4663852014-08-15 14:47:28 -0700749 callback = rClazz.getMethod("onResourcesLoaded", int.class);
750 } catch (NoSuchMethodException e) {
751 // No rewriting to be done.
752 return;
Adam Lesinskide898ff2014-01-29 18:20:45 -0800753 }
Adam Lesinski1e4663852014-08-15 14:47:28 -0700754
755 Throwable cause;
756 try {
757 callback.invoke(null, id);
758 return;
759 } catch (IllegalAccessException e) {
760 cause = e;
761 } catch (InvocationTargetException e) {
762 cause = e.getCause();
763 }
764
765 throw new RuntimeException("Failed to rewrite resource references for " + packageName,
766 cause);
Adam Lesinskide898ff2014-01-29 18:20:45 -0800767 }
768
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700769 public void removeContextRegistrations(Context context,
770 String who, String what) {
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800771 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800772 synchronized (mReceivers) {
773 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
774 mReceivers.remove(context);
775 if (rmap != null) {
776 for (int i = 0; i < rmap.size(); i++) {
777 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
778 IntentReceiverLeaked leak = new IntentReceiverLeaked(
779 what + " " + who + " has leaked IntentReceiver "
780 + rd.getIntentReceiver() + " that was " +
781 "originally registered here. Are you missing a " +
782 "call to unregisterReceiver()?");
783 leak.setStackTrace(rd.getLocation().getStackTrace());
784 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
785 if (reportRegistrationLeaks) {
786 StrictMode.onIntentReceiverLeaked(leak);
787 }
788 try {
789 ActivityManagerNative.getDefault().unregisterReceiver(
790 rd.getIIntentReceiver());
791 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700792 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800793 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700794 }
795 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800796 mUnregisteredReceivers.remove(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700797 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800798
799 synchronized (mServices) {
800 //Slog.i(TAG, "Receiver registrations: " + mReceivers);
801 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
802 mServices.remove(context);
803 if (smap != null) {
804 for (int i = 0; i < smap.size(); i++) {
805 LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
806 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
807 what + " " + who + " has leaked ServiceConnection "
808 + sd.getServiceConnection() + " that was originally bound here");
809 leak.setStackTrace(sd.getLocation().getStackTrace());
810 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
811 if (reportRegistrationLeaks) {
812 StrictMode.onServiceConnectionLeaked(leak);
813 }
814 try {
815 ActivityManagerNative.getDefault().unbindService(
816 sd.getIServiceConnection());
817 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700818 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -0800819 }
820 sd.doForget();
Jeff Sharkeyd7026f12012-03-01 20:50:32 -0800821 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700822 }
Adam Lesinski23d40c42014-11-20 11:58:21 -0800823 mUnboundServices.remove(context);
824 //Slog.i(TAG, "Service registrations: " + mServices);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700825 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700826 }
827
828 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
829 Context context, Handler handler,
830 Instrumentation instrumentation, boolean registered) {
831 synchronized (mReceivers) {
832 LoadedApk.ReceiverDispatcher rd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700833 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700834 if (registered) {
835 map = mReceivers.get(context);
836 if (map != null) {
837 rd = map.get(r);
838 }
839 }
840 if (rd == null) {
841 rd = new ReceiverDispatcher(r, context, handler,
842 instrumentation, registered);
843 if (registered) {
844 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700845 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700846 mReceivers.put(context, map);
847 }
848 map.put(r, rd);
849 }
850 } else {
851 rd.validate(context, handler);
852 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800853 rd.mForgotten = false;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700854 return rd.getIIntentReceiver();
855 }
856 }
857
858 public IIntentReceiver forgetReceiverDispatcher(Context context,
859 BroadcastReceiver r) {
860 synchronized (mReceivers) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700861 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700862 LoadedApk.ReceiverDispatcher rd = null;
863 if (map != null) {
864 rd = map.get(r);
865 if (rd != null) {
866 map.remove(r);
867 if (map.size() == 0) {
868 mReceivers.remove(context);
869 }
870 if (r.getDebugUnregister()) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700871 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700872 = mUnregisteredReceivers.get(context);
873 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700874 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700875 mUnregisteredReceivers.put(context, holder);
876 }
877 RuntimeException ex = new IllegalArgumentException(
878 "Originally unregistered here:");
879 ex.fillInStackTrace();
880 rd.setUnregisterLocation(ex);
881 holder.put(r, rd);
882 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800883 rd.mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700884 return rd.getIIntentReceiver();
885 }
886 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700887 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700888 = mUnregisteredReceivers.get(context);
889 if (holder != null) {
890 rd = holder.get(r);
891 if (rd != null) {
892 RuntimeException ex = rd.getUnregisterLocation();
893 throw new IllegalArgumentException(
894 "Unregistering Receiver " + r
895 + " that was already unregistered", ex);
896 }
897 }
898 if (context == null) {
899 throw new IllegalStateException("Unbinding Receiver " + r
900 + " from Context that is no longer in use: " + context);
901 } else {
902 throw new IllegalArgumentException("Receiver not registered: " + r);
903 }
904
905 }
906 }
907
908 static final class ReceiverDispatcher {
909
910 final static class InnerReceiver extends IIntentReceiver.Stub {
911 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
912 final LoadedApk.ReceiverDispatcher mStrongRef;
913
914 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
915 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
916 mStrongRef = strong ? rd : null;
917 }
Dianne Hackborn20e80982012-08-31 19:00:44 -0700918 public void performReceive(Intent intent, int resultCode, String data,
919 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700920 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
921 if (ActivityThread.DEBUG_BROADCAST) {
922 int seq = intent.getIntExtra("seq", -1);
923 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
924 + " to " + (rd != null ? rd.mReceiver : null));
925 }
926 if (rd != null) {
927 rd.performReceive(intent, resultCode, data, extras,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700928 ordered, sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700929 } else {
930 // The activity manager dispatched a broadcast to a registered
931 // receiver in this process, but before it could be delivered the
932 // receiver was unregistered. Acknowledge the broadcast on its
933 // behalf so that the system's broadcast sequence can continue.
934 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
935 "Finishing broadcast to unregistered receiver");
936 IActivityManager mgr = ActivityManagerNative.getDefault();
937 try {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -0400938 if (extras != null) {
939 extras.setAllowFds(false);
940 }
riddle_hsu1f5ac4d2015-01-03 15:38:21 +0800941 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700942 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700943 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700944 }
945 }
946 }
947 }
948
949 final IIntentReceiver.Stub mIIntentReceiver;
950 final BroadcastReceiver mReceiver;
951 final Context mContext;
952 final Handler mActivityThread;
953 final Instrumentation mInstrumentation;
954 final boolean mRegistered;
955 final IntentReceiverLeaked mLocation;
956 RuntimeException mUnregisterLocation;
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800957 boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700958
Dianne Hackborne829fef2010-10-26 17:44:01 -0700959 final class Args extends BroadcastReceiver.PendingResult implements Runnable {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700960 private Intent mCurIntent;
Dianne Hackborne829fef2010-10-26 17:44:01 -0700961 private final boolean mOrdered;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700962
Dianne Hackborne829fef2010-10-26 17:44:01 -0700963 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
Dianne Hackborn20e80982012-08-31 19:00:44 -0700964 boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700965 super(resultCode, resultData, resultExtras,
riddle_hsu1f5ac4d2015-01-03 15:38:21 +0800966 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
967 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
Dianne Hackborne829fef2010-10-26 17:44:01 -0700968 mCurIntent = intent;
969 mOrdered = ordered;
970 }
971
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700972 public void run() {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700973 final BroadcastReceiver receiver = mReceiver;
974 final boolean ordered = mOrdered;
975
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700976 if (ActivityThread.DEBUG_BROADCAST) {
977 int seq = mCurIntent.getIntExtra("seq", -1);
978 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
979 + " seq=" + seq + " to " + mReceiver);
980 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
Dianne Hackborne829fef2010-10-26 17:44:01 -0700981 + " mOrderedHint=" + ordered);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700982 }
983
Dianne Hackborne829fef2010-10-26 17:44:01 -0700984 final IActivityManager mgr = ActivityManagerNative.getDefault();
985 final Intent intent = mCurIntent;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700986 mCurIntent = null;
987
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -0800988 if (receiver == null || mForgotten) {
Dianne Hackborne829fef2010-10-26 17:44:01 -0700989 if (mRegistered && ordered) {
990 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
991 "Finishing null broadcast to " + mReceiver);
992 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700993 }
994 return;
995 }
996
Dianne Hackborn1ded0b12012-04-26 14:14:50 -0700997 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700998 try {
999 ClassLoader cl = mReceiver.getClass().getClassLoader();
1000 intent.setExtrasClassLoader(cl);
Dianne Hackborne829fef2010-10-26 17:44:01 -07001001 setExtrasClassLoader(cl);
1002 receiver.setPendingResult(this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001003 receiver.onReceive(mContext, intent);
1004 } catch (Exception e) {
Dianne Hackborne829fef2010-10-26 17:44:01 -07001005 if (mRegistered && ordered) {
1006 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1007 "Finishing failed broadcast to " + mReceiver);
1008 sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001009 }
1010 if (mInstrumentation == null ||
1011 !mInstrumentation.onException(mReceiver, e)) {
Dianne Hackborn1ded0b12012-04-26 14:14:50 -07001012 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001013 throw new RuntimeException(
1014 "Error receiving broadcast " + intent
1015 + " in " + mReceiver, e);
1016 }
1017 }
Dianne Hackborne829fef2010-10-26 17:44:01 -07001018
1019 if (receiver.getPendingResult() != null) {
1020 finish();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001021 }
Dianne Hackborn1ded0b12012-04-26 14:14:50 -07001022 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001023 }
1024 }
1025
1026 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
1027 Handler activityThread, Instrumentation instrumentation,
1028 boolean registered) {
1029 if (activityThread == null) {
1030 throw new NullPointerException("Handler must not be null");
1031 }
1032
1033 mIIntentReceiver = new InnerReceiver(this, !registered);
1034 mReceiver = receiver;
1035 mContext = context;
1036 mActivityThread = activityThread;
1037 mInstrumentation = instrumentation;
1038 mRegistered = registered;
1039 mLocation = new IntentReceiverLeaked(null);
1040 mLocation.fillInStackTrace();
1041 }
1042
1043 void validate(Context context, Handler activityThread) {
1044 if (mContext != context) {
1045 throw new IllegalStateException(
1046 "Receiver " + mReceiver +
1047 " registered with differing Context (was " +
1048 mContext + " now " + context + ")");
1049 }
1050 if (mActivityThread != activityThread) {
1051 throw new IllegalStateException(
1052 "Receiver " + mReceiver +
1053 " registered with differing handler (was " +
1054 mActivityThread + " now " + activityThread + ")");
1055 }
1056 }
1057
1058 IntentReceiverLeaked getLocation() {
1059 return mLocation;
1060 }
1061
1062 BroadcastReceiver getIntentReceiver() {
1063 return mReceiver;
1064 }
1065
1066 IIntentReceiver getIIntentReceiver() {
1067 return mIIntentReceiver;
1068 }
1069
1070 void setUnregisterLocation(RuntimeException ex) {
1071 mUnregisterLocation = ex;
1072 }
1073
1074 RuntimeException getUnregisterLocation() {
1075 return mUnregisterLocation;
1076 }
1077
Dianne Hackborn20e80982012-08-31 19:00:44 -07001078 public void performReceive(Intent intent, int resultCode, String data,
1079 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001080 if (ActivityThread.DEBUG_BROADCAST) {
1081 int seq = intent.getIntExtra("seq", -1);
1082 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
1083 + " to " + mReceiver);
1084 }
Dianne Hackborn20e80982012-08-31 19:00:44 -07001085 Args args = new Args(intent, resultCode, data, extras, ordered,
1086 sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001087 if (!mActivityThread.post(args)) {
1088 if (mRegistered && ordered) {
1089 IActivityManager mgr = ActivityManagerNative.getDefault();
Dianne Hackborne829fef2010-10-26 17:44:01 -07001090 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1091 "Finishing sync broadcast to " + mReceiver);
1092 args.sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001093 }
1094 }
1095 }
1096
1097 }
1098
1099 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1100 Context context, Handler handler, int flags) {
1101 synchronized (mServices) {
1102 LoadedApk.ServiceDispatcher sd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001103 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001104 if (map != null) {
1105 sd = map.get(c);
1106 }
1107 if (sd == null) {
1108 sd = new ServiceDispatcher(c, context, handler, flags);
1109 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001110 map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001111 mServices.put(context, map);
1112 }
1113 map.put(c, sd);
1114 } else {
1115 sd.validate(context, handler);
1116 }
1117 return sd.getIServiceConnection();
1118 }
1119 }
1120
1121 public final IServiceConnection forgetServiceDispatcher(Context context,
1122 ServiceConnection c) {
1123 synchronized (mServices) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001124 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001125 = mServices.get(context);
1126 LoadedApk.ServiceDispatcher sd = null;
1127 if (map != null) {
1128 sd = map.get(c);
1129 if (sd != null) {
1130 map.remove(c);
1131 sd.doForget();
1132 if (map.size() == 0) {
1133 mServices.remove(context);
1134 }
1135 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001136 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001137 = mUnboundServices.get(context);
1138 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001139 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001140 mUnboundServices.put(context, holder);
1141 }
1142 RuntimeException ex = new IllegalArgumentException(
1143 "Originally unbound here:");
1144 ex.fillInStackTrace();
1145 sd.setUnbindLocation(ex);
1146 holder.put(c, sd);
1147 }
1148 return sd.getIServiceConnection();
1149 }
1150 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001151 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001152 = mUnboundServices.get(context);
1153 if (holder != null) {
1154 sd = holder.get(c);
1155 if (sd != null) {
1156 RuntimeException ex = sd.getUnbindLocation();
1157 throw new IllegalArgumentException(
1158 "Unbinding Service " + c
1159 + " that was already unbound", ex);
1160 }
1161 }
1162 if (context == null) {
1163 throw new IllegalStateException("Unbinding Service " + c
1164 + " from Context that is no longer in use: " + context);
1165 } else {
1166 throw new IllegalArgumentException("Service not registered: " + c);
1167 }
1168 }
1169 }
1170
1171 static final class ServiceDispatcher {
1172 private final ServiceDispatcher.InnerConnection mIServiceConnection;
1173 private final ServiceConnection mConnection;
1174 private final Context mContext;
1175 private final Handler mActivityThread;
1176 private final ServiceConnectionLeaked mLocation;
1177 private final int mFlags;
1178
1179 private RuntimeException mUnbindLocation;
1180
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001181 private boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001182
1183 private static class ConnectionInfo {
1184 IBinder binder;
1185 IBinder.DeathRecipient deathMonitor;
1186 }
1187
1188 private static class InnerConnection extends IServiceConnection.Stub {
1189 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1190
1191 InnerConnection(LoadedApk.ServiceDispatcher sd) {
1192 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1193 }
1194
1195 public void connected(ComponentName name, IBinder service) throws RemoteException {
1196 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1197 if (sd != null) {
1198 sd.connected(name, service);
1199 }
1200 }
1201 }
1202
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001203 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1204 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001205
1206 ServiceDispatcher(ServiceConnection conn,
1207 Context context, Handler activityThread, int flags) {
1208 mIServiceConnection = new InnerConnection(this);
1209 mConnection = conn;
1210 mContext = context;
1211 mActivityThread = activityThread;
1212 mLocation = new ServiceConnectionLeaked(null);
1213 mLocation.fillInStackTrace();
1214 mFlags = flags;
1215 }
1216
1217 void validate(Context context, Handler activityThread) {
1218 if (mContext != context) {
1219 throw new RuntimeException(
1220 "ServiceConnection " + mConnection +
1221 " registered with differing Context (was " +
1222 mContext + " now " + context + ")");
1223 }
1224 if (mActivityThread != activityThread) {
1225 throw new RuntimeException(
1226 "ServiceConnection " + mConnection +
1227 " registered with differing handler (was " +
1228 mActivityThread + " now " + activityThread + ")");
1229 }
1230 }
1231
1232 void doForget() {
1233 synchronized(this) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001234 for (int i=0; i<mActiveConnections.size(); i++) {
1235 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001236 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1237 }
1238 mActiveConnections.clear();
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001239 mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001240 }
1241 }
1242
1243 ServiceConnectionLeaked getLocation() {
1244 return mLocation;
1245 }
1246
1247 ServiceConnection getServiceConnection() {
1248 return mConnection;
1249 }
1250
1251 IServiceConnection getIServiceConnection() {
1252 return mIServiceConnection;
1253 }
1254
1255 int getFlags() {
1256 return mFlags;
1257 }
1258
1259 void setUnbindLocation(RuntimeException ex) {
1260 mUnbindLocation = ex;
1261 }
1262
1263 RuntimeException getUnbindLocation() {
1264 return mUnbindLocation;
1265 }
1266
1267 public void connected(ComponentName name, IBinder service) {
1268 if (mActivityThread != null) {
1269 mActivityThread.post(new RunConnection(name, service, 0));
1270 } else {
1271 doConnected(name, service);
1272 }
1273 }
1274
1275 public void death(ComponentName name, IBinder service) {
1276 ServiceDispatcher.ConnectionInfo old;
1277
1278 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001279 old = mActiveConnections.remove(name);
1280 if (old == null || old.binder != service) {
1281 // Death for someone different than who we last
1282 // reported... just ignore it.
1283 return;
1284 }
1285 old.binder.unlinkToDeath(old.deathMonitor, 0);
1286 }
1287
1288 if (mActivityThread != null) {
1289 mActivityThread.post(new RunConnection(name, service, 1));
1290 } else {
1291 doDeath(name, service);
1292 }
1293 }
1294
1295 public void doConnected(ComponentName name, IBinder service) {
1296 ServiceDispatcher.ConnectionInfo old;
1297 ServiceDispatcher.ConnectionInfo info;
1298
1299 synchronized (this) {
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001300 if (mForgotten) {
1301 // We unbound before receiving the connection; ignore
1302 // any connection received.
1303 return;
1304 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001305 old = mActiveConnections.get(name);
1306 if (old != null && old.binder == service) {
1307 // Huh, already have this one. Oh well!
1308 return;
1309 }
1310
1311 if (service != null) {
1312 // A new service is being connected... set it all up.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001313 info = new ConnectionInfo();
1314 info.binder = service;
1315 info.deathMonitor = new DeathMonitor(name, service);
1316 try {
1317 service.linkToDeath(info.deathMonitor, 0);
1318 mActiveConnections.put(name, info);
1319 } catch (RemoteException e) {
1320 // This service was dead before we got it... just
1321 // don't do anything with it.
1322 mActiveConnections.remove(name);
1323 return;
1324 }
1325
1326 } else {
1327 // The named service is being disconnected... clean up.
1328 mActiveConnections.remove(name);
1329 }
1330
1331 if (old != null) {
1332 old.binder.unlinkToDeath(old.deathMonitor, 0);
1333 }
1334 }
1335
1336 // If there was an old service, it is not disconnected.
1337 if (old != null) {
1338 mConnection.onServiceDisconnected(name);
1339 }
1340 // If there is a new service, it is now connected.
1341 if (service != null) {
1342 mConnection.onServiceConnected(name, service);
1343 }
1344 }
1345
1346 public void doDeath(ComponentName name, IBinder service) {
1347 mConnection.onServiceDisconnected(name);
1348 }
1349
1350 private final class RunConnection implements Runnable {
1351 RunConnection(ComponentName name, IBinder service, int command) {
1352 mName = name;
1353 mService = service;
1354 mCommand = command;
1355 }
1356
1357 public void run() {
1358 if (mCommand == 0) {
1359 doConnected(mName, mService);
1360 } else if (mCommand == 1) {
1361 doDeath(mName, mService);
1362 }
1363 }
1364
1365 final ComponentName mName;
1366 final IBinder mService;
1367 final int mCommand;
1368 }
1369
1370 private final class DeathMonitor implements IBinder.DeathRecipient
1371 {
1372 DeathMonitor(ComponentName name, IBinder service) {
1373 mName = name;
1374 mService = service;
1375 }
1376
1377 public void binderDied() {
1378 death(mName, mService);
1379 }
1380
1381 final ComponentName mName;
1382 final IBinder mService;
1383 }
1384 }
1385}