blob: 26f498087786319109ca135caa52899cf72a272f [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
Adam Lesinskid33ef562017-01-19 14:49:59 -080019import android.annotation.NonNull;
20import android.annotation.Nullable;
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;
Adam Lesinski1665d0f2017-03-10 14:46:57 -080030import android.content.pm.PackageManager.NameNotFoundException;
31import android.content.pm.split.SplitDependencyLoader;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070032import android.content.res.AssetManager;
33import android.content.res.CompatibilityInfo;
Jeff Hamilton7541ca4d2017-10-24 15:20:43 -040034import android.content.res.Configuration;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070035import android.content.res.Resources;
Adam Lesinski4e862812016-11-21 16:02:24 -080036import android.os.Build;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.os.Bundle;
Calin Juravle2a727d72016-04-15 19:33:46 +010038import android.os.Environment;
Jeff Sharkey15447792015-11-05 16:18:51 -080039import android.os.FileUtils;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070040import android.os.Handler;
41import android.os.IBinder;
42import android.os.Process;
43import android.os.RemoteException;
Brad Fitzpatrick624d50f2010-11-09 14:25:12 -080044import android.os.StrictMode;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060045import android.os.SystemProperties;
Dianne Hackborn1ded0b12012-04-26 14:14:50 -070046import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070047import android.os.UserHandle;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060048import android.text.TextUtils;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070049import android.util.AndroidRuntimeException;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060050import android.util.ArrayMap;
Adam Lesinski2cb761e2014-08-15 13:59:02 -070051import android.util.Log;
Jeff Hamilton7541ca4d2017-10-24 15:20:43 -040052import android.util.LogPrinter;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070053import android.util.Slog;
Adam Lesinskide898ff2014-01-29 18:20:45 -080054import android.util.SparseArray;
Jeff Browna492c3a2012-08-23 19:48:44 -070055import android.view.Display;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060056import android.view.DisplayAdjustments;
Adam Lesinski4e862812016-11-21 16:02:24 -080057import com.android.internal.util.ArrayUtils;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +010058import dalvik.system.VMRuntime;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070059import java.io.File;
60import java.io.IOException;
61import java.io.InputStream;
62import java.lang.ref.WeakReference;
Adam Lesinski1e4663852014-08-15 14:47:28 -070063import java.lang.reflect.InvocationTargetException;
64import java.lang.reflect.Method;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070065import java.net.URL;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070066import java.util.ArrayList;
Adam Lesinski4e862812016-11-21 16:02:24 -080067import java.util.Arrays;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070068import java.util.Collections;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070069import java.util.Enumeration;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060070import java.util.List;
Narayan Kamath20531682014-07-14 13:18:43 +010071import java.util.Objects;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070072
73final 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 Hackborn94846032017-03-31 17:55:23 -070090 static final String TAG = "LoadedApk";
91 static final boolean DEBUG = false;
Amith Yamasani742a6712011-05-04 14:49:28 -070092
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;
Todd Kennedy39bfee52016-02-24 10:28:21 -080098 private String[] mOverlayDirs;
Todd Kennedy39bfee52016-02-24 10:28:21 -080099 private String mDataDir;
100 private String mLibDir;
101 private File mDataDirFile;
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600102 private File mDeviceProtectedDataDirFile;
103 private File mCredentialProtectedDataDirFile;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700104 private final ClassLoader mBaseClassLoader;
105 private final boolean mSecurityViolation;
106 private final boolean mIncludeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700107 private final boolean mRegisterPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700108 private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800109 /** WARNING: This may change. Don't hold external references to it. */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700110 Resources mResources;
111 private ClassLoader mClassLoader;
112 private Application mApplication;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700113
Adam Lesinski4e862812016-11-21 16:02:24 -0800114 private String[] mSplitNames;
115 private String[] mSplitAppDirs;
116 private String[] mSplitResDirs;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100117 private String[] mSplitClassLoaderNames;
Adam Lesinski4e862812016-11-21 16:02:24 -0800118
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700119 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
Adam Lesinski4e862812016-11-21 16:02:24 -0800120 = new ArrayMap<>();
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700121 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
Adam Lesinski4e862812016-11-21 16:02:24 -0800122 = new ArrayMap<>();
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700123 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
Adam Lesinski4e862812016-11-21 16:02:24 -0800124 = new ArrayMap<>();
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700125 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
Adam Lesinski4e862812016-11-21 16:02:24 -0800126 = new ArrayMap<>();
Jason Monka80bfb52017-11-16 17:15:37 -0500127 private AppComponentFactory mAppComponentFactory;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700128
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700129 Application getApplication() {
130 return mApplication;
131 }
132
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700133 /**
134 * Create information about a new .apk
135 *
136 * NOTE: This constructor is called with ActivityThread's lock held,
137 * so MUST NOT call back out to the activity manager.
138 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700139 public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
Jeff Browndefd4a62014-03-10 21:24:37 -0700140 CompatibilityInfo compatInfo, ClassLoader baseLoader,
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700141 boolean securityViolation, boolean includeCode, boolean registerPackage) {
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100142
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700143 mActivityThread = activityThread;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800144 setApplicationInfo(aInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700145 mPackageName = aInfo.packageName;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700146 mBaseClassLoader = baseLoader;
147 mSecurityViolation = securityViolation;
148 mIncludeCode = includeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700149 mRegisterPackage = registerPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700150 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
Jason Monka80bfb52017-11-16 17:15:37 -0500151 mAppComponentFactory = createAppFactory(mApplicationInfo, mBaseClassLoader);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700152 }
153
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100154 private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) {
155 // If we're dealing with a multi-arch application that has both
156 // 32 and 64 bit shared libraries, we might need to choose the secondary
157 // depending on what the current runtime's instruction set is.
158 if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
159 final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
jgu214741cd92014-12-17 17:23:29 -0500160
161 // Get the instruction set that the libraries of secondary Abi is supported.
162 // In presence of a native bridge this might be different than the one secondary Abi used.
163 String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
164 final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
165 secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100166
167 // If the runtimeIsa is the same as the primary isa, then we do nothing.
168 // Everything will be set up correctly because info.nativeLibraryDir will
169 // correspond to the right ISA.
170 if (runtimeIsa.equals(secondaryIsa)) {
171 final ApplicationInfo modified = new ApplicationInfo(info);
172 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
Dmitriy Ivanove56b3f62015-06-05 22:00:13 -0700173 modified.primaryCpuAbi = modified.secondaryCpuAbi;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100174 return modified;
175 }
176 }
177
178 return info;
179 }
180
Jeff Browndefd4a62014-03-10 21:24:37 -0700181 /**
182 * Create information about the system package.
183 * Must call {@link #installSystemApplicationInfo} later.
184 */
185 LoadedApk(ActivityThread activityThread) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700186 mActivityThread = activityThread;
Jeff Browndefd4a62014-03-10 21:24:37 -0700187 mApplicationInfo = new ApplicationInfo();
188 mApplicationInfo.packageName = "android";
189 mPackageName = "android";
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700190 mAppDir = null;
191 mResDir = null;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700192 mSplitAppDirs = null;
193 mSplitResDirs = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100194 mSplitClassLoaderNames = null;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100195 mOverlayDirs = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700196 mDataDir = null;
197 mDataDirFile = null;
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600198 mDeviceProtectedDataDirFile = null;
199 mCredentialProtectedDataDirFile = null;
Kenny Root85387d72010-08-26 10:13:11 -0700200 mLibDir = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700201 mBaseClassLoader = null;
202 mSecurityViolation = false;
203 mIncludeCode = true;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700204 mRegisterPackage = false;
Jeff Browndefd4a62014-03-10 21:24:37 -0700205 mClassLoader = ClassLoader.getSystemClassLoader();
206 mResources = Resources.getSystem();
Jason Monka80bfb52017-11-16 17:15:37 -0500207 mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader);
Jeff Browndefd4a62014-03-10 21:24:37 -0700208 }
209
210 /**
211 * Sets application info about the system package.
212 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100213 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
Jeff Browndefd4a62014-03-10 21:24:37 -0700214 assert info.packageName.equals("android");
215 mApplicationInfo = info;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100216 mClassLoader = classLoader;
Jason Monka80bfb52017-11-16 17:15:37 -0500217 mAppComponentFactory = createAppFactory(info, classLoader);
218 }
219
220 private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) {
221 if (appInfo.appComponentFactory != null) {
222 try {
223 return (AppComponentFactory) cl.loadClass(appInfo.appComponentFactory)
224 .newInstance();
225 } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
226 Slog.e(TAG, "Unable to instantiate appComponentFactory", e);
227 }
228 }
229 return AppComponentFactory.DEFAULT;
230 }
231
232 public AppComponentFactory getAppFactory() {
233 return mAppComponentFactory;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700234 }
235
236 public String getPackageName() {
237 return mPackageName;
238 }
239
240 public ApplicationInfo getApplicationInfo() {
241 return mApplicationInfo;
242 }
243
Jeff Sharkey369f5092016-02-29 11:16:21 -0700244 public int getTargetSdkVersion() {
245 return mApplicationInfo.targetSdkVersion;
246 }
247
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700248 public boolean isSecurityViolation() {
249 return mSecurityViolation;
250 }
251
Craig Mautner48d0d182013-06-11 07:53:06 -0700252 public CompatibilityInfo getCompatibilityInfo() {
253 return mDisplayAdjustments.getCompatibilityInfo();
254 }
255
256 public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
257 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
258 }
259
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700260 /**
261 * Gets the array of shared libraries that are listed as
262 * used by the given package.
263 *
264 * @param packageName the name of the package (note: not its
265 * file name)
266 * @return null-ok; the array of shared libraries, each one
267 * a fully-qualified path
268 */
269 private static String[] getLibrariesFor(String packageName) {
270 ApplicationInfo ai = null;
271 try {
272 ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700273 PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700274 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700275 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700276 }
277
278 if (ai == null) {
279 return null;
280 }
281
282 return ai.sharedLibraryFiles;
283 }
284
Adam Lesinskid33ef562017-01-19 14:49:59 -0800285 /**
286 * Update the ApplicationInfo for an app. If oldPaths is null, all the paths are considered
287 * new.
288 * @param aInfo The new ApplicationInfo to use for this LoadedApk
289 * @param oldPaths The code paths for the old ApplicationInfo object. null means no paths can
290 * be reused.
291 */
292 public void updateApplicationInfo(@NonNull ApplicationInfo aInfo,
293 @Nullable List<String> oldPaths) {
Todd Kennedy39bfee52016-02-24 10:28:21 -0800294 setApplicationInfo(aInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700295
Todd Kennedy39bfee52016-02-24 10:28:21 -0800296 final List<String> newPaths = new ArrayList<>();
Dimitry Ivanov638d8102017-02-22 15:39:42 -0800297 makePaths(mActivityThread, aInfo, newPaths);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800298 final List<String> addedPaths = new ArrayList<>(newPaths.size());
299
300 if (oldPaths != null) {
301 for (String path : newPaths) {
302 final String apkName = path.substring(path.lastIndexOf(File.separator));
303 boolean match = false;
304 for (String oldPath : oldPaths) {
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800305 final String oldApkName = oldPath.substring(oldPath.lastIndexOf(File.separator));
Todd Kennedy39bfee52016-02-24 10:28:21 -0800306 if (apkName.equals(oldApkName)) {
307 match = true;
308 break;
309 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700310 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800311 if (!match) {
312 addedPaths.add(path);
313 }
314 }
315 } else {
316 addedPaths.addAll(newPaths);
317 }
318 synchronized (this) {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700319 createOrUpdateClassLoaderLocked(addedPaths);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800320 if (mResources != null) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800321 final String[] splitPaths;
322 try {
323 splitPaths = getSplitPaths(null);
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800324 } catch (NameNotFoundException e) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800325 // This should NEVER fail.
326 throw new AssertionError("null split not found");
327 }
328
329 mResources = ResourcesManager.getInstance().getResources(null, mResDir,
Adam Lesinski0e618832017-02-07 11:40:12 -0800330 splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
Adam Lesinski4e862812016-11-21 16:02:24 -0800331 Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
332 getClassLoader());
Todd Kennedy39bfee52016-02-24 10:28:21 -0800333 }
334 }
Jason Monka80bfb52017-11-16 17:15:37 -0500335 mAppComponentFactory = createAppFactory(aInfo, mClassLoader);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800336 }
337
338 private void setApplicationInfo(ApplicationInfo aInfo) {
339 final int myUid = Process.myUid();
340 aInfo = adjustNativeLibraryPaths(aInfo);
341 mApplicationInfo = aInfo;
342 mAppDir = aInfo.sourceDir;
343 mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800344 mOverlayDirs = aInfo.resourceDirs;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800345 mDataDir = aInfo.dataDir;
346 mLibDir = aInfo.nativeLibraryDir;
347 mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600348 mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir);
349 mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir);
Adam Lesinski4e862812016-11-21 16:02:24 -0800350
351 mSplitNames = aInfo.splitNames;
352 mSplitAppDirs = aInfo.splitSourceDirs;
353 mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100354 mSplitClassLoaderNames = aInfo.splitClassLoaderNames;
Adam Lesinski4e862812016-11-21 16:02:24 -0800355
356 if (aInfo.requestsIsolatedSplitLoading() && !ArrayUtils.isEmpty(mSplitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800357 mSplitLoader = new SplitDependencyLoaderImpl(aInfo.splitDependencies);
Adam Lesinski4e862812016-11-21 16:02:24 -0800358 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800359 }
360
Dimitry Ivanov638d8102017-02-22 15:39:42 -0800361 public static void makePaths(ActivityThread activityThread,
362 ApplicationInfo aInfo,
363 List<String> outZipPaths) {
364 makePaths(activityThread, false, aInfo, outZipPaths, null);
365 }
366
367 public static void makePaths(ActivityThread activityThread,
368 boolean isBundledApp,
369 ApplicationInfo aInfo,
370 List<String> outZipPaths,
371 List<String> outLibPaths) {
Todd Kennedy39bfee52016-02-24 10:28:21 -0800372 final String appDir = aInfo.sourceDir;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800373 final String libDir = aInfo.nativeLibraryDir;
374 final String[] sharedLibraries = aInfo.sharedLibraryFiles;
375
376 outZipPaths.clear();
377 outZipPaths.add(appDir);
Adam Lesinski4e862812016-11-21 16:02:24 -0800378
379 // Do not load all available splits if the app requested isolated split loading.
380 if (aInfo.splitSourceDirs != null && !aInfo.requestsIsolatedSplitLoading()) {
381 Collections.addAll(outZipPaths, aInfo.splitSourceDirs);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800382 }
383
384 if (outLibPaths != null) {
385 outLibPaths.clear();
386 }
387
388 /*
389 * The following is a bit of a hack to inject
390 * instrumentation into the system: If the app
391 * being started matches one of the instrumentation names,
392 * then we combine both the "instrumentation" and
393 * "instrumented" app into the path, along with the
394 * concatenation of both apps' shared library lists.
395 */
396
Todd Kennedy39bfee52016-02-24 10:28:21 -0800397 String[] instrumentationLibs = null;
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100398 // activityThread will be null when called from the WebView zygote; just assume
399 // no instrumentation applies in this case.
400 if (activityThread != null) {
401 String instrumentationPackageName = activityThread.mInstrumentationPackageName;
402 String instrumentationAppDir = activityThread.mInstrumentationAppDir;
403 String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
404 String instrumentationLibDir = activityThread.mInstrumentationLibDir;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800405
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100406 String instrumentedAppDir = activityThread.mInstrumentedAppDir;
407 String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
408 String instrumentedLibDir = activityThread.mInstrumentedLibDir;
409
410 if (appDir.equals(instrumentationAppDir)
411 || appDir.equals(instrumentedAppDir)) {
412 outZipPaths.clear();
413 outZipPaths.add(instrumentationAppDir);
Adam Lesinski4e862812016-11-21 16:02:24 -0800414
415 // Only add splits if the app did not request isolated split loading.
416 if (!aInfo.requestsIsolatedSplitLoading()) {
417 if (instrumentationSplitAppDirs != null) {
418 Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
419 }
420
421 if (!instrumentationAppDir.equals(instrumentedAppDir)) {
422 outZipPaths.add(instrumentedAppDir);
423 if (instrumentedSplitAppDirs != null) {
424 Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
425 }
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100426 }
Jeff Haoc7b94822016-03-16 15:56:07 -0700427 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800428
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100429 if (outLibPaths != null) {
430 outLibPaths.add(instrumentationLibDir);
431 if (!instrumentationLibDir.equals(instrumentedLibDir)) {
432 outLibPaths.add(instrumentedLibDir);
433 }
434 }
435
436 if (!instrumentedAppDir.equals(instrumentationAppDir)) {
437 instrumentationLibs = getLibrariesFor(instrumentationPackageName);
438 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800439 }
440 }
441
442 if (outLibPaths != null) {
443 if (outLibPaths.isEmpty()) {
444 outLibPaths.add(libDir);
445 }
446
447 // Add path to libraries in apk for current abi. Do this now because more entries
448 // will be added to zipPaths that shouldn't be part of the library path.
449 if (aInfo.primaryCpuAbi != null) {
Alex Light20ed24f2016-04-20 14:07:43 -0700450 // Add fake libs into the library search path if we target prior to N.
Adam Lesinski4e862812016-11-21 16:02:24 -0800451 if (aInfo.targetSdkVersion < Build.VERSION_CODES.N) {
Alex Light20ed24f2016-04-20 14:07:43 -0700452 outLibPaths.add("/system/fake-libs" +
453 (VMRuntime.is64BitAbi(aInfo.primaryCpuAbi) ? "64" : ""));
454 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800455 for (String apk : outZipPaths) {
456 outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
457 }
458 }
459
Dimitry Ivanov638d8102017-02-22 15:39:42 -0800460 if (isBundledApp) {
Todd Kennedy39bfee52016-02-24 10:28:21 -0800461 // Add path to system libraries to libPaths;
462 // Access to system libs should be limited
463 // to bundled applications; this is why updated
464 // system apps are not included.
465 outLibPaths.add(System.getProperty("java.library.path"));
466 }
467 }
468
Jeff Hao090892f2017-04-24 17:37:31 -0700469 // Prepend the shared libraries, maintaining their original order where possible.
Todd Kennedy39bfee52016-02-24 10:28:21 -0800470 if (sharedLibraries != null) {
Jeff Hao090892f2017-04-24 17:37:31 -0700471 int index = 0;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800472 for (String lib : sharedLibraries) {
473 if (!outZipPaths.contains(lib)) {
Jeff Hao090892f2017-04-24 17:37:31 -0700474 outZipPaths.add(index, lib);
475 index++;
Svetoslav Ganov40610e32017-06-20 19:35:51 -0700476 appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800477 }
478 }
479 }
480
481 if (instrumentationLibs != null) {
482 for (String lib : instrumentationLibs) {
483 if (!outZipPaths.contains(lib)) {
484 outZipPaths.add(0, lib);
Svetoslav Ganov40610e32017-06-20 19:35:51 -0700485 appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800486 }
487 }
488 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800489 }
490
Svetoslav Ganov40610e32017-06-20 19:35:51 -0700491 /**
492 * This method appends a path to the appropriate native library folder of a
493 * library if this library is hosted in an APK. This allows support for native
494 * shared libraries. The library API is determined based on the application
495 * ABI.
496 *
497 * @param path Path to the library.
498 * @param applicationInfo The application depending on the library.
499 * @param outLibPaths List to which to add the native lib path if needed.
500 */
501 private static void appendApkLibPathIfNeeded(@NonNull String path,
502 @NonNull ApplicationInfo applicationInfo, @Nullable List<String> outLibPaths) {
503 // Looking at the suffix is a little hacky but a safe and simple solution.
504 // We will be revisiting code in the next release and clean this up.
505 if (outLibPaths != null && applicationInfo.primaryCpuAbi != null && path.endsWith(".apk")) {
506 if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
507 outLibPaths.add(path + "!/lib/" + applicationInfo.primaryCpuAbi);
508 }
509 }
510 }
511
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800512 /*
513 * All indices received by the super class should be shifted by 1 when accessing mSplitNames,
514 * etc. The super class assumes the base APK is index 0, while the PackageManager APIs don't
515 * include the base APK in the list of splits.
516 */
517 private class SplitDependencyLoaderImpl extends SplitDependencyLoader<NameNotFoundException> {
Adam Lesinski4e862812016-11-21 16:02:24 -0800518 private final String[][] mCachedResourcePaths;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800519 private final ClassLoader[] mCachedClassLoaders;
Adam Lesinski4e862812016-11-21 16:02:24 -0800520
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800521 SplitDependencyLoaderImpl(@NonNull SparseArray<int[]> dependencies) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800522 super(dependencies);
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800523 mCachedResourcePaths = new String[mSplitNames.length + 1][];
524 mCachedClassLoaders = new ClassLoader[mSplitNames.length + 1];
Adam Lesinski4e862812016-11-21 16:02:24 -0800525 }
526
527 @Override
528 protected boolean isSplitCached(int splitIdx) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800529 return mCachedClassLoaders[splitIdx] != null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800530 }
531
532 @Override
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800533 protected void constructSplit(int splitIdx, @NonNull int[] configSplitIndices,
534 int parentSplitIdx) throws NameNotFoundException {
Adam Lesinski4e862812016-11-21 16:02:24 -0800535 final ArrayList<String> splitPaths = new ArrayList<>();
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800536 if (splitIdx == 0) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800537 createOrUpdateClassLoaderLocked(null);
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800538 mCachedClassLoaders[0] = mClassLoader;
539
540 // Never add the base resources here, they always get added no matter what.
541 for (int configSplitIdx : configSplitIndices) {
542 splitPaths.add(mSplitResDirs[configSplitIdx - 1]);
543 }
544 mCachedResourcePaths[0] = splitPaths.toArray(new String[splitPaths.size()]);
Adam Lesinski4e862812016-11-21 16:02:24 -0800545 return;
546 }
547
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800548 // Since we handled the special base case above, parentSplitIdx is always valid.
549 final ClassLoader parent = mCachedClassLoaders[parentSplitIdx];
550 mCachedClassLoaders[splitIdx] = ApplicationLoaders.getDefault().getClassLoader(
Narayan Kamathf9419f02017-06-15 11:35:38 +0100551 mSplitAppDirs[splitIdx - 1], getTargetSdkVersion(), false, null, null, parent,
552 mSplitClassLoaderNames[splitIdx - 1]);
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800553
554 Collections.addAll(splitPaths, mCachedResourcePaths[parentSplitIdx]);
555 splitPaths.add(mSplitResDirs[splitIdx - 1]);
556 for (int configSplitIdx : configSplitIndices) {
557 splitPaths.add(mSplitResDirs[configSplitIdx - 1]);
Adam Lesinski4e862812016-11-21 16:02:24 -0800558 }
Adam Lesinski4e862812016-11-21 16:02:24 -0800559 mCachedResourcePaths[splitIdx] = splitPaths.toArray(new String[splitPaths.size()]);
560 }
561
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800562 private int ensureSplitLoaded(String splitName) throws NameNotFoundException {
563 int idx = 0;
564 if (splitName != null) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800565 idx = Arrays.binarySearch(mSplitNames, splitName);
566 if (idx < 0) {
567 throw new PackageManager.NameNotFoundException(
568 "Split name '" + splitName + "' is not installed");
569 }
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800570 idx += 1;
Adam Lesinski4e862812016-11-21 16:02:24 -0800571 }
Adam Lesinski4e862812016-11-21 16:02:24 -0800572 loadDependenciesForSplit(idx);
573 return idx;
574 }
575
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800576 ClassLoader getClassLoaderForSplit(String splitName) throws NameNotFoundException {
577 return mCachedClassLoaders[ensureSplitLoaded(splitName)];
Adam Lesinski4e862812016-11-21 16:02:24 -0800578 }
579
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800580 String[] getSplitPathsForSplit(String splitName) throws NameNotFoundException {
581 return mCachedResourcePaths[ensureSplitLoaded(splitName)];
Adam Lesinski4e862812016-11-21 16:02:24 -0800582 }
583 }
584
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800585 private SplitDependencyLoaderImpl mSplitLoader;
Adam Lesinski4e862812016-11-21 16:02:24 -0800586
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800587 ClassLoader getSplitClassLoader(String splitName) throws NameNotFoundException {
Adam Lesinski4e862812016-11-21 16:02:24 -0800588 if (mSplitLoader == null) {
589 return mClassLoader;
590 }
591 return mSplitLoader.getClassLoaderForSplit(splitName);
592 }
593
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800594 String[] getSplitPaths(String splitName) throws NameNotFoundException {
Adam Lesinski4e862812016-11-21 16:02:24 -0800595 if (mSplitLoader == null) {
596 return mSplitResDirs;
597 }
598 return mSplitLoader.getSplitPathsForSplit(splitName);
599 }
600
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700601 private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
602 if (mPackageName.equals("android")) {
Calin Juravle430ef452016-04-22 17:43:07 +0100603 // Note: This branch is taken for system server and we don't need to setup
604 // jit profiling support.
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700605 if (mClassLoader != null) {
606 // nothing to update
607 return;
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800608 }
609
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700610 if (mBaseClassLoader != null) {
611 mClassLoader = mBaseClassLoader;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800612 } else {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700613 mClassLoader = ClassLoader.getSystemClassLoader();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800614 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700615
616 return;
617 }
618
619 // Avoid the binder call when the package is the current application package.
620 // The activity manager will perform ensure that dexopt is performed before
621 // spinning up the process.
Narayan Kamathbf07e2a2017-03-15 11:37:32 +0000622 if (!Objects.equals(mPackageName, ActivityThread.currentPackageName()) && mIncludeCode) {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700623 try {
Brian Carlstromca82e612016-04-19 23:16:08 -0700624 ActivityThread.getPackageManager().notifyPackageUse(mPackageName,
625 PackageManager.NOTIFY_PACKAGE_USE_CROSS_PACKAGE);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700626 } catch (RemoteException re) {
627 throw re.rethrowFromSystemServer();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800628 }
629 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700630
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700631 if (mRegisterPackage) {
632 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800633 ActivityManager.getService().addPackageDependency(mPackageName);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700634 } catch (RemoteException e) {
635 throw e.rethrowFromSystemServer();
636 }
637 }
638
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700639 // Lists for the elements of zip/code and native libraries.
640 //
641 // Both lists are usually not empty. We expect on average one APK for the zip component,
642 // but shared libraries and splits are not uncommon. We expect at least three elements
643 // for native libraries (app-based, system, vendor). As such, give both some breathing
644 // space and initialize to a small value (instead of incurring growth code).
645 final List<String> zipPaths = new ArrayList<>(10);
646 final List<String> libPaths = new ArrayList<>(10);
Narayan Kamath8995b002016-05-11 20:31:09 +0100647
Jiyong Parkfcad6962017-08-22 10:24:28 +0900648 boolean isBundledApp = mApplicationInfo.isSystemApp()
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700649 && !mApplicationInfo.isUpdatedSystemApp();
Dimitry Ivanovbf3b5f72016-05-03 11:34:58 -0700650
Jiyong Parkfcad6962017-08-22 10:24:28 +0900651 // Vendor apks are treated as bundled only when /vendor/lib is in the default search
652 // paths. If not, they are treated as unbundled; access to system libs is limited.
653 // Having /vendor/lib in the default search paths means that all system processes
654 // are allowed to use any vendor library, which in turn means that system is dependent
655 // on vendor partition. In the contrary, not having /vendor/lib in the default search
656 // paths mean that the two partitions are separated and thus we can treat vendor apks
657 // as unbundled.
658 final String defaultSearchPaths = System.getProperty("java.library.path");
659 final boolean treatVendorApkAsUnbundled = !defaultSearchPaths.contains("/vendor/lib");
Jiyong Park63495c22017-09-15 07:48:06 +0900660 if (mApplicationInfo.getCodePath() != null
Jiyong Park002fdbd2017-02-13 20:50:31 +0900661 && mApplicationInfo.isVendor() && treatVendorApkAsUnbundled) {
Jiyong Parkfcad6962017-08-22 10:24:28 +0900662 isBundledApp = false;
663 }
664
Dimitry Ivanov638d8102017-02-22 15:39:42 -0800665 makePaths(mActivityThread, isBundledApp, mApplicationInfo, zipPaths, libPaths);
666
Dimitry Ivanoveb96b002016-05-10 10:51:40 -0700667 String libraryPermittedPath = mDataDir;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700668 if (isBundledApp) {
669 // This is necessary to grant bundled apps access to
670 // libraries located in subdirectories of /system/lib
Jiyong Parkfcad6962017-08-22 10:24:28 +0900671 libraryPermittedPath += File.pathSeparator + defaultSearchPaths;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700672 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700673
674 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
675
Narayan Kamath8995b002016-05-11 20:31:09 +0100676 // If we're not asked to include code, we construct a classloader that has
677 // no code path included. We still need to set up the library search paths
678 // and permitted path because NativeActivity relies on it (it attempts to
679 // call System.loadLibrary() on a classloader from a LoadedApk with
680 // mIncludeCode == false).
681 if (!mIncludeCode) {
682 if (mClassLoader == null) {
683 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
684 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
Narayan Kamathf9419f02017-06-15 11:35:38 +0100685 "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
686 librarySearchPath, libraryPermittedPath, mBaseClassLoader,
687 null /* classLoaderName */);
Narayan Kamath8995b002016-05-11 20:31:09 +0100688 StrictMode.setThreadPolicy(oldPolicy);
689 }
690
691 return;
692 }
693
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700694 /*
Narayan Kamath8995b002016-05-11 20:31:09 +0100695 * With all the combination done (if necessary, actually create the java class
696 * loader and set up JIT profiling support if necessary.
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700697 *
698 * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils.
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700699 */
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700700 final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
701 TextUtils.join(File.pathSeparator, zipPaths);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700702
Dianne Hackborn94846032017-03-31 17:55:23 -0700703 if (DEBUG) Slog.v(ActivityThread.TAG, "Class path: " + zip +
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700704 ", JNI path: " + librarySearchPath);
705
Calin Juravle430ef452016-04-22 17:43:07 +0100706 boolean needToSetupJitProfiles = false;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700707 if (mClassLoader == null) {
708 // Temporarily disable logging of disk reads on the Looper thread
709 // as this is early and necessary.
710 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
711
712 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
713 mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
Narayan Kamathf9419f02017-06-15 11:35:38 +0100714 libraryPermittedPath, mBaseClassLoader,
715 mApplicationInfo.classLoaderName);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700716
717 StrictMode.setThreadPolicy(oldPolicy);
Calin Juravle430ef452016-04-22 17:43:07 +0100718 // Setup the class loader paths for profiling.
719 needToSetupJitProfiles = true;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700720 }
721
722 if (addedPaths != null && addedPaths.size() > 0) {
723 final String add = TextUtils.join(File.pathSeparator, addedPaths);
724 ApplicationLoaders.getDefault().addPath(mClassLoader, add);
Calin Juravle430ef452016-04-22 17:43:07 +0100725 // Setup the new code paths for profiling.
726 needToSetupJitProfiles = true;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700727 }
Calin Juravle2a727d72016-04-15 19:33:46 +0100728
729 // Setup jit profile support.
Narayan Kamath2d4a2222016-04-25 19:16:56 +0100730 //
Calin Juravle2a727d72016-04-15 19:33:46 +0100731 // It is ok to call this multiple times if the application gets updated with new splits.
732 // The runtime only keeps track of unique code paths and can handle re-registration of
733 // the same code path. There's no need to pass `addedPaths` since any new code paths
734 // are already in `mApplicationInfo`.
Narayan Kamath2d4a2222016-04-25 19:16:56 +0100735 //
736 // It is NOT ok to call this function from the system_server (for any of the packages it
737 // loads code from) so we explicitly disallow it there.
738 if (needToSetupJitProfiles && !ActivityThread.isSystem()) {
Calin Juravle430ef452016-04-22 17:43:07 +0100739 setupJitProfileSupport();
Calin Juravle430ef452016-04-22 17:43:07 +0100740 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800741 }
742
743 public ClassLoader getClassLoader() {
744 synchronized (this) {
745 if (mClassLoader == null) {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700746 createOrUpdateClassLoaderLocked(null /*addedPaths*/);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800747 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700748 return mClassLoader;
749 }
750 }
751
Calin Juravle2a727d72016-04-15 19:33:46 +0100752 // Keep in sync with installd (frameworks/native/cmds/installd/commands.cpp).
753 private static File getPrimaryProfileFile(String packageName) {
754 File profileDir = Environment.getDataProfilesDePackageDirectory(
755 UserHandle.myUserId(), packageName);
756 return new File(profileDir, "primary.prof");
757 }
758
759 private void setupJitProfileSupport() {
760 if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
761 return;
762 }
Calin Juravle126f7802016-05-24 15:23:47 +0100763 // Only set up profile support if the loaded apk has the same uid as the
764 // current process.
765 // Currently, we do not support profiling across different apps.
766 // (e.g. application's uid might be different when the code is
767 // loaded by another app via createApplicationContext)
768 if (mApplicationInfo.uid != Process.myUid()) {
769 return;
770 }
771
Calin Juravle2a727d72016-04-15 19:33:46 +0100772 final List<String> codePaths = new ArrayList<>();
773 if ((mApplicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
774 codePaths.add(mApplicationInfo.sourceDir);
775 }
776 if (mApplicationInfo.splitSourceDirs != null) {
777 Collections.addAll(codePaths, mApplicationInfo.splitSourceDirs);
778 }
779
780 if (codePaths.isEmpty()) {
781 // If there are no code paths there's no need to setup a profile file and register with
782 // the runtime,
783 return;
784 }
785
786 final File profileFile = getPrimaryProfileFile(mPackageName);
Calin Juravle126f7802016-05-24 15:23:47 +0100787
Calin Juravle74f0a342017-03-03 17:04:55 -0800788 VMRuntime.registerAppInfo(profileFile.getPath(),
789 codePaths.toArray(new String[codePaths.size()]));
Calin Juravlef5a7bfc2017-03-13 23:30:30 -0700790
791 // Register the app data directory with the reporter. It will
792 // help deciding whether or not a dex file is the primary apk or a
793 // secondary dex.
794 DexLoadReporter.getInstance().registerAppDataDir(mPackageName, mDataDir);
Calin Juravle2a727d72016-04-15 19:33:46 +0100795 }
796
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700797 /**
798 * Setup value for Thread.getContextClassLoader(). If the
799 * package will not run in in a VM with other packages, we set
800 * the Java context ClassLoader to the
801 * PackageInfo.getClassLoader value. However, if this VM can
802 * contain multiple packages, we intead set the Java context
803 * ClassLoader to a proxy that will warn about the use of Java
804 * context ClassLoaders and then fall through to use the
805 * system ClassLoader.
806 *
807 * <p> Note that this is similar to but not the same as the
808 * android.content.Context.getClassLoader(). While both
809 * context class loaders are typically set to the
810 * PathClassLoader used to load the package archive in the
811 * single application per VM case, a single Android process
812 * may contain several Contexts executing on one thread with
813 * their own logical ClassLoaders while the Java context
814 * ClassLoader is a thread local. This is why in the case when
815 * we have multiple packages per VM we do not set the Java
816 * context ClassLoader to an arbitrary but instead warn the
817 * user to set their own if we detect that they are using a
818 * Java library that expects it to be set.
819 */
820 private void initializeJavaContextClassLoader() {
821 IPackageManager pm = ActivityThread.getPackageManager();
822 android.content.pm.PackageInfo pi;
823 try {
Jeff Sharkeyc7bacab2016-02-09 15:56:11 -0700824 pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
825 UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700826 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700827 throw e.rethrowFromSystemServer();
Dianne Hackborn208d9372013-02-25 13:17:54 -0800828 }
829 if (pi == null) {
830 throw new IllegalStateException("Unable to get package info for "
831 + mPackageName + "; is package not installed?");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700832 }
833 /*
834 * Two possible indications that this package could be
835 * sharing its virtual machine with other packages:
836 *
837 * 1.) the sharedUserId attribute is set in the manifest,
838 * indicating a request to share a VM with other
839 * packages with the same sharedUserId.
840 *
841 * 2.) the application element of the manifest has an
842 * attribute specifying a non-default process name,
843 * indicating the desire to run in another packages VM.
844 */
845 boolean sharedUserIdSet = (pi.sharedUserId != null);
846 boolean processNameNotDefault =
847 (pi.applicationInfo != null &&
848 !mPackageName.equals(pi.applicationInfo.processName));
849 boolean sharable = (sharedUserIdSet || processNameNotDefault);
850 ClassLoader contextClassLoader =
851 (sharable)
852 ? new WarningContextClassLoader()
853 : mClassLoader;
854 Thread.currentThread().setContextClassLoader(contextClassLoader);
855 }
856
857 private static class WarningContextClassLoader extends ClassLoader {
858
859 private static boolean warned = false;
860
861 private void warn(String methodName) {
862 if (warned) {
863 return;
864 }
865 warned = true;
866 Thread.currentThread().setContextClassLoader(getParent());
867 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
868 "The class loader returned by " +
869 "Thread.getContextClassLoader() may fail for processes " +
870 "that host multiple applications. You should explicitly " +
871 "specify a context class loader. For example: " +
872 "Thread.setContextClassLoader(getClass().getClassLoader());");
873 }
874
875 @Override public URL getResource(String resName) {
876 warn("getResource");
877 return getParent().getResource(resName);
878 }
879
880 @Override public Enumeration<URL> getResources(String resName) throws IOException {
881 warn("getResources");
882 return getParent().getResources(resName);
883 }
884
885 @Override public InputStream getResourceAsStream(String resName) {
886 warn("getResourceAsStream");
887 return getParent().getResourceAsStream(resName);
888 }
889
890 @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
891 warn("loadClass");
892 return getParent().loadClass(className);
893 }
894
895 @Override public void setClassAssertionStatus(String cname, boolean enable) {
896 warn("setClassAssertionStatus");
897 getParent().setClassAssertionStatus(cname, enable);
898 }
899
900 @Override public void setPackageAssertionStatus(String pname, boolean enable) {
901 warn("setPackageAssertionStatus");
902 getParent().setPackageAssertionStatus(pname, enable);
903 }
904
905 @Override public void setDefaultAssertionStatus(boolean enable) {
906 warn("setDefaultAssertionStatus");
907 getParent().setDefaultAssertionStatus(enable);
908 }
909
910 @Override public void clearAssertionStatus() {
911 warn("clearAssertionStatus");
912 getParent().clearAssertionStatus();
913 }
914 }
915
916 public String getAppDir() {
917 return mAppDir;
918 }
919
Brian Carlstromd893a892012-04-01 21:30:26 -0700920 public String getLibDir() {
921 return mLibDir;
922 }
923
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700924 public String getResDir() {
925 return mResDir;
926 }
927
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700928 public String[] getSplitAppDirs() {
929 return mSplitAppDirs;
930 }
931
932 public String[] getSplitResDirs() {
933 return mSplitResDirs;
934 }
935
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100936 public String[] getOverlayDirs() {
937 return mOverlayDirs;
938 }
939
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700940 public String getDataDir() {
941 return mDataDir;
942 }
943
944 public File getDataDirFile() {
945 return mDataDirFile;
946 }
947
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600948 public File getDeviceProtectedDataDirFile() {
949 return mDeviceProtectedDataDirFile;
Jeff Sharkey15447792015-11-05 16:18:51 -0800950 }
951
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600952 public File getCredentialProtectedDataDirFile() {
953 return mCredentialProtectedDataDirFile;
Jeff Sharkey15447792015-11-05 16:18:51 -0800954 }
955
Adam Lesinski4e862812016-11-21 16:02:24 -0800956 public AssetManager getAssets() {
957 return getResources().getAssets();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700958 }
959
Adam Lesinski4e862812016-11-21 16:02:24 -0800960 public Resources getResources() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700961 if (mResources == null) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800962 final String[] splitPaths;
963 try {
964 splitPaths = getSplitPaths(null);
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800965 } catch (NameNotFoundException e) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800966 // This should never fail.
967 throw new AssertionError("null split not found");
968 }
969
Jeff Hamilton7541ca4d2017-10-24 15:20:43 -0400970 mResources = ResourcesManager.getInstance().getResources(
971 null,
972 mResDir,
973 splitPaths,
974 mOverlayDirs,
975 mApplicationInfo.sharedLibraryFiles,
976 Display.DEFAULT_DISPLAY,
977 null,
978 getCompatibilityInfo(),
Adam Lesinski4e862812016-11-21 16:02:24 -0800979 getClassLoader());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700980 }
981 return mResources;
982 }
983
Jeff Hamilton7541ca4d2017-10-24 15:20:43 -0400984 public Resources getOrCreateResourcesForSplit(@NonNull String splitName,
985 @Nullable IBinder activityToken, int displayId) throws NameNotFoundException {
986 return ResourcesManager.getInstance().getResources(
987 activityToken,
988 mResDir,
989 getSplitPaths(splitName),
990 mOverlayDirs,
991 mApplicationInfo.sharedLibraryFiles,
992 displayId,
993 null,
994 getCompatibilityInfo(),
995 getSplitClassLoader(splitName));
996 }
997
998 /**
999 * Creates the top level resources for the given package. Will return an existing
1000 * Resources if one has already been created.
1001 */
1002 public Resources getOrCreateTopLevelResources(@NonNull ApplicationInfo appInfo) {
1003 // Request for this app, short circuit
1004 if (appInfo.uid == Process.myUid()) {
1005 return getResources();
1006 }
1007
1008 // Get resources for a different package
1009 return ResourcesManager.getInstance().getResources(
1010 null,
1011 appInfo.publicSourceDir,
1012 appInfo.splitPublicSourceDirs,
1013 appInfo.resourceDirs,
1014 appInfo.sharedLibraryFiles,
1015 Display.DEFAULT_DISPLAY,
1016 null,
1017 getCompatibilityInfo(),
1018 getClassLoader());
1019 }
1020
1021 public Resources createResources(IBinder activityToken, String splitName,
1022 int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo) {
1023 final String[] splitResDirs;
1024 final ClassLoader classLoader;
1025 try {
1026 splitResDirs = getSplitPaths(splitName);
1027 classLoader = getSplitClassLoader(splitName);
1028 } catch (NameNotFoundException e) {
1029 throw new RuntimeException(e);
1030 }
1031 return ResourcesManager.getInstance().getResources(activityToken,
1032 mResDir,
1033 splitResDirs,
1034 mOverlayDirs,
1035 mApplicationInfo.sharedLibraryFiles,
1036 displayId,
1037 overrideConfig,
1038 compatInfo,
1039 classLoader);
1040 }
1041
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001042 public Application makeApplication(boolean forceDefaultAppClass,
1043 Instrumentation instrumentation) {
1044 if (mApplication != null) {
1045 return mApplication;
1046 }
1047
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001048 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
1049
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001050 Application app = null;
1051
1052 String appClass = mApplicationInfo.className;
1053 if (forceDefaultAppClass || (appClass == null)) {
1054 appClass = "android.app.Application";
1055 }
1056
1057 try {
1058 java.lang.ClassLoader cl = getClassLoader();
Narayan Kamath8091edb2014-10-15 11:38:44 +01001059 if (!mPackageName.equals("android")) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001060 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
1061 "initializeJavaContextClassLoader");
Narayan Kamath8091edb2014-10-15 11:38:44 +01001062 initializeJavaContextClassLoader();
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001063 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Narayan Kamath8091edb2014-10-15 11:38:44 +01001064 }
Jeff Browndefd4a62014-03-10 21:24:37 -07001065 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001066 app = mActivityThread.mInstrumentation.newApplication(
1067 cl, appClass, appContext);
1068 appContext.setOuterContext(app);
1069 } catch (Exception e) {
1070 if (!mActivityThread.mInstrumentation.onException(app, e)) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001071 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001072 throw new RuntimeException(
1073 "Unable to instantiate application " + appClass
1074 + ": " + e.toString(), e);
1075 }
1076 }
1077 mActivityThread.mAllApplications.add(app);
1078 mApplication = app;
1079
1080 if (instrumentation != null) {
1081 try {
1082 instrumentation.callApplicationOnCreate(app);
1083 } catch (Exception e) {
1084 if (!instrumentation.onException(app, e)) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001085 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001086 throw new RuntimeException(
1087 "Unable to create application " + app.getClass().getName()
1088 + ": " + e.toString(), e);
1089 }
1090 }
1091 }
Adam Lesinskide898ff2014-01-29 18:20:45 -08001092
1093 // Rewrite the R 'constants' for all library apks.
Adam Lesinski4e862812016-11-21 16:02:24 -08001094 SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
Adam Lesinskide898ff2014-01-29 18:20:45 -08001095 final int N = packageIdentifiers.size();
1096 for (int i = 0; i < N; i++) {
1097 final int id = packageIdentifiers.keyAt(i);
1098 if (id == 0x01 || id == 0x7f) {
1099 continue;
1100 }
1101
1102 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
1103 }
1104
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001105 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1106
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001107 return app;
1108 }
1109
Adam Lesinskide898ff2014-01-29 18:20:45 -08001110 private void rewriteRValues(ClassLoader cl, String packageName, int id) {
Adam Lesinski2cb761e2014-08-15 13:59:02 -07001111 final Class<?> rClazz;
Adam Lesinskide898ff2014-01-29 18:20:45 -08001112 try {
Adam Lesinski2cb761e2014-08-15 13:59:02 -07001113 rClazz = cl.loadClass(packageName + ".R");
1114 } catch (ClassNotFoundException e) {
1115 // This is not necessarily an error, as some packages do not ship with resources
1116 // (or they do not need rewriting).
Adam Lesinski1e4663852014-08-15 14:47:28 -07001117 Log.i(TAG, "No resource references to update in package " + packageName);
Adam Lesinski2cb761e2014-08-15 13:59:02 -07001118 return;
1119 }
1120
Adam Lesinski1e4663852014-08-15 14:47:28 -07001121 final Method callback;
Adam Lesinski2cb761e2014-08-15 13:59:02 -07001122 try {
Adam Lesinski1e4663852014-08-15 14:47:28 -07001123 callback = rClazz.getMethod("onResourcesLoaded", int.class);
1124 } catch (NoSuchMethodException e) {
1125 // No rewriting to be done.
1126 return;
Adam Lesinskide898ff2014-01-29 18:20:45 -08001127 }
Adam Lesinski1e4663852014-08-15 14:47:28 -07001128
1129 Throwable cause;
1130 try {
1131 callback.invoke(null, id);
1132 return;
1133 } catch (IllegalAccessException e) {
1134 cause = e;
1135 } catch (InvocationTargetException e) {
1136 cause = e.getCause();
1137 }
1138
1139 throw new RuntimeException("Failed to rewrite resource references for " + packageName,
1140 cause);
Adam Lesinskide898ff2014-01-29 18:20:45 -08001141 }
1142
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001143 public void removeContextRegistrations(Context context,
1144 String who, String what) {
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001145 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
Adam Lesinski23d40c42014-11-20 11:58:21 -08001146 synchronized (mReceivers) {
1147 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
1148 mReceivers.remove(context);
1149 if (rmap != null) {
1150 for (int i = 0; i < rmap.size(); i++) {
1151 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
1152 IntentReceiverLeaked leak = new IntentReceiverLeaked(
1153 what + " " + who + " has leaked IntentReceiver "
1154 + rd.getIntentReceiver() + " that was " +
1155 "originally registered here. Are you missing a " +
1156 "call to unregisterReceiver()?");
1157 leak.setStackTrace(rd.getLocation().getStackTrace());
1158 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
1159 if (reportRegistrationLeaks) {
1160 StrictMode.onIntentReceiverLeaked(leak);
1161 }
1162 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001163 ActivityManager.getService().unregisterReceiver(
Adam Lesinski23d40c42014-11-20 11:58:21 -08001164 rd.getIIntentReceiver());
1165 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001166 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -08001167 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001168 }
1169 }
Adam Lesinski23d40c42014-11-20 11:58:21 -08001170 mUnregisteredReceivers.remove(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001171 }
Adam Lesinski23d40c42014-11-20 11:58:21 -08001172
1173 synchronized (mServices) {
1174 //Slog.i(TAG, "Receiver registrations: " + mReceivers);
1175 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
1176 mServices.remove(context);
1177 if (smap != null) {
1178 for (int i = 0; i < smap.size(); i++) {
1179 LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
1180 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
1181 what + " " + who + " has leaked ServiceConnection "
1182 + sd.getServiceConnection() + " that was originally bound here");
1183 leak.setStackTrace(sd.getLocation().getStackTrace());
1184 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
1185 if (reportRegistrationLeaks) {
1186 StrictMode.onServiceConnectionLeaked(leak);
1187 }
1188 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001189 ActivityManager.getService().unbindService(
Adam Lesinski23d40c42014-11-20 11:58:21 -08001190 sd.getIServiceConnection());
1191 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001192 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -08001193 }
1194 sd.doForget();
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001195 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001196 }
Adam Lesinski23d40c42014-11-20 11:58:21 -08001197 mUnboundServices.remove(context);
1198 //Slog.i(TAG, "Service registrations: " + mServices);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001199 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001200 }
1201
1202 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
1203 Context context, Handler handler,
1204 Instrumentation instrumentation, boolean registered) {
1205 synchronized (mReceivers) {
1206 LoadedApk.ReceiverDispatcher rd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001207 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001208 if (registered) {
1209 map = mReceivers.get(context);
1210 if (map != null) {
1211 rd = map.get(r);
1212 }
1213 }
1214 if (rd == null) {
1215 rd = new ReceiverDispatcher(r, context, handler,
1216 instrumentation, registered);
1217 if (registered) {
1218 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001219 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001220 mReceivers.put(context, map);
1221 }
1222 map.put(r, rd);
1223 }
1224 } else {
1225 rd.validate(context, handler);
1226 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -08001227 rd.mForgotten = false;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001228 return rd.getIIntentReceiver();
1229 }
1230 }
1231
1232 public IIntentReceiver forgetReceiverDispatcher(Context context,
1233 BroadcastReceiver r) {
1234 synchronized (mReceivers) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001235 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001236 LoadedApk.ReceiverDispatcher rd = null;
1237 if (map != null) {
1238 rd = map.get(r);
1239 if (rd != null) {
1240 map.remove(r);
1241 if (map.size() == 0) {
1242 mReceivers.remove(context);
1243 }
1244 if (r.getDebugUnregister()) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001245 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001246 = mUnregisteredReceivers.get(context);
1247 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001248 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001249 mUnregisteredReceivers.put(context, holder);
1250 }
1251 RuntimeException ex = new IllegalArgumentException(
1252 "Originally unregistered here:");
1253 ex.fillInStackTrace();
1254 rd.setUnregisterLocation(ex);
1255 holder.put(r, rd);
1256 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -08001257 rd.mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001258 return rd.getIIntentReceiver();
1259 }
1260 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001261 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001262 = mUnregisteredReceivers.get(context);
1263 if (holder != null) {
1264 rd = holder.get(r);
1265 if (rd != null) {
1266 RuntimeException ex = rd.getUnregisterLocation();
1267 throw new IllegalArgumentException(
1268 "Unregistering Receiver " + r
1269 + " that was already unregistered", ex);
1270 }
1271 }
1272 if (context == null) {
1273 throw new IllegalStateException("Unbinding Receiver " + r
1274 + " from Context that is no longer in use: " + context);
1275 } else {
1276 throw new IllegalArgumentException("Receiver not registered: " + r);
1277 }
1278
1279 }
1280 }
1281
1282 static final class ReceiverDispatcher {
1283
1284 final static class InnerReceiver extends IIntentReceiver.Stub {
1285 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
1286 final LoadedApk.ReceiverDispatcher mStrongRef;
1287
1288 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
1289 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
1290 mStrongRef = strong ? rd : null;
1291 }
Jeff Sharkeyd136e512016-03-09 22:30:56 -07001292
1293 @Override
Dianne Hackborn20e80982012-08-31 19:00:44 -07001294 public void performReceive(Intent intent, int resultCode, String data,
1295 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn26756162016-05-17 13:40:44 -07001296 final LoadedApk.ReceiverDispatcher rd;
1297 if (intent == null) {
1298 Log.wtf(TAG, "Null intent received");
1299 rd = null;
1300 } else {
1301 rd = mDispatcher.get();
1302 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001303 if (ActivityThread.DEBUG_BROADCAST) {
1304 int seq = intent.getIntExtra("seq", -1);
Dianne Hackborn26756162016-05-17 13:40:44 -07001305 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
1306 + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001307 }
1308 if (rd != null) {
1309 rd.performReceive(intent, resultCode, data, extras,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001310 ordered, sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001311 } else {
1312 // The activity manager dispatched a broadcast to a registered
1313 // receiver in this process, but before it could be delivered the
1314 // receiver was unregistered. Acknowledge the broadcast on its
1315 // behalf so that the system's broadcast sequence can continue.
1316 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1317 "Finishing broadcast to unregistered receiver");
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001318 IActivityManager mgr = ActivityManager.getService();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001319 try {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001320 if (extras != null) {
1321 extras.setAllowFds(false);
1322 }
riddle_hsu1f5ac4d2015-01-03 15:38:21 +08001323 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001324 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001325 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001326 }
1327 }
1328 }
1329 }
1330
1331 final IIntentReceiver.Stub mIIntentReceiver;
1332 final BroadcastReceiver mReceiver;
1333 final Context mContext;
1334 final Handler mActivityThread;
1335 final Instrumentation mInstrumentation;
1336 final boolean mRegistered;
1337 final IntentReceiverLeaked mLocation;
1338 RuntimeException mUnregisterLocation;
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -08001339 boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001340
Makoto Onuki08408b92017-05-09 13:48:53 -07001341 final class Args extends BroadcastReceiver.PendingResult {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001342 private Intent mCurIntent;
Dianne Hackborne829fef2010-10-26 17:44:01 -07001343 private final boolean mOrdered;
Dianne Hackborn17c77532016-06-22 16:49:14 -07001344 private boolean mDispatched;
Makoto Onukif3bb6f32017-05-02 12:02:23 -07001345 private Throwable mPreviousRunStacktrace; // To investigate b/37809561. STOPSHIP remove.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001346
Dianne Hackborne829fef2010-10-26 17:44:01 -07001347 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001348 boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborne829fef2010-10-26 17:44:01 -07001349 super(resultCode, resultData, resultExtras,
riddle_hsu1f5ac4d2015-01-03 15:38:21 +08001350 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
1351 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
Dianne Hackborne829fef2010-10-26 17:44:01 -07001352 mCurIntent = intent;
1353 mOrdered = ordered;
1354 }
Dianne Hackborn17c77532016-06-22 16:49:14 -07001355
Makoto Onuki08408b92017-05-09 13:48:53 -07001356 public final Runnable getRunnable() {
1357 return () -> {
1358 final BroadcastReceiver receiver = mReceiver;
1359 final boolean ordered = mOrdered;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001360
Makoto Onuki08408b92017-05-09 13:48:53 -07001361 if (ActivityThread.DEBUG_BROADCAST) {
1362 int seq = mCurIntent.getIntExtra("seq", -1);
1363 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
1364 + " seq=" + seq + " to " + mReceiver);
1365 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
1366 + " mOrderedHint=" + ordered);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001367 }
Makoto Onuki08408b92017-05-09 13:48:53 -07001368
1369 final IActivityManager mgr = ActivityManager.getService();
1370 final Intent intent = mCurIntent;
1371 if (intent == null) {
1372 Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
1373 + ": run() previously called at "
1374 + Log.getStackTraceString(mPreviousRunStacktrace));
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001375 }
Makoto Onuki08408b92017-05-09 13:48:53 -07001376
1377 mCurIntent = null;
1378 mDispatched = true;
1379 mPreviousRunStacktrace = new Throwable("Previous stacktrace");
1380 if (receiver == null || intent == null || mForgotten) {
1381 if (mRegistered && ordered) {
1382 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1383 "Finishing null broadcast to " + mReceiver);
1384 sendFinished(mgr);
1385 }
1386 return;
1387 }
1388
1389 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
1390 try {
1391 ClassLoader cl = mReceiver.getClass().getClassLoader();
1392 intent.setExtrasClassLoader(cl);
1393 intent.prepareToEnterProcess();
1394 setExtrasClassLoader(cl);
1395 receiver.setPendingResult(this);
1396 receiver.onReceive(mContext, intent);
1397 } catch (Exception e) {
1398 if (mRegistered && ordered) {
1399 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1400 "Finishing failed broadcast to " + mReceiver);
1401 sendFinished(mgr);
1402 }
1403 if (mInstrumentation == null ||
1404 !mInstrumentation.onException(mReceiver, e)) {
1405 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1406 throw new RuntimeException(
1407 "Error receiving broadcast " + intent
1408 + " in " + mReceiver, e);
1409 }
1410 }
1411
1412 if (receiver.getPendingResult() != null) {
1413 finish();
1414 }
1415 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1416 };
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001417 }
1418 }
1419
1420 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
1421 Handler activityThread, Instrumentation instrumentation,
1422 boolean registered) {
1423 if (activityThread == null) {
1424 throw new NullPointerException("Handler must not be null");
1425 }
1426
1427 mIIntentReceiver = new InnerReceiver(this, !registered);
1428 mReceiver = receiver;
1429 mContext = context;
1430 mActivityThread = activityThread;
1431 mInstrumentation = instrumentation;
1432 mRegistered = registered;
1433 mLocation = new IntentReceiverLeaked(null);
1434 mLocation.fillInStackTrace();
1435 }
1436
1437 void validate(Context context, Handler activityThread) {
1438 if (mContext != context) {
1439 throw new IllegalStateException(
1440 "Receiver " + mReceiver +
1441 " registered with differing Context (was " +
1442 mContext + " now " + context + ")");
1443 }
1444 if (mActivityThread != activityThread) {
1445 throw new IllegalStateException(
1446 "Receiver " + mReceiver +
1447 " registered with differing handler (was " +
1448 mActivityThread + " now " + activityThread + ")");
1449 }
1450 }
1451
1452 IntentReceiverLeaked getLocation() {
1453 return mLocation;
1454 }
1455
1456 BroadcastReceiver getIntentReceiver() {
1457 return mReceiver;
1458 }
1459
1460 IIntentReceiver getIIntentReceiver() {
1461 return mIIntentReceiver;
1462 }
1463
1464 void setUnregisterLocation(RuntimeException ex) {
1465 mUnregisterLocation = ex;
1466 }
1467
1468 RuntimeException getUnregisterLocation() {
1469 return mUnregisterLocation;
1470 }
1471
Dianne Hackborn20e80982012-08-31 19:00:44 -07001472 public void performReceive(Intent intent, int resultCode, String data,
1473 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn41bfaf82016-06-08 16:33:29 -07001474 final Args args = new Args(intent, resultCode, data, extras, ordered,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001475 sticky, sendingUser);
Dianne Hackborn41bfaf82016-06-08 16:33:29 -07001476 if (intent == null) {
1477 Log.wtf(TAG, "Null intent received");
1478 } else {
1479 if (ActivityThread.DEBUG_BROADCAST) {
1480 int seq = intent.getIntExtra("seq", -1);
1481 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
1482 + " seq=" + seq + " to " + mReceiver);
1483 }
1484 }
Makoto Onuki08408b92017-05-09 13:48:53 -07001485 if (intent == null || !mActivityThread.post(args.getRunnable())) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001486 if (mRegistered && ordered) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001487 IActivityManager mgr = ActivityManager.getService();
Dianne Hackborne829fef2010-10-26 17:44:01 -07001488 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1489 "Finishing sync broadcast to " + mReceiver);
1490 args.sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001491 }
1492 }
1493 }
1494
1495 }
1496
1497 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1498 Context context, Handler handler, int flags) {
1499 synchronized (mServices) {
1500 LoadedApk.ServiceDispatcher sd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001501 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001502 if (map != null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001503 if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001504 sd = map.get(c);
1505 }
1506 if (sd == null) {
1507 sd = new ServiceDispatcher(c, context, handler, flags);
Dianne Hackborn94846032017-03-31 17:55:23 -07001508 if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001509 if (map == null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001510 map = new ArrayMap<>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001511 mServices.put(context, map);
1512 }
1513 map.put(c, sd);
1514 } else {
1515 sd.validate(context, handler);
1516 }
1517 return sd.getIServiceConnection();
1518 }
1519 }
1520
1521 public final IServiceConnection forgetServiceDispatcher(Context context,
1522 ServiceConnection c) {
1523 synchronized (mServices) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001524 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001525 = mServices.get(context);
1526 LoadedApk.ServiceDispatcher sd = null;
1527 if (map != null) {
1528 sd = map.get(c);
1529 if (sd != null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001530 if (DEBUG) Slog.d(TAG, "Removing dispatcher " + sd + " for conn " + c);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001531 map.remove(c);
1532 sd.doForget();
1533 if (map.size() == 0) {
1534 mServices.remove(context);
1535 }
1536 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001537 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001538 = mUnboundServices.get(context);
1539 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001540 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001541 mUnboundServices.put(context, holder);
1542 }
1543 RuntimeException ex = new IllegalArgumentException(
1544 "Originally unbound here:");
1545 ex.fillInStackTrace();
1546 sd.setUnbindLocation(ex);
1547 holder.put(c, sd);
1548 }
1549 return sd.getIServiceConnection();
1550 }
1551 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001552 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001553 = mUnboundServices.get(context);
1554 if (holder != null) {
1555 sd = holder.get(c);
1556 if (sd != null) {
1557 RuntimeException ex = sd.getUnbindLocation();
1558 throw new IllegalArgumentException(
1559 "Unbinding Service " + c
1560 + " that was already unbound", ex);
1561 }
1562 }
1563 if (context == null) {
1564 throw new IllegalStateException("Unbinding Service " + c
1565 + " from Context that is no longer in use: " + context);
1566 } else {
1567 throw new IllegalArgumentException("Service not registered: " + c);
1568 }
1569 }
1570 }
1571
1572 static final class ServiceDispatcher {
1573 private final ServiceDispatcher.InnerConnection mIServiceConnection;
1574 private final ServiceConnection mConnection;
1575 private final Context mContext;
1576 private final Handler mActivityThread;
1577 private final ServiceConnectionLeaked mLocation;
1578 private final int mFlags;
1579
1580 private RuntimeException mUnbindLocation;
1581
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001582 private boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001583
1584 private static class ConnectionInfo {
1585 IBinder binder;
1586 IBinder.DeathRecipient deathMonitor;
1587 }
1588
1589 private static class InnerConnection extends IServiceConnection.Stub {
1590 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1591
1592 InnerConnection(LoadedApk.ServiceDispatcher sd) {
1593 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1594 }
1595
Dianne Hackborn94846032017-03-31 17:55:23 -07001596 public void connected(ComponentName name, IBinder service, boolean dead)
1597 throws RemoteException {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001598 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1599 if (sd != null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001600 sd.connected(name, service, dead);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001601 }
1602 }
1603 }
1604
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001605 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1606 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001607
1608 ServiceDispatcher(ServiceConnection conn,
1609 Context context, Handler activityThread, int flags) {
1610 mIServiceConnection = new InnerConnection(this);
1611 mConnection = conn;
1612 mContext = context;
1613 mActivityThread = activityThread;
1614 mLocation = new ServiceConnectionLeaked(null);
1615 mLocation.fillInStackTrace();
1616 mFlags = flags;
1617 }
1618
1619 void validate(Context context, Handler activityThread) {
1620 if (mContext != context) {
1621 throw new RuntimeException(
1622 "ServiceConnection " + mConnection +
1623 " registered with differing Context (was " +
1624 mContext + " now " + context + ")");
1625 }
1626 if (mActivityThread != activityThread) {
1627 throw new RuntimeException(
1628 "ServiceConnection " + mConnection +
1629 " registered with differing handler (was " +
1630 mActivityThread + " now " + activityThread + ")");
1631 }
1632 }
1633
1634 void doForget() {
1635 synchronized(this) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001636 for (int i=0; i<mActiveConnections.size(); i++) {
1637 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001638 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1639 }
1640 mActiveConnections.clear();
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001641 mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001642 }
1643 }
1644
1645 ServiceConnectionLeaked getLocation() {
1646 return mLocation;
1647 }
1648
1649 ServiceConnection getServiceConnection() {
1650 return mConnection;
1651 }
1652
1653 IServiceConnection getIServiceConnection() {
1654 return mIServiceConnection;
1655 }
1656
1657 int getFlags() {
1658 return mFlags;
1659 }
1660
1661 void setUnbindLocation(RuntimeException ex) {
1662 mUnbindLocation = ex;
1663 }
1664
1665 RuntimeException getUnbindLocation() {
1666 return mUnbindLocation;
1667 }
1668
Dianne Hackborn94846032017-03-31 17:55:23 -07001669 public void connected(ComponentName name, IBinder service, boolean dead) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001670 if (mActivityThread != null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001671 mActivityThread.post(new RunConnection(name, service, 0, dead));
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001672 } else {
Dianne Hackborn94846032017-03-31 17:55:23 -07001673 doConnected(name, service, dead);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001674 }
1675 }
1676
1677 public void death(ComponentName name, IBinder service) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001678 if (mActivityThread != null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001679 mActivityThread.post(new RunConnection(name, service, 1, false));
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001680 } else {
1681 doDeath(name, service);
1682 }
1683 }
1684
Dianne Hackborn94846032017-03-31 17:55:23 -07001685 public void doConnected(ComponentName name, IBinder service, boolean dead) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001686 ServiceDispatcher.ConnectionInfo old;
1687 ServiceDispatcher.ConnectionInfo info;
1688
1689 synchronized (this) {
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001690 if (mForgotten) {
1691 // We unbound before receiving the connection; ignore
1692 // any connection received.
1693 return;
1694 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001695 old = mActiveConnections.get(name);
1696 if (old != null && old.binder == service) {
1697 // Huh, already have this one. Oh well!
1698 return;
1699 }
1700
1701 if (service != null) {
1702 // A new service is being connected... set it all up.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001703 info = new ConnectionInfo();
1704 info.binder = service;
1705 info.deathMonitor = new DeathMonitor(name, service);
1706 try {
1707 service.linkToDeath(info.deathMonitor, 0);
1708 mActiveConnections.put(name, info);
1709 } catch (RemoteException e) {
1710 // This service was dead before we got it... just
1711 // don't do anything with it.
1712 mActiveConnections.remove(name);
1713 return;
1714 }
1715
1716 } else {
1717 // The named service is being disconnected... clean up.
1718 mActiveConnections.remove(name);
1719 }
1720
1721 if (old != null) {
1722 old.binder.unlinkToDeath(old.deathMonitor, 0);
1723 }
1724 }
1725
Adrian Roosa9b43182016-07-21 13:20:38 -07001726 // If there was an old service, it is now disconnected.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001727 if (old != null) {
1728 mConnection.onServiceDisconnected(name);
1729 }
Dianne Hackborn94846032017-03-31 17:55:23 -07001730 if (dead) {
Dianne Hackbornac265342017-04-19 14:53:18 -07001731 mConnection.onBindingDied(name);
Dianne Hackborn94846032017-03-31 17:55:23 -07001732 }
Christopher Tate5d73b6d2017-10-06 16:15:34 -07001733 // If there is a new viable service, it is now connected.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001734 if (service != null) {
1735 mConnection.onServiceConnected(name, service);
Christopher Tate5d73b6d2017-10-06 16:15:34 -07001736 } else {
1737 // The binding machinery worked, but the remote returned null from onBind().
1738 mConnection.onNullBinding(name);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001739 }
1740 }
1741
1742 public void doDeath(ComponentName name, IBinder service) {
Adrian Roosa9b43182016-07-21 13:20:38 -07001743 synchronized (this) {
1744 ConnectionInfo old = mActiveConnections.get(name);
1745 if (old == null || old.binder != service) {
1746 // Death for someone different than who we last
1747 // reported... just ignore it.
1748 return;
1749 }
1750 mActiveConnections.remove(name);
1751 old.binder.unlinkToDeath(old.deathMonitor, 0);
1752 }
1753
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001754 mConnection.onServiceDisconnected(name);
1755 }
1756
1757 private final class RunConnection implements Runnable {
Dianne Hackborn94846032017-03-31 17:55:23 -07001758 RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001759 mName = name;
1760 mService = service;
1761 mCommand = command;
Dianne Hackborn94846032017-03-31 17:55:23 -07001762 mDead = dead;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001763 }
1764
1765 public void run() {
1766 if (mCommand == 0) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001767 doConnected(mName, mService, mDead);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001768 } else if (mCommand == 1) {
1769 doDeath(mName, mService);
1770 }
1771 }
1772
1773 final ComponentName mName;
1774 final IBinder mService;
1775 final int mCommand;
Dianne Hackborn94846032017-03-31 17:55:23 -07001776 final boolean mDead;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001777 }
1778
1779 private final class DeathMonitor implements IBinder.DeathRecipient
1780 {
1781 DeathMonitor(ComponentName name, IBinder service) {
1782 mName = name;
1783 mService = service;
1784 }
1785
1786 public void binderDied() {
1787 death(mName, mService);
1788 }
1789
1790 final ComponentName mName;
1791 final IBinder mService;
1792 }
1793 }
1794}