blob: d24d4f341aeae1600099e2f8af3c14d770fe49d6 [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;
Calin Juravle6ae39fc2018-01-19 20:32:47 -080031import android.content.pm.dex.ArtManager;
Adam Lesinski1665d0f2017-03-10 14:46:57 -080032import android.content.pm.split.SplitDependencyLoader;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070033import android.content.res.AssetManager;
34import android.content.res.CompatibilityInfo;
Jeff Hamilton7541ca4d2017-10-24 15:20:43 -040035import android.content.res.Configuration;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070036import android.content.res.Resources;
Adam Lesinski4e862812016-11-21 16:02:24 -080037import android.os.Build;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070038import android.os.Bundle;
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;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070052import android.util.Slog;
Adam Lesinskide898ff2014-01-29 18:20:45 -080053import android.util.SparseArray;
Jeff Browna492c3a2012-08-23 19:48:44 -070054import android.view.Display;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060055import android.view.DisplayAdjustments;
Calin Juravle6ae39fc2018-01-19 20:32:47 -080056
Adam Lesinski4e862812016-11-21 16:02:24 -080057import com.android.internal.util.ArrayUtils;
Calin Juravle6ae39fc2018-01-19 20:32:47 -080058
Narayan Kamath7dba6eb2014-07-16 08:53:30 +010059import dalvik.system.VMRuntime;
Calin Juravle6ae39fc2018-01-19 20:32:47 -080060
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070061import java.io.File;
62import java.io.IOException;
63import java.io.InputStream;
64import java.lang.ref.WeakReference;
Adam Lesinski1e4663852014-08-15 14:47:28 -070065import java.lang.reflect.InvocationTargetException;
66import java.lang.reflect.Method;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070067import java.net.URL;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070068import java.util.ArrayList;
Adam Lesinski4e862812016-11-21 16:02:24 -080069import java.util.Arrays;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -070070import java.util.Collections;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070071import java.util.Enumeration;
Jeff Sharkey8a372a02016-03-16 16:25:45 -060072import java.util.List;
Narayan Kamath20531682014-07-14 13:18:43 +010073import java.util.Objects;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070074
75final class IntentReceiverLeaked extends AndroidRuntimeException {
76 public IntentReceiverLeaked(String msg) {
77 super(msg);
78 }
79}
80
81final class ServiceConnectionLeaked extends AndroidRuntimeException {
82 public ServiceConnectionLeaked(String msg) {
83 super(msg);
84 }
85}
86
87/**
88 * Local state maintained about a currently loaded .apk.
89 * @hide
90 */
Dianne Hackborn5fd21692011-06-07 14:09:47 -070091public final class LoadedApk {
Dianne Hackborn94846032017-03-31 17:55:23 -070092 static final String TAG = "LoadedApk";
93 static final boolean DEBUG = false;
Amith Yamasani742a6712011-05-04 14:49:28 -070094
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070095 private final ActivityThread mActivityThread;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070096 final String mPackageName;
Todd Kennedy39bfee52016-02-24 10:28:21 -080097 private ApplicationInfo mApplicationInfo;
98 private String mAppDir;
99 private String mResDir;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800100 private String[] mOverlayDirs;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800101 private String mDataDir;
102 private String mLibDir;
103 private File mDataDirFile;
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600104 private File mDeviceProtectedDataDirFile;
105 private File mCredentialProtectedDataDirFile;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700106 private final ClassLoader mBaseClassLoader;
107 private final boolean mSecurityViolation;
108 private final boolean mIncludeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700109 private final boolean mRegisterPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700110 private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800111 /** WARNING: This may change. Don't hold external references to it. */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700112 Resources mResources;
113 private ClassLoader mClassLoader;
114 private Application mApplication;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700115
Adam Lesinski4e862812016-11-21 16:02:24 -0800116 private String[] mSplitNames;
117 private String[] mSplitAppDirs;
118 private String[] mSplitResDirs;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100119 private String[] mSplitClassLoaderNames;
Adam Lesinski4e862812016-11-21 16:02:24 -0800120
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700121 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
Adam Lesinski4e862812016-11-21 16:02:24 -0800122 = new ArrayMap<>();
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700123 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
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>> mServices
Adam Lesinski4e862812016-11-21 16:02:24 -0800126 = new ArrayMap<>();
Dianne Hackbornadd005c2013-07-17 18:43:12 -0700127 private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
Adam Lesinski4e862812016-11-21 16:02:24 -0800128 = new ArrayMap<>();
Jason Monka80bfb52017-11-16 17:15:37 -0500129 private AppComponentFactory mAppComponentFactory;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700130
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700131 Application getApplication() {
132 return mApplication;
133 }
134
Dianne Hackborn2f0b1752011-05-31 17:59:49 -0700135 /**
136 * Create information about a new .apk
137 *
138 * NOTE: This constructor is called with ActivityThread's lock held,
139 * so MUST NOT call back out to the activity manager.
140 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700141 public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
Jeff Browndefd4a62014-03-10 21:24:37 -0700142 CompatibilityInfo compatInfo, ClassLoader baseLoader,
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700143 boolean securityViolation, boolean includeCode, boolean registerPackage) {
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100144
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700145 mActivityThread = activityThread;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800146 setApplicationInfo(aInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700147 mPackageName = aInfo.packageName;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700148 mBaseClassLoader = baseLoader;
149 mSecurityViolation = securityViolation;
150 mIncludeCode = includeCode;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700151 mRegisterPackage = registerPackage;
Craig Mautner48d0d182013-06-11 07:53:06 -0700152 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
Jason Monka80bfb52017-11-16 17:15:37 -0500153 mAppComponentFactory = createAppFactory(mApplicationInfo, mBaseClassLoader);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700154 }
155
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100156 private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) {
157 // If we're dealing with a multi-arch application that has both
158 // 32 and 64 bit shared libraries, we might need to choose the secondary
159 // depending on what the current runtime's instruction set is.
160 if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
161 final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
jgu214741cd92014-12-17 17:23:29 -0500162
163 // Get the instruction set that the libraries of secondary Abi is supported.
164 // In presence of a native bridge this might be different than the one secondary Abi used.
165 String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
166 final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
167 secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100168
169 // If the runtimeIsa is the same as the primary isa, then we do nothing.
170 // Everything will be set up correctly because info.nativeLibraryDir will
171 // correspond to the right ISA.
172 if (runtimeIsa.equals(secondaryIsa)) {
173 final ApplicationInfo modified = new ApplicationInfo(info);
174 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
Dmitriy Ivanove56b3f62015-06-05 22:00:13 -0700175 modified.primaryCpuAbi = modified.secondaryCpuAbi;
Narayan Kamath7dba6eb2014-07-16 08:53:30 +0100176 return modified;
177 }
178 }
179
180 return info;
181 }
182
Jeff Browndefd4a62014-03-10 21:24:37 -0700183 /**
184 * Create information about the system package.
185 * Must call {@link #installSystemApplicationInfo} later.
186 */
187 LoadedApk(ActivityThread activityThread) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700188 mActivityThread = activityThread;
Jeff Browndefd4a62014-03-10 21:24:37 -0700189 mApplicationInfo = new ApplicationInfo();
190 mApplicationInfo.packageName = "android";
191 mPackageName = "android";
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700192 mAppDir = null;
193 mResDir = null;
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700194 mSplitAppDirs = null;
195 mSplitResDirs = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100196 mSplitClassLoaderNames = null;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100197 mOverlayDirs = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700198 mDataDir = null;
199 mDataDirFile = null;
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600200 mDeviceProtectedDataDirFile = null;
201 mCredentialProtectedDataDirFile = null;
Kenny Root85387d72010-08-26 10:13:11 -0700202 mLibDir = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700203 mBaseClassLoader = null;
204 mSecurityViolation = false;
205 mIncludeCode = true;
Dianne Hackbornfee756f2014-07-16 17:31:10 -0700206 mRegisterPackage = false;
Jeff Browndefd4a62014-03-10 21:24:37 -0700207 mClassLoader = ClassLoader.getSystemClassLoader();
208 mResources = Resources.getSystem();
Jason Monka80bfb52017-11-16 17:15:37 -0500209 mAppComponentFactory = createAppFactory(mApplicationInfo, mClassLoader);
Jeff Browndefd4a62014-03-10 21:24:37 -0700210 }
211
212 /**
213 * Sets application info about the system package.
214 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100215 void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
Jeff Browndefd4a62014-03-10 21:24:37 -0700216 assert info.packageName.equals("android");
217 mApplicationInfo = info;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100218 mClassLoader = classLoader;
Jason Monka80bfb52017-11-16 17:15:37 -0500219 mAppComponentFactory = createAppFactory(info, classLoader);
220 }
221
222 private AppComponentFactory createAppFactory(ApplicationInfo appInfo, ClassLoader cl) {
223 if (appInfo.appComponentFactory != null) {
224 try {
225 return (AppComponentFactory) cl.loadClass(appInfo.appComponentFactory)
226 .newInstance();
227 } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
228 Slog.e(TAG, "Unable to instantiate appComponentFactory", e);
229 }
230 }
231 return AppComponentFactory.DEFAULT;
232 }
233
234 public AppComponentFactory getAppFactory() {
235 return mAppComponentFactory;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700236 }
237
238 public String getPackageName() {
239 return mPackageName;
240 }
241
242 public ApplicationInfo getApplicationInfo() {
243 return mApplicationInfo;
244 }
245
Jeff Sharkey369f5092016-02-29 11:16:21 -0700246 public int getTargetSdkVersion() {
247 return mApplicationInfo.targetSdkVersion;
248 }
249
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700250 public boolean isSecurityViolation() {
251 return mSecurityViolation;
252 }
253
Craig Mautner48d0d182013-06-11 07:53:06 -0700254 public CompatibilityInfo getCompatibilityInfo() {
255 return mDisplayAdjustments.getCompatibilityInfo();
256 }
257
258 public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
259 mDisplayAdjustments.setCompatibilityInfo(compatInfo);
260 }
261
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700262 /**
263 * Gets the array of shared libraries that are listed as
264 * used by the given package.
265 *
266 * @param packageName the name of the package (note: not its
267 * file name)
268 * @return null-ok; the array of shared libraries, each one
269 * a fully-qualified path
270 */
271 private static String[] getLibrariesFor(String packageName) {
272 ApplicationInfo ai = null;
273 try {
274 ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700275 PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700276 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700277 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700278 }
279
280 if (ai == null) {
281 return null;
282 }
283
284 return ai.sharedLibraryFiles;
285 }
286
Adam Lesinskid33ef562017-01-19 14:49:59 -0800287 /**
288 * Update the ApplicationInfo for an app. If oldPaths is null, all the paths are considered
289 * new.
290 * @param aInfo The new ApplicationInfo to use for this LoadedApk
291 * @param oldPaths The code paths for the old ApplicationInfo object. null means no paths can
292 * be reused.
293 */
294 public void updateApplicationInfo(@NonNull ApplicationInfo aInfo,
295 @Nullable List<String> oldPaths) {
Todd Kennedy39bfee52016-02-24 10:28:21 -0800296 setApplicationInfo(aInfo);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700297
Todd Kennedy39bfee52016-02-24 10:28:21 -0800298 final List<String> newPaths = new ArrayList<>();
Dimitry Ivanov638d8102017-02-22 15:39:42 -0800299 makePaths(mActivityThread, aInfo, newPaths);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800300 final List<String> addedPaths = new ArrayList<>(newPaths.size());
301
302 if (oldPaths != null) {
303 for (String path : newPaths) {
304 final String apkName = path.substring(path.lastIndexOf(File.separator));
305 boolean match = false;
306 for (String oldPath : oldPaths) {
Adam Lesinskia5ca6242017-03-01 15:45:12 -0800307 final String oldApkName = oldPath.substring(oldPath.lastIndexOf(File.separator));
Todd Kennedy39bfee52016-02-24 10:28:21 -0800308 if (apkName.equals(oldApkName)) {
309 match = true;
310 break;
311 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700312 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800313 if (!match) {
314 addedPaths.add(path);
315 }
316 }
317 } else {
318 addedPaths.addAll(newPaths);
319 }
320 synchronized (this) {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700321 createOrUpdateClassLoaderLocked(addedPaths);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800322 if (mResources != null) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800323 final String[] splitPaths;
324 try {
325 splitPaths = getSplitPaths(null);
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800326 } catch (NameNotFoundException e) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800327 // This should NEVER fail.
328 throw new AssertionError("null split not found");
329 }
330
331 mResources = ResourcesManager.getInstance().getResources(null, mResDir,
Adam Lesinski0e618832017-02-07 11:40:12 -0800332 splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
Adam Lesinski4e862812016-11-21 16:02:24 -0800333 Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
334 getClassLoader());
Todd Kennedy39bfee52016-02-24 10:28:21 -0800335 }
336 }
Jason Monka80bfb52017-11-16 17:15:37 -0500337 mAppComponentFactory = createAppFactory(aInfo, mClassLoader);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800338 }
339
340 private void setApplicationInfo(ApplicationInfo aInfo) {
341 final int myUid = Process.myUid();
342 aInfo = adjustNativeLibraryPaths(aInfo);
343 mApplicationInfo = aInfo;
344 mAppDir = aInfo.sourceDir;
345 mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800346 mOverlayDirs = aInfo.resourceDirs;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800347 mDataDir = aInfo.dataDir;
348 mLibDir = aInfo.nativeLibraryDir;
349 mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600350 mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir);
351 mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir);
Adam Lesinski4e862812016-11-21 16:02:24 -0800352
353 mSplitNames = aInfo.splitNames;
354 mSplitAppDirs = aInfo.splitSourceDirs;
355 mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100356 mSplitClassLoaderNames = aInfo.splitClassLoaderNames;
Adam Lesinski4e862812016-11-21 16:02:24 -0800357
358 if (aInfo.requestsIsolatedSplitLoading() && !ArrayUtils.isEmpty(mSplitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800359 mSplitLoader = new SplitDependencyLoaderImpl(aInfo.splitDependencies);
Adam Lesinski4e862812016-11-21 16:02:24 -0800360 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800361 }
362
Dimitry Ivanov638d8102017-02-22 15:39:42 -0800363 public static void makePaths(ActivityThread activityThread,
364 ApplicationInfo aInfo,
365 List<String> outZipPaths) {
366 makePaths(activityThread, false, aInfo, outZipPaths, null);
367 }
368
369 public static void makePaths(ActivityThread activityThread,
370 boolean isBundledApp,
371 ApplicationInfo aInfo,
372 List<String> outZipPaths,
373 List<String> outLibPaths) {
Todd Kennedy39bfee52016-02-24 10:28:21 -0800374 final String appDir = aInfo.sourceDir;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800375 final String libDir = aInfo.nativeLibraryDir;
376 final String[] sharedLibraries = aInfo.sharedLibraryFiles;
377
378 outZipPaths.clear();
379 outZipPaths.add(appDir);
Adam Lesinski4e862812016-11-21 16:02:24 -0800380
381 // Do not load all available splits if the app requested isolated split loading.
382 if (aInfo.splitSourceDirs != null && !aInfo.requestsIsolatedSplitLoading()) {
383 Collections.addAll(outZipPaths, aInfo.splitSourceDirs);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800384 }
385
386 if (outLibPaths != null) {
387 outLibPaths.clear();
388 }
389
390 /*
391 * The following is a bit of a hack to inject
392 * instrumentation into the system: If the app
393 * being started matches one of the instrumentation names,
394 * then we combine both the "instrumentation" and
395 * "instrumented" app into the path, along with the
396 * concatenation of both apps' shared library lists.
397 */
398
Todd Kennedy39bfee52016-02-24 10:28:21 -0800399 String[] instrumentationLibs = null;
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100400 // activityThread will be null when called from the WebView zygote; just assume
401 // no instrumentation applies in this case.
402 if (activityThread != null) {
403 String instrumentationPackageName = activityThread.mInstrumentationPackageName;
404 String instrumentationAppDir = activityThread.mInstrumentationAppDir;
405 String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
406 String instrumentationLibDir = activityThread.mInstrumentationLibDir;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800407
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100408 String instrumentedAppDir = activityThread.mInstrumentedAppDir;
409 String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
410 String instrumentedLibDir = activityThread.mInstrumentedLibDir;
411
412 if (appDir.equals(instrumentationAppDir)
413 || appDir.equals(instrumentedAppDir)) {
414 outZipPaths.clear();
415 outZipPaths.add(instrumentationAppDir);
Adam Lesinski4e862812016-11-21 16:02:24 -0800416
417 // Only add splits if the app did not request isolated split loading.
418 if (!aInfo.requestsIsolatedSplitLoading()) {
419 if (instrumentationSplitAppDirs != null) {
420 Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
421 }
422
423 if (!instrumentationAppDir.equals(instrumentedAppDir)) {
424 outZipPaths.add(instrumentedAppDir);
425 if (instrumentedSplitAppDirs != null) {
426 Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
427 }
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100428 }
Jeff Haoc7b94822016-03-16 15:56:07 -0700429 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800430
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100431 if (outLibPaths != null) {
432 outLibPaths.add(instrumentationLibDir);
433 if (!instrumentationLibDir.equals(instrumentedLibDir)) {
434 outLibPaths.add(instrumentedLibDir);
435 }
436 }
437
438 if (!instrumentedAppDir.equals(instrumentationAppDir)) {
439 instrumentationLibs = getLibrariesFor(instrumentationPackageName);
440 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800441 }
442 }
443
444 if (outLibPaths != null) {
445 if (outLibPaths.isEmpty()) {
446 outLibPaths.add(libDir);
447 }
448
449 // Add path to libraries in apk for current abi. Do this now because more entries
450 // will be added to zipPaths that shouldn't be part of the library path.
451 if (aInfo.primaryCpuAbi != null) {
Alex Light20ed24f2016-04-20 14:07:43 -0700452 // Add fake libs into the library search path if we target prior to N.
Adam Lesinski4e862812016-11-21 16:02:24 -0800453 if (aInfo.targetSdkVersion < Build.VERSION_CODES.N) {
Alex Light20ed24f2016-04-20 14:07:43 -0700454 outLibPaths.add("/system/fake-libs" +
455 (VMRuntime.is64BitAbi(aInfo.primaryCpuAbi) ? "64" : ""));
456 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800457 for (String apk : outZipPaths) {
458 outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
459 }
460 }
461
Dimitry Ivanov638d8102017-02-22 15:39:42 -0800462 if (isBundledApp) {
Todd Kennedy39bfee52016-02-24 10:28:21 -0800463 // Add path to system libraries to libPaths;
464 // Access to system libs should be limited
465 // to bundled applications; this is why updated
466 // system apps are not included.
467 outLibPaths.add(System.getProperty("java.library.path"));
468 }
469 }
470
Jeff Hao090892f2017-04-24 17:37:31 -0700471 // Prepend the shared libraries, maintaining their original order where possible.
Todd Kennedy39bfee52016-02-24 10:28:21 -0800472 if (sharedLibraries != null) {
Jeff Hao090892f2017-04-24 17:37:31 -0700473 int index = 0;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800474 for (String lib : sharedLibraries) {
475 if (!outZipPaths.contains(lib)) {
Jeff Hao090892f2017-04-24 17:37:31 -0700476 outZipPaths.add(index, lib);
477 index++;
Svetoslav Ganov40610e32017-06-20 19:35:51 -0700478 appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800479 }
480 }
481 }
482
483 if (instrumentationLibs != null) {
484 for (String lib : instrumentationLibs) {
485 if (!outZipPaths.contains(lib)) {
486 outZipPaths.add(0, lib);
Svetoslav Ganov40610e32017-06-20 19:35:51 -0700487 appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800488 }
489 }
490 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800491 }
492
Svetoslav Ganov40610e32017-06-20 19:35:51 -0700493 /**
494 * This method appends a path to the appropriate native library folder of a
495 * library if this library is hosted in an APK. This allows support for native
496 * shared libraries. The library API is determined based on the application
497 * ABI.
498 *
499 * @param path Path to the library.
500 * @param applicationInfo The application depending on the library.
501 * @param outLibPaths List to which to add the native lib path if needed.
502 */
503 private static void appendApkLibPathIfNeeded(@NonNull String path,
504 @NonNull ApplicationInfo applicationInfo, @Nullable List<String> outLibPaths) {
505 // Looking at the suffix is a little hacky but a safe and simple solution.
506 // We will be revisiting code in the next release and clean this up.
507 if (outLibPaths != null && applicationInfo.primaryCpuAbi != null && path.endsWith(".apk")) {
508 if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
509 outLibPaths.add(path + "!/lib/" + applicationInfo.primaryCpuAbi);
510 }
511 }
512 }
513
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800514 /*
515 * All indices received by the super class should be shifted by 1 when accessing mSplitNames,
516 * etc. The super class assumes the base APK is index 0, while the PackageManager APIs don't
517 * include the base APK in the list of splits.
518 */
519 private class SplitDependencyLoaderImpl extends SplitDependencyLoader<NameNotFoundException> {
Adam Lesinski4e862812016-11-21 16:02:24 -0800520 private final String[][] mCachedResourcePaths;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800521 private final ClassLoader[] mCachedClassLoaders;
Adam Lesinski4e862812016-11-21 16:02:24 -0800522
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800523 SplitDependencyLoaderImpl(@NonNull SparseArray<int[]> dependencies) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800524 super(dependencies);
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800525 mCachedResourcePaths = new String[mSplitNames.length + 1][];
526 mCachedClassLoaders = new ClassLoader[mSplitNames.length + 1];
Adam Lesinski4e862812016-11-21 16:02:24 -0800527 }
528
529 @Override
530 protected boolean isSplitCached(int splitIdx) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800531 return mCachedClassLoaders[splitIdx] != null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800532 }
533
534 @Override
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800535 protected void constructSplit(int splitIdx, @NonNull int[] configSplitIndices,
536 int parentSplitIdx) throws NameNotFoundException {
Adam Lesinski4e862812016-11-21 16:02:24 -0800537 final ArrayList<String> splitPaths = new ArrayList<>();
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800538 if (splitIdx == 0) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800539 createOrUpdateClassLoaderLocked(null);
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800540 mCachedClassLoaders[0] = mClassLoader;
541
542 // Never add the base resources here, they always get added no matter what.
543 for (int configSplitIdx : configSplitIndices) {
544 splitPaths.add(mSplitResDirs[configSplitIdx - 1]);
545 }
546 mCachedResourcePaths[0] = splitPaths.toArray(new String[splitPaths.size()]);
Adam Lesinski4e862812016-11-21 16:02:24 -0800547 return;
548 }
549
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800550 // Since we handled the special base case above, parentSplitIdx is always valid.
551 final ClassLoader parent = mCachedClassLoaders[parentSplitIdx];
552 mCachedClassLoaders[splitIdx] = ApplicationLoaders.getDefault().getClassLoader(
Narayan Kamathf9419f02017-06-15 11:35:38 +0100553 mSplitAppDirs[splitIdx - 1], getTargetSdkVersion(), false, null, null, parent,
554 mSplitClassLoaderNames[splitIdx - 1]);
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800555
556 Collections.addAll(splitPaths, mCachedResourcePaths[parentSplitIdx]);
557 splitPaths.add(mSplitResDirs[splitIdx - 1]);
558 for (int configSplitIdx : configSplitIndices) {
559 splitPaths.add(mSplitResDirs[configSplitIdx - 1]);
Adam Lesinski4e862812016-11-21 16:02:24 -0800560 }
Adam Lesinski4e862812016-11-21 16:02:24 -0800561 mCachedResourcePaths[splitIdx] = splitPaths.toArray(new String[splitPaths.size()]);
562 }
563
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800564 private int ensureSplitLoaded(String splitName) throws NameNotFoundException {
565 int idx = 0;
566 if (splitName != null) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800567 idx = Arrays.binarySearch(mSplitNames, splitName);
568 if (idx < 0) {
569 throw new PackageManager.NameNotFoundException(
570 "Split name '" + splitName + "' is not installed");
571 }
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800572 idx += 1;
Adam Lesinski4e862812016-11-21 16:02:24 -0800573 }
Adam Lesinski4e862812016-11-21 16:02:24 -0800574 loadDependenciesForSplit(idx);
575 return idx;
576 }
577
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800578 ClassLoader getClassLoaderForSplit(String splitName) throws NameNotFoundException {
579 return mCachedClassLoaders[ensureSplitLoaded(splitName)];
Adam Lesinski4e862812016-11-21 16:02:24 -0800580 }
581
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800582 String[] getSplitPathsForSplit(String splitName) throws NameNotFoundException {
583 return mCachedResourcePaths[ensureSplitLoaded(splitName)];
Adam Lesinski4e862812016-11-21 16:02:24 -0800584 }
585 }
586
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800587 private SplitDependencyLoaderImpl mSplitLoader;
Adam Lesinski4e862812016-11-21 16:02:24 -0800588
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800589 ClassLoader getSplitClassLoader(String splitName) throws NameNotFoundException {
Adam Lesinski4e862812016-11-21 16:02:24 -0800590 if (mSplitLoader == null) {
591 return mClassLoader;
592 }
593 return mSplitLoader.getClassLoaderForSplit(splitName);
594 }
595
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800596 String[] getSplitPaths(String splitName) throws NameNotFoundException {
Adam Lesinski4e862812016-11-21 16:02:24 -0800597 if (mSplitLoader == null) {
598 return mSplitResDirs;
599 }
600 return mSplitLoader.getSplitPathsForSplit(splitName);
601 }
602
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700603 private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
604 if (mPackageName.equals("android")) {
Calin Juravle430ef452016-04-22 17:43:07 +0100605 // Note: This branch is taken for system server and we don't need to setup
606 // jit profiling support.
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700607 if (mClassLoader != null) {
608 // nothing to update
609 return;
Dimitry Ivanovb9c90262016-02-19 14:09:20 -0800610 }
611
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700612 if (mBaseClassLoader != null) {
613 mClassLoader = mBaseClassLoader;
Todd Kennedy39bfee52016-02-24 10:28:21 -0800614 } else {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700615 mClassLoader = ClassLoader.getSystemClassLoader();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800616 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700617
618 return;
619 }
620
621 // Avoid the binder call when the package is the current application package.
622 // The activity manager will perform ensure that dexopt is performed before
623 // spinning up the process.
Narayan Kamathbf07e2a2017-03-15 11:37:32 +0000624 if (!Objects.equals(mPackageName, ActivityThread.currentPackageName()) && mIncludeCode) {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700625 try {
Brian Carlstromca82e612016-04-19 23:16:08 -0700626 ActivityThread.getPackageManager().notifyPackageUse(mPackageName,
627 PackageManager.NOTIFY_PACKAGE_USE_CROSS_PACKAGE);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700628 } catch (RemoteException re) {
629 throw re.rethrowFromSystemServer();
Todd Kennedy39bfee52016-02-24 10:28:21 -0800630 }
631 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700632
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700633 if (mRegisterPackage) {
634 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800635 ActivityManager.getService().addPackageDependency(mPackageName);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700636 } catch (RemoteException e) {
637 throw e.rethrowFromSystemServer();
638 }
639 }
640
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700641 // Lists for the elements of zip/code and native libraries.
642 //
643 // Both lists are usually not empty. We expect on average one APK for the zip component,
644 // but shared libraries and splits are not uncommon. We expect at least three elements
645 // for native libraries (app-based, system, vendor). As such, give both some breathing
646 // space and initialize to a small value (instead of incurring growth code).
647 final List<String> zipPaths = new ArrayList<>(10);
648 final List<String> libPaths = new ArrayList<>(10);
Narayan Kamath8995b002016-05-11 20:31:09 +0100649
Jiyong Parkfcad6962017-08-22 10:24:28 +0900650 boolean isBundledApp = mApplicationInfo.isSystemApp()
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700651 && !mApplicationInfo.isUpdatedSystemApp();
Dimitry Ivanovbf3b5f72016-05-03 11:34:58 -0700652
Jiyong Parkfcad6962017-08-22 10:24:28 +0900653 // Vendor apks are treated as bundled only when /vendor/lib is in the default search
654 // paths. If not, they are treated as unbundled; access to system libs is limited.
655 // Having /vendor/lib in the default search paths means that all system processes
656 // are allowed to use any vendor library, which in turn means that system is dependent
657 // on vendor partition. In the contrary, not having /vendor/lib in the default search
658 // paths mean that the two partitions are separated and thus we can treat vendor apks
659 // as unbundled.
660 final String defaultSearchPaths = System.getProperty("java.library.path");
661 final boolean treatVendorApkAsUnbundled = !defaultSearchPaths.contains("/vendor/lib");
Jiyong Park63495c22017-09-15 07:48:06 +0900662 if (mApplicationInfo.getCodePath() != null
Jiyong Park002fdbd2017-02-13 20:50:31 +0900663 && mApplicationInfo.isVendor() && treatVendorApkAsUnbundled) {
Jiyong Parkfcad6962017-08-22 10:24:28 +0900664 isBundledApp = false;
665 }
666
Dimitry Ivanov638d8102017-02-22 15:39:42 -0800667 makePaths(mActivityThread, isBundledApp, mApplicationInfo, zipPaths, libPaths);
668
Dimitry Ivanoveb96b002016-05-10 10:51:40 -0700669 String libraryPermittedPath = mDataDir;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700670 if (isBundledApp) {
671 // This is necessary to grant bundled apps access to
672 // libraries located in subdirectories of /system/lib
Jiyong Parkfcad6962017-08-22 10:24:28 +0900673 libraryPermittedPath += File.pathSeparator + defaultSearchPaths;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700674 }
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700675
676 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
677
Narayan Kamath8995b002016-05-11 20:31:09 +0100678 // If we're not asked to include code, we construct a classloader that has
679 // no code path included. We still need to set up the library search paths
680 // and permitted path because NativeActivity relies on it (it attempts to
681 // call System.loadLibrary() on a classloader from a LoadedApk with
682 // mIncludeCode == false).
683 if (!mIncludeCode) {
684 if (mClassLoader == null) {
685 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
686 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
Narayan Kamathf9419f02017-06-15 11:35:38 +0100687 "" /* codePath */, mApplicationInfo.targetSdkVersion, isBundledApp,
688 librarySearchPath, libraryPermittedPath, mBaseClassLoader,
689 null /* classLoaderName */);
Narayan Kamath8995b002016-05-11 20:31:09 +0100690 StrictMode.setThreadPolicy(oldPolicy);
691 }
692
693 return;
694 }
695
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700696 /*
Narayan Kamath8995b002016-05-11 20:31:09 +0100697 * With all the combination done (if necessary, actually create the java class
698 * loader and set up JIT profiling support if necessary.
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700699 *
700 * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils.
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700701 */
Andreas Gampea8a58ff2016-05-18 11:58:39 -0700702 final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
703 TextUtils.join(File.pathSeparator, zipPaths);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700704
Dianne Hackborn94846032017-03-31 17:55:23 -0700705 if (DEBUG) Slog.v(ActivityThread.TAG, "Class path: " + zip +
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700706 ", JNI path: " + librarySearchPath);
707
Calin Juravle430ef452016-04-22 17:43:07 +0100708 boolean needToSetupJitProfiles = false;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700709 if (mClassLoader == null) {
710 // Temporarily disable logging of disk reads on the Looper thread
711 // as this is early and necessary.
712 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
713
714 mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
715 mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
Narayan Kamathf9419f02017-06-15 11:35:38 +0100716 libraryPermittedPath, mBaseClassLoader,
717 mApplicationInfo.classLoaderName);
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700718
719 StrictMode.setThreadPolicy(oldPolicy);
Calin Juravle430ef452016-04-22 17:43:07 +0100720 // Setup the class loader paths for profiling.
721 needToSetupJitProfiles = true;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700722 }
723
724 if (addedPaths != null && addedPaths.size() > 0) {
725 final String add = TextUtils.join(File.pathSeparator, addedPaths);
726 ApplicationLoaders.getDefault().addPath(mClassLoader, add);
Calin Juravle430ef452016-04-22 17:43:07 +0100727 // Setup the new code paths for profiling.
728 needToSetupJitProfiles = true;
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700729 }
Calin Juravle2a727d72016-04-15 19:33:46 +0100730
731 // Setup jit profile support.
Narayan Kamath2d4a2222016-04-25 19:16:56 +0100732 //
Calin Juravle2a727d72016-04-15 19:33:46 +0100733 // It is ok to call this multiple times if the application gets updated with new splits.
734 // The runtime only keeps track of unique code paths and can handle re-registration of
735 // the same code path. There's no need to pass `addedPaths` since any new code paths
736 // are already in `mApplicationInfo`.
Narayan Kamath2d4a2222016-04-25 19:16:56 +0100737 //
738 // It is NOT ok to call this function from the system_server (for any of the packages it
739 // loads code from) so we explicitly disallow it there.
740 if (needToSetupJitProfiles && !ActivityThread.isSystem()) {
Calin Juravle430ef452016-04-22 17:43:07 +0100741 setupJitProfileSupport();
Calin Juravle430ef452016-04-22 17:43:07 +0100742 }
Todd Kennedy39bfee52016-02-24 10:28:21 -0800743 }
744
745 public ClassLoader getClassLoader() {
746 synchronized (this) {
747 if (mClassLoader == null) {
Dimitry Ivanov43b28b12016-03-14 17:15:38 -0700748 createOrUpdateClassLoaderLocked(null /*addedPaths*/);
Todd Kennedy39bfee52016-02-24 10:28:21 -0800749 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700750 return mClassLoader;
751 }
752 }
753
Calin Juravle2a727d72016-04-15 19:33:46 +0100754 private void setupJitProfileSupport() {
755 if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
756 return;
757 }
Calin Juravle126f7802016-05-24 15:23:47 +0100758 // Only set up profile support if the loaded apk has the same uid as the
759 // current process.
760 // Currently, we do not support profiling across different apps.
761 // (e.g. application's uid might be different when the code is
762 // loaded by another app via createApplicationContext)
763 if (mApplicationInfo.uid != Process.myUid()) {
764 return;
765 }
766
Calin Juravle2a727d72016-04-15 19:33:46 +0100767 final List<String> codePaths = new ArrayList<>();
768 if ((mApplicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
769 codePaths.add(mApplicationInfo.sourceDir);
770 }
771 if (mApplicationInfo.splitSourceDirs != null) {
772 Collections.addAll(codePaths, mApplicationInfo.splitSourceDirs);
773 }
774
775 if (codePaths.isEmpty()) {
776 // If there are no code paths there's no need to setup a profile file and register with
777 // the runtime,
778 return;
779 }
780
Calin Juravle6ae39fc2018-01-19 20:32:47 -0800781 for (int i = codePaths.size() - 1; i >= 0; i--) {
782 String splitName = i == 0 ? null : mApplicationInfo.splitNames[i - 1];
783 String profileFile = ArtManager.getCurrentProfilePath(
784 mPackageName, UserHandle.myUserId(), splitName);
785 VMRuntime.registerAppInfo(profileFile, new String[] {codePaths.get(i)});
786 }
Calin Juravlef5a7bfc2017-03-13 23:30:30 -0700787
788 // Register the app data directory with the reporter. It will
789 // help deciding whether or not a dex file is the primary apk or a
790 // secondary dex.
791 DexLoadReporter.getInstance().registerAppDataDir(mPackageName, mDataDir);
Calin Juravle2a727d72016-04-15 19:33:46 +0100792 }
793
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700794 /**
795 * Setup value for Thread.getContextClassLoader(). If the
796 * package will not run in in a VM with other packages, we set
797 * the Java context ClassLoader to the
798 * PackageInfo.getClassLoader value. However, if this VM can
799 * contain multiple packages, we intead set the Java context
800 * ClassLoader to a proxy that will warn about the use of Java
801 * context ClassLoaders and then fall through to use the
802 * system ClassLoader.
803 *
804 * <p> Note that this is similar to but not the same as the
805 * android.content.Context.getClassLoader(). While both
806 * context class loaders are typically set to the
807 * PathClassLoader used to load the package archive in the
808 * single application per VM case, a single Android process
809 * may contain several Contexts executing on one thread with
810 * their own logical ClassLoaders while the Java context
811 * ClassLoader is a thread local. This is why in the case when
812 * we have multiple packages per VM we do not set the Java
813 * context ClassLoader to an arbitrary but instead warn the
814 * user to set their own if we detect that they are using a
815 * Java library that expects it to be set.
816 */
817 private void initializeJavaContextClassLoader() {
818 IPackageManager pm = ActivityThread.getPackageManager();
819 android.content.pm.PackageInfo pi;
820 try {
Jeff Sharkeyc7bacab2016-02-09 15:56:11 -0700821 pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
822 UserHandle.myUserId());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700823 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700824 throw e.rethrowFromSystemServer();
Dianne Hackborn208d9372013-02-25 13:17:54 -0800825 }
826 if (pi == null) {
827 throw new IllegalStateException("Unable to get package info for "
828 + mPackageName + "; is package not installed?");
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700829 }
830 /*
831 * Two possible indications that this package could be
832 * sharing its virtual machine with other packages:
833 *
834 * 1.) the sharedUserId attribute is set in the manifest,
835 * indicating a request to share a VM with other
836 * packages with the same sharedUserId.
837 *
838 * 2.) the application element of the manifest has an
839 * attribute specifying a non-default process name,
840 * indicating the desire to run in another packages VM.
841 */
842 boolean sharedUserIdSet = (pi.sharedUserId != null);
843 boolean processNameNotDefault =
844 (pi.applicationInfo != null &&
845 !mPackageName.equals(pi.applicationInfo.processName));
846 boolean sharable = (sharedUserIdSet || processNameNotDefault);
847 ClassLoader contextClassLoader =
848 (sharable)
849 ? new WarningContextClassLoader()
850 : mClassLoader;
851 Thread.currentThread().setContextClassLoader(contextClassLoader);
852 }
853
854 private static class WarningContextClassLoader extends ClassLoader {
855
856 private static boolean warned = false;
857
858 private void warn(String methodName) {
859 if (warned) {
860 return;
861 }
862 warned = true;
863 Thread.currentThread().setContextClassLoader(getParent());
864 Slog.w(ActivityThread.TAG, "ClassLoader." + methodName + ": " +
865 "The class loader returned by " +
866 "Thread.getContextClassLoader() may fail for processes " +
867 "that host multiple applications. You should explicitly " +
868 "specify a context class loader. For example: " +
869 "Thread.setContextClassLoader(getClass().getClassLoader());");
870 }
871
872 @Override public URL getResource(String resName) {
873 warn("getResource");
874 return getParent().getResource(resName);
875 }
876
877 @Override public Enumeration<URL> getResources(String resName) throws IOException {
878 warn("getResources");
879 return getParent().getResources(resName);
880 }
881
882 @Override public InputStream getResourceAsStream(String resName) {
883 warn("getResourceAsStream");
884 return getParent().getResourceAsStream(resName);
885 }
886
887 @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
888 warn("loadClass");
889 return getParent().loadClass(className);
890 }
891
892 @Override public void setClassAssertionStatus(String cname, boolean enable) {
893 warn("setClassAssertionStatus");
894 getParent().setClassAssertionStatus(cname, enable);
895 }
896
897 @Override public void setPackageAssertionStatus(String pname, boolean enable) {
898 warn("setPackageAssertionStatus");
899 getParent().setPackageAssertionStatus(pname, enable);
900 }
901
902 @Override public void setDefaultAssertionStatus(boolean enable) {
903 warn("setDefaultAssertionStatus");
904 getParent().setDefaultAssertionStatus(enable);
905 }
906
907 @Override public void clearAssertionStatus() {
908 warn("clearAssertionStatus");
909 getParent().clearAssertionStatus();
910 }
911 }
912
913 public String getAppDir() {
914 return mAppDir;
915 }
916
Brian Carlstromd893a892012-04-01 21:30:26 -0700917 public String getLibDir() {
918 return mLibDir;
919 }
920
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700921 public String getResDir() {
922 return mResDir;
923 }
924
Jeff Sharkey8a4c9722014-06-16 13:48:42 -0700925 public String[] getSplitAppDirs() {
926 return mSplitAppDirs;
927 }
928
929 public String[] getSplitResDirs() {
930 return mSplitResDirs;
931 }
932
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100933 public String[] getOverlayDirs() {
934 return mOverlayDirs;
935 }
936
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700937 public String getDataDir() {
938 return mDataDir;
939 }
940
941 public File getDataDirFile() {
942 return mDataDirFile;
943 }
944
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600945 public File getDeviceProtectedDataDirFile() {
946 return mDeviceProtectedDataDirFile;
Jeff Sharkey15447792015-11-05 16:18:51 -0800947 }
948
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600949 public File getCredentialProtectedDataDirFile() {
950 return mCredentialProtectedDataDirFile;
Jeff Sharkey15447792015-11-05 16:18:51 -0800951 }
952
Adam Lesinski4e862812016-11-21 16:02:24 -0800953 public AssetManager getAssets() {
954 return getResources().getAssets();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700955 }
956
Adam Lesinski4e862812016-11-21 16:02:24 -0800957 public Resources getResources() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700958 if (mResources == null) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800959 final String[] splitPaths;
960 try {
961 splitPaths = getSplitPaths(null);
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800962 } catch (NameNotFoundException e) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800963 // This should never fail.
964 throw new AssertionError("null split not found");
965 }
966
Jeff Hamilton7541ca4d2017-10-24 15:20:43 -0400967 mResources = ResourcesManager.getInstance().getResources(
968 null,
969 mResDir,
970 splitPaths,
971 mOverlayDirs,
972 mApplicationInfo.sharedLibraryFiles,
973 Display.DEFAULT_DISPLAY,
974 null,
975 getCompatibilityInfo(),
Adam Lesinski4e862812016-11-21 16:02:24 -0800976 getClassLoader());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700977 }
978 return mResources;
979 }
980
Jeff Hamilton7541ca4d2017-10-24 15:20:43 -0400981 public Resources getOrCreateResourcesForSplit(@NonNull String splitName,
982 @Nullable IBinder activityToken, int displayId) throws NameNotFoundException {
983 return ResourcesManager.getInstance().getResources(
984 activityToken,
985 mResDir,
986 getSplitPaths(splitName),
987 mOverlayDirs,
988 mApplicationInfo.sharedLibraryFiles,
989 displayId,
990 null,
991 getCompatibilityInfo(),
992 getSplitClassLoader(splitName));
993 }
994
995 /**
996 * Creates the top level resources for the given package. Will return an existing
997 * Resources if one has already been created.
998 */
999 public Resources getOrCreateTopLevelResources(@NonNull ApplicationInfo appInfo) {
1000 // Request for this app, short circuit
1001 if (appInfo.uid == Process.myUid()) {
1002 return getResources();
1003 }
1004
1005 // Get resources for a different package
1006 return ResourcesManager.getInstance().getResources(
1007 null,
1008 appInfo.publicSourceDir,
1009 appInfo.splitPublicSourceDirs,
1010 appInfo.resourceDirs,
1011 appInfo.sharedLibraryFiles,
1012 Display.DEFAULT_DISPLAY,
1013 null,
1014 getCompatibilityInfo(),
1015 getClassLoader());
1016 }
1017
1018 public Resources createResources(IBinder activityToken, String splitName,
1019 int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo) {
1020 final String[] splitResDirs;
1021 final ClassLoader classLoader;
1022 try {
1023 splitResDirs = getSplitPaths(splitName);
1024 classLoader = getSplitClassLoader(splitName);
1025 } catch (NameNotFoundException e) {
1026 throw new RuntimeException(e);
1027 }
1028 return ResourcesManager.getInstance().getResources(activityToken,
1029 mResDir,
1030 splitResDirs,
1031 mOverlayDirs,
1032 mApplicationInfo.sharedLibraryFiles,
1033 displayId,
1034 overrideConfig,
1035 compatInfo,
1036 classLoader);
1037 }
1038
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001039 public Application makeApplication(boolean forceDefaultAppClass,
1040 Instrumentation instrumentation) {
1041 if (mApplication != null) {
1042 return mApplication;
1043 }
1044
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001045 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
1046
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001047 Application app = null;
1048
1049 String appClass = mApplicationInfo.className;
1050 if (forceDefaultAppClass || (appClass == null)) {
1051 appClass = "android.app.Application";
1052 }
1053
1054 try {
1055 java.lang.ClassLoader cl = getClassLoader();
Narayan Kamath8091edb2014-10-15 11:38:44 +01001056 if (!mPackageName.equals("android")) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001057 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
1058 "initializeJavaContextClassLoader");
Narayan Kamath8091edb2014-10-15 11:38:44 +01001059 initializeJavaContextClassLoader();
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001060 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Narayan Kamath8091edb2014-10-15 11:38:44 +01001061 }
Jeff Browndefd4a62014-03-10 21:24:37 -07001062 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001063 app = mActivityThread.mInstrumentation.newApplication(
1064 cl, appClass, appContext);
1065 appContext.setOuterContext(app);
1066 } catch (Exception e) {
1067 if (!mActivityThread.mInstrumentation.onException(app, e)) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001068 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001069 throw new RuntimeException(
1070 "Unable to instantiate application " + appClass
1071 + ": " + e.toString(), e);
1072 }
1073 }
1074 mActivityThread.mAllApplications.add(app);
1075 mApplication = app;
1076
1077 if (instrumentation != null) {
1078 try {
1079 instrumentation.callApplicationOnCreate(app);
1080 } catch (Exception e) {
1081 if (!instrumentation.onException(app, e)) {
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001082 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001083 throw new RuntimeException(
1084 "Unable to create application " + app.getClass().getName()
1085 + ": " + e.toString(), e);
1086 }
1087 }
1088 }
Adam Lesinskide898ff2014-01-29 18:20:45 -08001089
1090 // Rewrite the R 'constants' for all library apks.
Adam Lesinski4e862812016-11-21 16:02:24 -08001091 SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
Adam Lesinskide898ff2014-01-29 18:20:45 -08001092 final int N = packageIdentifiers.size();
1093 for (int i = 0; i < N; i++) {
1094 final int id = packageIdentifiers.keyAt(i);
1095 if (id == 0x01 || id == 0x7f) {
1096 continue;
1097 }
1098
1099 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
1100 }
1101
Andreas Gampe4c8e5422016-05-18 11:58:47 -07001102 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1103
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001104 return app;
1105 }
1106
Adam Lesinskide898ff2014-01-29 18:20:45 -08001107 private void rewriteRValues(ClassLoader cl, String packageName, int id) {
Adam Lesinski2cb761e2014-08-15 13:59:02 -07001108 final Class<?> rClazz;
Adam Lesinskide898ff2014-01-29 18:20:45 -08001109 try {
Adam Lesinski2cb761e2014-08-15 13:59:02 -07001110 rClazz = cl.loadClass(packageName + ".R");
1111 } catch (ClassNotFoundException e) {
1112 // This is not necessarily an error, as some packages do not ship with resources
1113 // (or they do not need rewriting).
Adam Lesinski1e4663852014-08-15 14:47:28 -07001114 Log.i(TAG, "No resource references to update in package " + packageName);
Adam Lesinski2cb761e2014-08-15 13:59:02 -07001115 return;
1116 }
1117
Adam Lesinski1e4663852014-08-15 14:47:28 -07001118 final Method callback;
Adam Lesinski2cb761e2014-08-15 13:59:02 -07001119 try {
Adam Lesinski1e4663852014-08-15 14:47:28 -07001120 callback = rClazz.getMethod("onResourcesLoaded", int.class);
1121 } catch (NoSuchMethodException e) {
1122 // No rewriting to be done.
1123 return;
Adam Lesinskide898ff2014-01-29 18:20:45 -08001124 }
Adam Lesinski1e4663852014-08-15 14:47:28 -07001125
1126 Throwable cause;
1127 try {
1128 callback.invoke(null, id);
1129 return;
1130 } catch (IllegalAccessException e) {
1131 cause = e;
1132 } catch (InvocationTargetException e) {
1133 cause = e.getCause();
1134 }
1135
1136 throw new RuntimeException("Failed to rewrite resource references for " + packageName,
1137 cause);
Adam Lesinskide898ff2014-01-29 18:20:45 -08001138 }
1139
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001140 public void removeContextRegistrations(Context context,
1141 String who, String what) {
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001142 final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
Adam Lesinski23d40c42014-11-20 11:58:21 -08001143 synchronized (mReceivers) {
1144 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
1145 mReceivers.remove(context);
1146 if (rmap != null) {
1147 for (int i = 0; i < rmap.size(); i++) {
1148 LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
1149 IntentReceiverLeaked leak = new IntentReceiverLeaked(
1150 what + " " + who + " has leaked IntentReceiver "
1151 + rd.getIntentReceiver() + " that was " +
1152 "originally registered here. Are you missing a " +
1153 "call to unregisterReceiver()?");
1154 leak.setStackTrace(rd.getLocation().getStackTrace());
1155 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
1156 if (reportRegistrationLeaks) {
1157 StrictMode.onIntentReceiverLeaked(leak);
1158 }
1159 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001160 ActivityManager.getService().unregisterReceiver(
Adam Lesinski23d40c42014-11-20 11:58:21 -08001161 rd.getIIntentReceiver());
1162 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001163 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -08001164 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001165 }
1166 }
Adam Lesinski23d40c42014-11-20 11:58:21 -08001167 mUnregisteredReceivers.remove(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001168 }
Adam Lesinski23d40c42014-11-20 11:58:21 -08001169
1170 synchronized (mServices) {
1171 //Slog.i(TAG, "Receiver registrations: " + mReceivers);
1172 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
1173 mServices.remove(context);
1174 if (smap != null) {
1175 for (int i = 0; i < smap.size(); i++) {
1176 LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
1177 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
1178 what + " " + who + " has leaked ServiceConnection "
1179 + sd.getServiceConnection() + " that was originally bound here");
1180 leak.setStackTrace(sd.getLocation().getStackTrace());
1181 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
1182 if (reportRegistrationLeaks) {
1183 StrictMode.onServiceConnectionLeaked(leak);
1184 }
1185 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001186 ActivityManager.getService().unbindService(
Adam Lesinski23d40c42014-11-20 11:58:21 -08001187 sd.getIServiceConnection());
1188 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001189 throw e.rethrowFromSystemServer();
Adam Lesinski23d40c42014-11-20 11:58:21 -08001190 }
1191 sd.doForget();
Jeff Sharkeyd7026f12012-03-01 20:50:32 -08001192 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001193 }
Adam Lesinski23d40c42014-11-20 11:58:21 -08001194 mUnboundServices.remove(context);
1195 //Slog.i(TAG, "Service registrations: " + mServices);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001196 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001197 }
1198
1199 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
1200 Context context, Handler handler,
1201 Instrumentation instrumentation, boolean registered) {
1202 synchronized (mReceivers) {
1203 LoadedApk.ReceiverDispatcher rd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001204 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001205 if (registered) {
1206 map = mReceivers.get(context);
1207 if (map != null) {
1208 rd = map.get(r);
1209 }
1210 }
1211 if (rd == null) {
1212 rd = new ReceiverDispatcher(r, context, handler,
1213 instrumentation, registered);
1214 if (registered) {
1215 if (map == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001216 map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001217 mReceivers.put(context, map);
1218 }
1219 map.put(r, rd);
1220 }
1221 } else {
1222 rd.validate(context, handler);
1223 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -08001224 rd.mForgotten = false;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001225 return rd.getIIntentReceiver();
1226 }
1227 }
1228
1229 public IIntentReceiver forgetReceiverDispatcher(Context context,
1230 BroadcastReceiver r) {
1231 synchronized (mReceivers) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001232 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001233 LoadedApk.ReceiverDispatcher rd = null;
1234 if (map != null) {
1235 rd = map.get(r);
1236 if (rd != null) {
1237 map.remove(r);
1238 if (map.size() == 0) {
1239 mReceivers.remove(context);
1240 }
1241 if (r.getDebugUnregister()) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001242 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001243 = mUnregisteredReceivers.get(context);
1244 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001245 holder = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001246 mUnregisteredReceivers.put(context, holder);
1247 }
1248 RuntimeException ex = new IllegalArgumentException(
1249 "Originally unregistered here:");
1250 ex.fillInStackTrace();
1251 rd.setUnregisterLocation(ex);
1252 holder.put(r, rd);
1253 }
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -08001254 rd.mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001255 return rd.getIIntentReceiver();
1256 }
1257 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001258 ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001259 = mUnregisteredReceivers.get(context);
1260 if (holder != null) {
1261 rd = holder.get(r);
1262 if (rd != null) {
1263 RuntimeException ex = rd.getUnregisterLocation();
1264 throw new IllegalArgumentException(
1265 "Unregistering Receiver " + r
1266 + " that was already unregistered", ex);
1267 }
1268 }
1269 if (context == null) {
1270 throw new IllegalStateException("Unbinding Receiver " + r
1271 + " from Context that is no longer in use: " + context);
1272 } else {
1273 throw new IllegalArgumentException("Receiver not registered: " + r);
1274 }
1275
1276 }
1277 }
1278
1279 static final class ReceiverDispatcher {
1280
1281 final static class InnerReceiver extends IIntentReceiver.Stub {
1282 final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
1283 final LoadedApk.ReceiverDispatcher mStrongRef;
1284
1285 InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
1286 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
1287 mStrongRef = strong ? rd : null;
1288 }
Jeff Sharkeyd136e512016-03-09 22:30:56 -07001289
1290 @Override
Dianne Hackborn20e80982012-08-31 19:00:44 -07001291 public void performReceive(Intent intent, int resultCode, String data,
1292 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn26756162016-05-17 13:40:44 -07001293 final LoadedApk.ReceiverDispatcher rd;
1294 if (intent == null) {
1295 Log.wtf(TAG, "Null intent received");
1296 rd = null;
1297 } else {
1298 rd = mDispatcher.get();
1299 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001300 if (ActivityThread.DEBUG_BROADCAST) {
1301 int seq = intent.getIntExtra("seq", -1);
Dianne Hackborn26756162016-05-17 13:40:44 -07001302 Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
1303 + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001304 }
1305 if (rd != null) {
1306 rd.performReceive(intent, resultCode, data, extras,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001307 ordered, sticky, sendingUser);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001308 } else {
1309 // The activity manager dispatched a broadcast to a registered
1310 // receiver in this process, but before it could be delivered the
1311 // receiver was unregistered. Acknowledge the broadcast on its
1312 // behalf so that the system's broadcast sequence can continue.
1313 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1314 "Finishing broadcast to unregistered receiver");
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001315 IActivityManager mgr = ActivityManager.getService();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001316 try {
Dianne Hackborn9ecebbf2011-09-28 23:19:47 -04001317 if (extras != null) {
1318 extras.setAllowFds(false);
1319 }
riddle_hsu1f5ac4d2015-01-03 15:38:21 +08001320 mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001321 } catch (RemoteException e) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001322 throw e.rethrowFromSystemServer();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001323 }
1324 }
1325 }
1326 }
1327
1328 final IIntentReceiver.Stub mIIntentReceiver;
1329 final BroadcastReceiver mReceiver;
1330 final Context mContext;
1331 final Handler mActivityThread;
1332 final Instrumentation mInstrumentation;
1333 final boolean mRegistered;
1334 final IntentReceiverLeaked mLocation;
1335 RuntimeException mUnregisterLocation;
Dianne Hackbornc2d9c8e2011-01-24 21:59:21 -08001336 boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001337
Makoto Onuki08408b92017-05-09 13:48:53 -07001338 final class Args extends BroadcastReceiver.PendingResult {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001339 private Intent mCurIntent;
Dianne Hackborne829fef2010-10-26 17:44:01 -07001340 private final boolean mOrdered;
Dianne Hackborn17c77532016-06-22 16:49:14 -07001341 private boolean mDispatched;
Makoto Onukif3bb6f32017-05-02 12:02:23 -07001342 private Throwable mPreviousRunStacktrace; // To investigate b/37809561. STOPSHIP remove.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001343
Dianne Hackborne829fef2010-10-26 17:44:01 -07001344 public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001345 boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborne829fef2010-10-26 17:44:01 -07001346 super(resultCode, resultData, resultExtras,
riddle_hsu1f5ac4d2015-01-03 15:38:21 +08001347 mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
1348 sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
Dianne Hackborne829fef2010-10-26 17:44:01 -07001349 mCurIntent = intent;
1350 mOrdered = ordered;
1351 }
Dianne Hackborn17c77532016-06-22 16:49:14 -07001352
Makoto Onuki08408b92017-05-09 13:48:53 -07001353 public final Runnable getRunnable() {
1354 return () -> {
1355 final BroadcastReceiver receiver = mReceiver;
1356 final boolean ordered = mOrdered;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001357
Makoto Onuki08408b92017-05-09 13:48:53 -07001358 if (ActivityThread.DEBUG_BROADCAST) {
1359 int seq = mCurIntent.getIntExtra("seq", -1);
1360 Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
1361 + " seq=" + seq + " to " + mReceiver);
1362 Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
1363 + " mOrderedHint=" + ordered);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001364 }
Makoto Onuki08408b92017-05-09 13:48:53 -07001365
1366 final IActivityManager mgr = ActivityManager.getService();
1367 final Intent intent = mCurIntent;
1368 if (intent == null) {
1369 Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
1370 + ": run() previously called at "
1371 + Log.getStackTraceString(mPreviousRunStacktrace));
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001372 }
Makoto Onuki08408b92017-05-09 13:48:53 -07001373
1374 mCurIntent = null;
1375 mDispatched = true;
1376 mPreviousRunStacktrace = new Throwable("Previous stacktrace");
1377 if (receiver == null || intent == null || mForgotten) {
1378 if (mRegistered && ordered) {
1379 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1380 "Finishing null broadcast to " + mReceiver);
1381 sendFinished(mgr);
1382 }
1383 return;
1384 }
1385
1386 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
1387 try {
1388 ClassLoader cl = mReceiver.getClass().getClassLoader();
1389 intent.setExtrasClassLoader(cl);
1390 intent.prepareToEnterProcess();
1391 setExtrasClassLoader(cl);
1392 receiver.setPendingResult(this);
1393 receiver.onReceive(mContext, intent);
1394 } catch (Exception e) {
1395 if (mRegistered && ordered) {
1396 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1397 "Finishing failed broadcast to " + mReceiver);
1398 sendFinished(mgr);
1399 }
1400 if (mInstrumentation == null ||
1401 !mInstrumentation.onException(mReceiver, e)) {
1402 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1403 throw new RuntimeException(
1404 "Error receiving broadcast " + intent
1405 + " in " + mReceiver, e);
1406 }
1407 }
1408
1409 if (receiver.getPendingResult() != null) {
1410 finish();
1411 }
1412 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1413 };
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001414 }
1415 }
1416
1417 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
1418 Handler activityThread, Instrumentation instrumentation,
1419 boolean registered) {
1420 if (activityThread == null) {
1421 throw new NullPointerException("Handler must not be null");
1422 }
1423
1424 mIIntentReceiver = new InnerReceiver(this, !registered);
1425 mReceiver = receiver;
1426 mContext = context;
1427 mActivityThread = activityThread;
1428 mInstrumentation = instrumentation;
1429 mRegistered = registered;
1430 mLocation = new IntentReceiverLeaked(null);
1431 mLocation.fillInStackTrace();
1432 }
1433
1434 void validate(Context context, Handler activityThread) {
1435 if (mContext != context) {
1436 throw new IllegalStateException(
1437 "Receiver " + mReceiver +
1438 " registered with differing Context (was " +
1439 mContext + " now " + context + ")");
1440 }
1441 if (mActivityThread != activityThread) {
1442 throw new IllegalStateException(
1443 "Receiver " + mReceiver +
1444 " registered with differing handler (was " +
1445 mActivityThread + " now " + activityThread + ")");
1446 }
1447 }
1448
1449 IntentReceiverLeaked getLocation() {
1450 return mLocation;
1451 }
1452
1453 BroadcastReceiver getIntentReceiver() {
1454 return mReceiver;
1455 }
1456
1457 IIntentReceiver getIIntentReceiver() {
1458 return mIIntentReceiver;
1459 }
1460
1461 void setUnregisterLocation(RuntimeException ex) {
1462 mUnregisterLocation = ex;
1463 }
1464
1465 RuntimeException getUnregisterLocation() {
1466 return mUnregisterLocation;
1467 }
1468
Dianne Hackborn20e80982012-08-31 19:00:44 -07001469 public void performReceive(Intent intent, int resultCode, String data,
1470 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
Dianne Hackborn41bfaf82016-06-08 16:33:29 -07001471 final Args args = new Args(intent, resultCode, data, extras, ordered,
Dianne Hackborn20e80982012-08-31 19:00:44 -07001472 sticky, sendingUser);
Dianne Hackborn41bfaf82016-06-08 16:33:29 -07001473 if (intent == null) {
1474 Log.wtf(TAG, "Null intent received");
1475 } else {
1476 if (ActivityThread.DEBUG_BROADCAST) {
1477 int seq = intent.getIntExtra("seq", -1);
1478 Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
1479 + " seq=" + seq + " to " + mReceiver);
1480 }
1481 }
Makoto Onuki08408b92017-05-09 13:48:53 -07001482 if (intent == null || !mActivityThread.post(args.getRunnable())) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001483 if (mRegistered && ordered) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001484 IActivityManager mgr = ActivityManager.getService();
Dianne Hackborne829fef2010-10-26 17:44:01 -07001485 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
1486 "Finishing sync broadcast to " + mReceiver);
1487 args.sendFinished(mgr);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001488 }
1489 }
1490 }
1491
1492 }
1493
1494 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1495 Context context, Handler handler, int flags) {
1496 synchronized (mServices) {
1497 LoadedApk.ServiceDispatcher sd = null;
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001498 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001499 if (map != null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001500 if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001501 sd = map.get(c);
1502 }
1503 if (sd == null) {
1504 sd = new ServiceDispatcher(c, context, handler, flags);
Dianne Hackborn94846032017-03-31 17:55:23 -07001505 if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001506 if (map == null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001507 map = new ArrayMap<>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001508 mServices.put(context, map);
1509 }
1510 map.put(c, sd);
1511 } else {
1512 sd.validate(context, handler);
1513 }
1514 return sd.getIServiceConnection();
1515 }
1516 }
1517
1518 public final IServiceConnection forgetServiceDispatcher(Context context,
1519 ServiceConnection c) {
1520 synchronized (mServices) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001521 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001522 = mServices.get(context);
1523 LoadedApk.ServiceDispatcher sd = null;
1524 if (map != null) {
1525 sd = map.get(c);
1526 if (sd != null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001527 if (DEBUG) Slog.d(TAG, "Removing dispatcher " + sd + " for conn " + c);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001528 map.remove(c);
1529 sd.doForget();
1530 if (map.size() == 0) {
1531 mServices.remove(context);
1532 }
1533 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001534 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001535 = mUnboundServices.get(context);
1536 if (holder == null) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001537 holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001538 mUnboundServices.put(context, holder);
1539 }
1540 RuntimeException ex = new IllegalArgumentException(
1541 "Originally unbound here:");
1542 ex.fillInStackTrace();
1543 sd.setUnbindLocation(ex);
1544 holder.put(c, sd);
1545 }
1546 return sd.getIServiceConnection();
1547 }
1548 }
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001549 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001550 = mUnboundServices.get(context);
1551 if (holder != null) {
1552 sd = holder.get(c);
1553 if (sd != null) {
1554 RuntimeException ex = sd.getUnbindLocation();
1555 throw new IllegalArgumentException(
1556 "Unbinding Service " + c
1557 + " that was already unbound", ex);
1558 }
1559 }
1560 if (context == null) {
1561 throw new IllegalStateException("Unbinding Service " + c
1562 + " from Context that is no longer in use: " + context);
1563 } else {
1564 throw new IllegalArgumentException("Service not registered: " + c);
1565 }
1566 }
1567 }
1568
1569 static final class ServiceDispatcher {
1570 private final ServiceDispatcher.InnerConnection mIServiceConnection;
1571 private final ServiceConnection mConnection;
1572 private final Context mContext;
1573 private final Handler mActivityThread;
1574 private final ServiceConnectionLeaked mLocation;
1575 private final int mFlags;
1576
1577 private RuntimeException mUnbindLocation;
1578
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001579 private boolean mForgotten;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001580
1581 private static class ConnectionInfo {
1582 IBinder binder;
1583 IBinder.DeathRecipient deathMonitor;
1584 }
1585
1586 private static class InnerConnection extends IServiceConnection.Stub {
1587 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1588
1589 InnerConnection(LoadedApk.ServiceDispatcher sd) {
1590 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1591 }
1592
Dianne Hackborn94846032017-03-31 17:55:23 -07001593 public void connected(ComponentName name, IBinder service, boolean dead)
1594 throws RemoteException {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001595 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1596 if (sd != null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001597 sd.connected(name, service, dead);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001598 }
1599 }
1600 }
1601
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001602 private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
1603 = new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001604
1605 ServiceDispatcher(ServiceConnection conn,
1606 Context context, Handler activityThread, int flags) {
1607 mIServiceConnection = new InnerConnection(this);
1608 mConnection = conn;
1609 mContext = context;
1610 mActivityThread = activityThread;
1611 mLocation = new ServiceConnectionLeaked(null);
1612 mLocation.fillInStackTrace();
1613 mFlags = flags;
1614 }
1615
1616 void validate(Context context, Handler activityThread) {
1617 if (mContext != context) {
1618 throw new RuntimeException(
1619 "ServiceConnection " + mConnection +
1620 " registered with differing Context (was " +
1621 mContext + " now " + context + ")");
1622 }
1623 if (mActivityThread != activityThread) {
1624 throw new RuntimeException(
1625 "ServiceConnection " + mConnection +
1626 " registered with differing handler (was " +
1627 mActivityThread + " now " + activityThread + ")");
1628 }
1629 }
1630
1631 void doForget() {
1632 synchronized(this) {
Dianne Hackbornadd005c2013-07-17 18:43:12 -07001633 for (int i=0; i<mActiveConnections.size(); i++) {
1634 ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001635 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1636 }
1637 mActiveConnections.clear();
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001638 mForgotten = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001639 }
1640 }
1641
1642 ServiceConnectionLeaked getLocation() {
1643 return mLocation;
1644 }
1645
1646 ServiceConnection getServiceConnection() {
1647 return mConnection;
1648 }
1649
1650 IServiceConnection getIServiceConnection() {
1651 return mIServiceConnection;
1652 }
1653
1654 int getFlags() {
1655 return mFlags;
1656 }
1657
1658 void setUnbindLocation(RuntimeException ex) {
1659 mUnbindLocation = ex;
1660 }
1661
1662 RuntimeException getUnbindLocation() {
1663 return mUnbindLocation;
1664 }
1665
Dianne Hackborn94846032017-03-31 17:55:23 -07001666 public void connected(ComponentName name, IBinder service, boolean dead) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001667 if (mActivityThread != null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001668 mActivityThread.post(new RunConnection(name, service, 0, dead));
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001669 } else {
Dianne Hackborn94846032017-03-31 17:55:23 -07001670 doConnected(name, service, dead);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001671 }
1672 }
1673
1674 public void death(ComponentName name, IBinder service) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001675 if (mActivityThread != null) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001676 mActivityThread.post(new RunConnection(name, service, 1, false));
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001677 } else {
1678 doDeath(name, service);
1679 }
1680 }
1681
Dianne Hackborn94846032017-03-31 17:55:23 -07001682 public void doConnected(ComponentName name, IBinder service, boolean dead) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001683 ServiceDispatcher.ConnectionInfo old;
1684 ServiceDispatcher.ConnectionInfo info;
1685
1686 synchronized (this) {
Dianne Hackborn5a6ef732011-11-11 12:31:52 -08001687 if (mForgotten) {
1688 // We unbound before receiving the connection; ignore
1689 // any connection received.
1690 return;
1691 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001692 old = mActiveConnections.get(name);
1693 if (old != null && old.binder == service) {
1694 // Huh, already have this one. Oh well!
1695 return;
1696 }
1697
1698 if (service != null) {
1699 // A new service is being connected... set it all up.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001700 info = new ConnectionInfo();
1701 info.binder = service;
1702 info.deathMonitor = new DeathMonitor(name, service);
1703 try {
1704 service.linkToDeath(info.deathMonitor, 0);
1705 mActiveConnections.put(name, info);
1706 } catch (RemoteException e) {
1707 // This service was dead before we got it... just
1708 // don't do anything with it.
1709 mActiveConnections.remove(name);
1710 return;
1711 }
1712
1713 } else {
1714 // The named service is being disconnected... clean up.
1715 mActiveConnections.remove(name);
1716 }
1717
1718 if (old != null) {
1719 old.binder.unlinkToDeath(old.deathMonitor, 0);
1720 }
1721 }
1722
Adrian Roosa9b43182016-07-21 13:20:38 -07001723 // If there was an old service, it is now disconnected.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001724 if (old != null) {
1725 mConnection.onServiceDisconnected(name);
1726 }
Dianne Hackborn94846032017-03-31 17:55:23 -07001727 if (dead) {
Dianne Hackbornac265342017-04-19 14:53:18 -07001728 mConnection.onBindingDied(name);
Dianne Hackborn94846032017-03-31 17:55:23 -07001729 }
Christopher Tate5d73b6d2017-10-06 16:15:34 -07001730 // If there is a new viable service, it is now connected.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001731 if (service != null) {
1732 mConnection.onServiceConnected(name, service);
Christopher Tate5d73b6d2017-10-06 16:15:34 -07001733 } else {
1734 // The binding machinery worked, but the remote returned null from onBind().
1735 mConnection.onNullBinding(name);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001736 }
1737 }
1738
1739 public void doDeath(ComponentName name, IBinder service) {
Adrian Roosa9b43182016-07-21 13:20:38 -07001740 synchronized (this) {
1741 ConnectionInfo old = mActiveConnections.get(name);
1742 if (old == null || old.binder != service) {
1743 // Death for someone different than who we last
1744 // reported... just ignore it.
1745 return;
1746 }
1747 mActiveConnections.remove(name);
1748 old.binder.unlinkToDeath(old.deathMonitor, 0);
1749 }
1750
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001751 mConnection.onServiceDisconnected(name);
1752 }
1753
1754 private final class RunConnection implements Runnable {
Dianne Hackborn94846032017-03-31 17:55:23 -07001755 RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001756 mName = name;
1757 mService = service;
1758 mCommand = command;
Dianne Hackborn94846032017-03-31 17:55:23 -07001759 mDead = dead;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001760 }
1761
1762 public void run() {
1763 if (mCommand == 0) {
Dianne Hackborn94846032017-03-31 17:55:23 -07001764 doConnected(mName, mService, mDead);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001765 } else if (mCommand == 1) {
1766 doDeath(mName, mService);
1767 }
1768 }
1769
1770 final ComponentName mName;
1771 final IBinder mService;
1772 final int mCommand;
Dianne Hackborn94846032017-03-31 17:55:23 -07001773 final boolean mDead;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001774 }
1775
1776 private final class DeathMonitor implements IBinder.DeathRecipient
1777 {
1778 DeathMonitor(ComponentName name, IBinder service) {
1779 mName = name;
1780 mService = service;
1781 }
1782
1783 public void binderDied() {
1784 death(mName, mService);
1785 }
1786
1787 final ComponentName mName;
1788 final IBinder mService;
1789 }
1790 }
1791}