blob: 1f2fa26d4220f7f7fda98ba8244cc7ef6cff66a2 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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
Christopher Tate45281862010-03-05 15:46:30 -080019import android.app.backup.BackupAgent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.content.BroadcastReceiver;
21import android.content.ComponentCallbacks;
22import android.content.ComponentName;
23import android.content.ContentProvider;
24import android.content.Context;
25import android.content.IContentProvider;
26import android.content.Intent;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070027import android.content.IIntentReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.content.ServiceConnection;
29import android.content.pm.ActivityInfo;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.IPackageManager;
32import android.content.pm.InstrumentationInfo;
33import android.content.pm.PackageManager;
34import android.content.pm.ProviderInfo;
35import android.content.pm.ServiceInfo;
36import android.content.res.AssetManager;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -070037import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.content.res.Configuration;
39import android.content.res.Resources;
40import android.database.sqlite.SQLiteDatabase;
41import android.database.sqlite.SQLiteDebug;
Vasu Noric3849202010-03-09 10:47:25 -080042import android.database.sqlite.SQLiteDebug.DbStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.graphics.Bitmap;
44import android.graphics.Canvas;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.os.Bundle;
46import android.os.Debug;
47import android.os.Handler;
48import android.os.IBinder;
49import android.os.Looper;
50import android.os.Message;
51import android.os.MessageQueue;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070052import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import android.os.Process;
54import android.os.RemoteException;
55import android.os.ServiceManager;
56import android.os.SystemClock;
57import android.util.AndroidRuntimeException;
58import android.util.Config;
59import android.util.DisplayMetrics;
60import android.util.EventLog;
61import android.util.Log;
Dianne Hackbornc9421ba2010-03-11 22:23:46 -080062import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.view.Display;
64import android.view.View;
65import android.view.ViewDebug;
66import android.view.ViewManager;
Dianne Hackborn2a9094d2010-02-03 19:20:09 -080067import android.view.ViewRoot;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import android.view.Window;
69import android.view.WindowManager;
70import android.view.WindowManagerImpl;
71
72import com.android.internal.os.BinderInternal;
73import com.android.internal.os.RuntimeInit;
Bob Leee5408332009-09-04 18:31:17 -070074import com.android.internal.os.SamplingProfilerIntegration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import com.android.internal.util.ArrayUtils;
76
77import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
78
79import java.io.File;
80import java.io.FileDescriptor;
81import java.io.FileOutputStream;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070082import java.io.IOException;
Brian Carlstrom778ce482010-02-09 11:23:40 -080083import java.io.InputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import java.io.PrintWriter;
85import java.lang.ref.WeakReference;
Brian Carlstrom778ce482010-02-09 11:23:40 -080086import java.net.URL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import java.util.ArrayList;
Brian Carlstrom778ce482010-02-09 11:23:40 -080088import java.util.Enumeration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import java.util.HashMap;
90import java.util.Iterator;
91import java.util.List;
92import java.util.Locale;
93import java.util.Map;
94import java.util.TimeZone;
95import java.util.regex.Pattern;
96
Bob Leee5408332009-09-04 18:31:17 -070097import dalvik.system.SamplingProfiler;
98
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099final class IntentReceiverLeaked extends AndroidRuntimeException {
100 public IntentReceiverLeaked(String msg) {
101 super(msg);
102 }
103}
104
105final class ServiceConnectionLeaked extends AndroidRuntimeException {
106 public ServiceConnectionLeaked(String msg) {
107 super(msg);
108 }
109}
110
111final class SuperNotCalledException extends AndroidRuntimeException {
112 public SuperNotCalledException(String msg) {
113 super(msg);
114 }
115}
116
117/**
118 * This manages the execution of the main thread in an
119 * application process, scheduling and executing activities,
120 * broadcasts, and other operations on it as the activity
121 * manager requests.
122 *
123 * {@hide}
124 */
125public final class ActivityThread {
126 private static final String TAG = "ActivityThread";
127 private static final boolean DEBUG = false;
128 private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
129 private static final boolean DEBUG_BROADCAST = false;
Chris Tate8a7dc172009-03-24 20:11:42 -0700130 private static final boolean DEBUG_RESULTS = false;
Christopher Tate436344a2009-09-30 16:17:37 -0700131 private static final boolean DEBUG_BACKUP = false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700132 private static final boolean DEBUG_CONFIGURATION = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
134 private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
135 private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
136 private static final int LOG_ON_PAUSE_CALLED = 30021;
137 private static final int LOG_ON_RESUME_CALLED = 30022;
138
Bob Leee5408332009-09-04 18:31:17 -0700139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 public static final ActivityThread currentActivityThread() {
141 return (ActivityThread)sThreadLocal.get();
142 }
143
144 public static final String currentPackageName()
145 {
146 ActivityThread am = currentActivityThread();
147 return (am != null && am.mBoundApplication != null)
148 ? am.mBoundApplication.processName : null;
149 }
150
151 public static IPackageManager getPackageManager() {
152 if (sPackageManager != null) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700153 //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 return sPackageManager;
155 }
156 IBinder b = ServiceManager.getService("package");
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700157 //Slog.v("PackageManager", "default service binder = " + b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 sPackageManager = IPackageManager.Stub.asInterface(b);
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700159 //Slog.v("PackageManager", "default service = " + sPackageManager);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 return sPackageManager;
161 }
162
163 DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
164 if (mDisplayMetrics != null && !forceUpdate) {
165 return mDisplayMetrics;
166 }
167 if (mDisplay == null) {
168 WindowManager wm = WindowManagerImpl.getDefault();
169 mDisplay = wm.getDefaultDisplay();
170 }
171 DisplayMetrics metrics = mDisplayMetrics = new DisplayMetrics();
172 mDisplay.getMetrics(metrics);
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700173 //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 // + metrics.heightPixels + " den=" + metrics.density
175 // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
176 return metrics;
177 }
178
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700179 /**
180 * Creates the top level Resources for applications with the given compatibility info.
181 *
182 * @param resDir the resource directory.
183 * @param compInfo the compability info. It will use the default compatibility info when it's
184 * null.
185 */
186 Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
Dianne Hackbornf9315202009-11-17 18:28:55 -0800187 ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
188 Resources r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 synchronized (mPackages) {
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700190 // Resources is app scale dependent.
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700191 if (false) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700192 Slog.w(TAG, "getTopLevelResources: " + resDir + " / "
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700193 + compInfo.applicationScale);
194 }
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700195 WeakReference<Resources> wr = mActiveResources.get(key);
Dianne Hackbornf9315202009-11-17 18:28:55 -0800196 r = wr != null ? wr.get() : null;
Dianne Hackborn4416c3d2010-05-04 17:22:49 -0700197 //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 if (r != null && r.getAssets().isUpToDate()) {
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700199 if (false) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700200 Slog.w(TAG, "Returning cached resources " + r + " " + resDir
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700201 + ": appScale=" + r.getCompatibilityInfo().applicationScale);
202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 return r;
204 }
Dianne Hackbornf9315202009-11-17 18:28:55 -0800205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206
Dianne Hackbornf9315202009-11-17 18:28:55 -0800207 //if (r != null) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700208 // Slog.w(TAG, "Throwing away out-of-date resources!!!! "
Dianne Hackbornf9315202009-11-17 18:28:55 -0800209 // + r + " " + resDir);
210 //}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211
Dianne Hackbornf9315202009-11-17 18:28:55 -0800212 AssetManager assets = new AssetManager();
213 if (assets.addAssetPath(resDir) == 0) {
214 return null;
215 }
216
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700217 //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
Dianne Hackbornf9315202009-11-17 18:28:55 -0800218 DisplayMetrics metrics = getDisplayMetricsLocked(false);
219 r = new Resources(assets, metrics, getConfiguration(), compInfo);
220 if (false) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700221 Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
Dianne Hackbornf9315202009-11-17 18:28:55 -0800222 + r.getConfiguration() + " appScale="
223 + r.getCompatibilityInfo().applicationScale);
224 }
225
226 synchronized (mPackages) {
227 WeakReference<Resources> wr = mActiveResources.get(key);
228 Resources existing = wr != null ? wr.get() : null;
229 if (existing != null && existing.getAssets().isUpToDate()) {
230 // Someone else already created the resources while we were
231 // unlocked; go ahead and use theirs.
232 r.getAssets().close();
233 return existing;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 }
Dianne Hackbornf9315202009-11-17 18:28:55 -0800235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 // XXX need to remove entries when weak references go away
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700237 mActiveResources.put(key, new WeakReference<Resources>(r));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 return r;
239 }
240 }
241
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700242 /**
243 * Creates the top level resources for the given package.
244 */
245 Resources getTopLevelResources(String resDir, PackageInfo pkgInfo) {
246 return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo);
247 }
248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 final Handler getHandler() {
250 return mH;
251 }
252
253 public final static class PackageInfo {
254
255 private final ActivityThread mActivityThread;
256 private final ApplicationInfo mApplicationInfo;
257 private final String mPackageName;
258 private final String mAppDir;
259 private final String mResDir;
260 private final String[] mSharedLibraries;
261 private final String mDataDir;
262 private final File mDataDirFile;
263 private final ClassLoader mBaseClassLoader;
264 private final boolean mSecurityViolation;
265 private final boolean mIncludeCode;
266 private Resources mResources;
267 private ClassLoader mClassLoader;
268 private Application mApplication;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700269 private CompatibilityInfo mCompatibilityInfo;
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
272 = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
273 private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mUnregisteredReceivers
274 = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
275 private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mServices
276 = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
277 private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mUnboundServices
278 = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
279
280 int mClientCount = 0;
281
Christopher Tateeb9e9ec2010-03-23 17:14:36 -0700282 Application getApplication() {
283 return mApplication;
284 }
285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 public PackageInfo(ActivityThread activityThread, ApplicationInfo aInfo,
287 ActivityThread mainThread, ClassLoader baseLoader,
288 boolean securityViolation, boolean includeCode) {
289 mActivityThread = activityThread;
290 mApplicationInfo = aInfo;
291 mPackageName = aInfo.packageName;
292 mAppDir = aInfo.sourceDir;
293 mResDir = aInfo.uid == Process.myUid() ? aInfo.sourceDir
294 : aInfo.publicSourceDir;
295 mSharedLibraries = aInfo.sharedLibraryFiles;
296 mDataDir = aInfo.dataDir;
297 mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
298 mBaseClassLoader = baseLoader;
299 mSecurityViolation = securityViolation;
300 mIncludeCode = includeCode;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700301 mCompatibilityInfo = new CompatibilityInfo(aInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302
303 if (mAppDir == null) {
304 if (mSystemContext == null) {
305 mSystemContext =
Dianne Hackborn21556372010-02-04 16:34:40 -0800306 ContextImpl.createSystemContext(mainThread);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 mSystemContext.getResources().updateConfiguration(
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700308 mainThread.getConfiguration(),
309 mainThread.getDisplayMetricsLocked(false));
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700310 //Slog.i(TAG, "Created system resources "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 // + mSystemContext.getResources() + ": "
312 // + mSystemContext.getResources().getConfiguration());
313 }
314 mClassLoader = mSystemContext.getClassLoader();
315 mResources = mSystemContext.getResources();
316 }
317 }
318
319 public PackageInfo(ActivityThread activityThread, String name,
Mike Cleron432b7132009-09-24 15:28:29 -0700320 Context systemContext, ApplicationInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 mActivityThread = activityThread;
Mike Cleron432b7132009-09-24 15:28:29 -0700322 mApplicationInfo = info != null ? info : new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 mApplicationInfo.packageName = name;
324 mPackageName = name;
325 mAppDir = null;
326 mResDir = null;
327 mSharedLibraries = null;
328 mDataDir = null;
329 mDataDirFile = null;
330 mBaseClassLoader = null;
331 mSecurityViolation = false;
332 mIncludeCode = true;
333 mClassLoader = systemContext.getClassLoader();
334 mResources = systemContext.getResources();
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700335 mCompatibilityInfo = new CompatibilityInfo(mApplicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 }
337
338 public String getPackageName() {
339 return mPackageName;
340 }
341
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700342 public ApplicationInfo getApplicationInfo() {
343 return mApplicationInfo;
344 }
Bob Leee5408332009-09-04 18:31:17 -0700345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 public boolean isSecurityViolation() {
347 return mSecurityViolation;
348 }
349
350 /**
351 * Gets the array of shared libraries that are listed as
352 * used by the given package.
Bob Leee5408332009-09-04 18:31:17 -0700353 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 * @param packageName the name of the package (note: not its
355 * file name)
356 * @return null-ok; the array of shared libraries, each one
357 * a fully-qualified path
358 */
359 private static String[] getLibrariesFor(String packageName) {
360 ApplicationInfo ai = null;
361 try {
362 ai = getPackageManager().getApplicationInfo(packageName,
363 PackageManager.GET_SHARED_LIBRARY_FILES);
364 } catch (RemoteException e) {
365 throw new AssertionError(e);
366 }
367
368 if (ai == null) {
369 return null;
370 }
371
372 return ai.sharedLibraryFiles;
373 }
374
375 /**
376 * Combines two arrays (of library names) such that they are
377 * concatenated in order but are devoid of duplicates. The
378 * result is a single string with the names of the libraries
379 * separated by colons, or <code>null</code> if both lists
380 * were <code>null</code> or empty.
Bob Leee5408332009-09-04 18:31:17 -0700381 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 * @param list1 null-ok; the first list
383 * @param list2 null-ok; the second list
384 * @return null-ok; the combination
385 */
386 private static String combineLibs(String[] list1, String[] list2) {
387 StringBuilder result = new StringBuilder(300);
388 boolean first = true;
389
390 if (list1 != null) {
391 for (String s : list1) {
392 if (first) {
393 first = false;
394 } else {
395 result.append(':');
396 }
397 result.append(s);
398 }
399 }
400
401 // Only need to check for duplicates if list1 was non-empty.
402 boolean dupCheck = !first;
403
404 if (list2 != null) {
405 for (String s : list2) {
406 if (dupCheck && ArrayUtils.contains(list1, s)) {
407 continue;
408 }
Bob Leee5408332009-09-04 18:31:17 -0700409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 if (first) {
411 first = false;
412 } else {
413 result.append(':');
414 }
415 result.append(s);
416 }
417 }
418
419 return result.toString();
420 }
Bob Leee5408332009-09-04 18:31:17 -0700421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 public ClassLoader getClassLoader() {
423 synchronized (this) {
424 if (mClassLoader != null) {
425 return mClassLoader;
426 }
427
428 if (mIncludeCode && !mPackageName.equals("android")) {
429 String zip = mAppDir;
430
431 /*
432 * The following is a bit of a hack to inject
433 * instrumentation into the system: If the app
434 * being started matches one of the instrumentation names,
435 * then we combine both the "instrumentation" and
436 * "instrumented" app into the path, along with the
437 * concatenation of both apps' shared library lists.
438 */
439
440 String instrumentationAppDir =
441 mActivityThread.mInstrumentationAppDir;
442 String instrumentationAppPackage =
443 mActivityThread.mInstrumentationAppPackage;
444 String instrumentedAppDir =
445 mActivityThread.mInstrumentedAppDir;
446 String[] instrumentationLibs = null;
447
448 if (mAppDir.equals(instrumentationAppDir)
449 || mAppDir.equals(instrumentedAppDir)) {
450 zip = instrumentationAppDir + ":" + instrumentedAppDir;
451 if (! instrumentedAppDir.equals(instrumentationAppDir)) {
452 instrumentationLibs =
453 getLibrariesFor(instrumentationAppPackage);
454 }
455 }
456
457 if ((mSharedLibraries != null) ||
458 (instrumentationLibs != null)) {
Bob Leee5408332009-09-04 18:31:17 -0700459 zip =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 combineLibs(mSharedLibraries, instrumentationLibs)
461 + ':' + zip;
462 }
463
464 /*
465 * With all the combination done (if necessary, actually
466 * create the class loader.
467 */
468
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700469 if (localLOGV) Slog.v(TAG, "Class path: " + zip);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470
471 mClassLoader =
472 ApplicationLoaders.getDefault().getClassLoader(
473 zip, mDataDir, mBaseClassLoader);
Brian Carlstrom778ce482010-02-09 11:23:40 -0800474 initializeJavaContextClassLoader();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 } else {
476 if (mBaseClassLoader == null) {
477 mClassLoader = ClassLoader.getSystemClassLoader();
478 } else {
479 mClassLoader = mBaseClassLoader;
480 }
481 }
482 return mClassLoader;
483 }
484 }
485
Brian Carlstrom778ce482010-02-09 11:23:40 -0800486 /**
487 * Setup value for Thread.getContextClassLoader(). If the
488 * package will not run in in a VM with other packages, we set
489 * the Java context ClassLoader to the
490 * PackageInfo.getClassLoader value. However, if this VM can
491 * contain multiple packages, we intead set the Java context
492 * ClassLoader to a proxy that will warn about the use of Java
493 * context ClassLoaders and then fall through to use the
494 * system ClassLoader.
495 *
496 * <p> Note that this is similar to but not the same as the
497 * android.content.Context.getClassLoader(). While both
498 * context class loaders are typically set to the
499 * PathClassLoader used to load the package archive in the
500 * single application per VM case, a single Android process
501 * may contain several Contexts executing on one thread with
502 * their own logical ClassLoaders while the Java context
503 * ClassLoader is a thread local. This is why in the case when
504 * we have multiple packages per VM we do not set the Java
505 * context ClassLoader to an arbitrary but instead warn the
506 * user to set their own if we detect that they are using a
507 * Java library that expects it to be set.
508 */
509 private void initializeJavaContextClassLoader() {
510 IPackageManager pm = getPackageManager();
511 android.content.pm.PackageInfo pi;
512 try {
513 pi = pm.getPackageInfo(mPackageName, 0);
514 } catch (RemoteException e) {
515 throw new AssertionError(e);
516 }
517 /*
518 * Two possible indications that this package could be
519 * sharing its virtual machine with other packages:
520 *
521 * 1.) the sharedUserId attribute is set in the manifest,
522 * indicating a request to share a VM with other
523 * packages with the same sharedUserId.
524 *
525 * 2.) the application element of the manifest has an
526 * attribute specifying a non-default process name,
527 * indicating the desire to run in another packages VM.
528 */
529 boolean sharedUserIdSet = (pi.sharedUserId != null);
530 boolean processNameNotDefault =
531 (pi.applicationInfo != null &&
532 !mPackageName.equals(pi.applicationInfo.processName));
533 boolean sharable = (sharedUserIdSet || processNameNotDefault);
534 ClassLoader contextClassLoader =
535 (sharable)
536 ? new WarningContextClassLoader()
537 : mClassLoader;
538 Thread.currentThread().setContextClassLoader(contextClassLoader);
539 }
540
541 private static class WarningContextClassLoader extends ClassLoader {
542
543 private static boolean warned = false;
544
545 private void warn(String methodName) {
546 if (warned) {
547 return;
548 }
549 warned = true;
550 Thread.currentThread().setContextClassLoader(getParent());
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800551 Slog.w(TAG, "ClassLoader." + methodName + ": " +
Brian Carlstrom778ce482010-02-09 11:23:40 -0800552 "The class loader returned by " +
553 "Thread.getContextClassLoader() may fail for processes " +
554 "that host multiple applications. You should explicitly " +
555 "specify a context class loader. For example: " +
556 "Thread.setContextClassLoader(getClass().getClassLoader());");
557 }
558
559 @Override public URL getResource(String resName) {
560 warn("getResource");
561 return getParent().getResource(resName);
562 }
563
564 @Override public Enumeration<URL> getResources(String resName) throws IOException {
565 warn("getResources");
566 return getParent().getResources(resName);
567 }
568
569 @Override public InputStream getResourceAsStream(String resName) {
570 warn("getResourceAsStream");
571 return getParent().getResourceAsStream(resName);
572 }
573
574 @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
575 warn("loadClass");
576 return getParent().loadClass(className);
577 }
578
579 @Override public void setClassAssertionStatus(String cname, boolean enable) {
580 warn("setClassAssertionStatus");
581 getParent().setClassAssertionStatus(cname, enable);
582 }
583
584 @Override public void setPackageAssertionStatus(String pname, boolean enable) {
585 warn("setPackageAssertionStatus");
586 getParent().setPackageAssertionStatus(pname, enable);
587 }
588
589 @Override public void setDefaultAssertionStatus(boolean enable) {
590 warn("setDefaultAssertionStatus");
591 getParent().setDefaultAssertionStatus(enable);
592 }
593
594 @Override public void clearAssertionStatus() {
595 warn("clearAssertionStatus");
596 getParent().clearAssertionStatus();
597 }
598 }
599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 public String getAppDir() {
601 return mAppDir;
602 }
603
604 public String getResDir() {
605 return mResDir;
606 }
607
608 public String getDataDir() {
609 return mDataDir;
610 }
611
612 public File getDataDirFile() {
613 return mDataDirFile;
614 }
615
616 public AssetManager getAssets(ActivityThread mainThread) {
617 return getResources(mainThread).getAssets();
618 }
619
620 public Resources getResources(ActivityThread mainThread) {
621 if (mResources == null) {
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700622 mResources = mainThread.getTopLevelResources(mResDir, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 }
624 return mResources;
625 }
626
Dianne Hackborn0be1f782009-11-09 12:30:12 -0800627 public Application makeApplication(boolean forceDefaultAppClass,
628 Instrumentation instrumentation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 if (mApplication != null) {
630 return mApplication;
631 }
Bob Leee5408332009-09-04 18:31:17 -0700632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 Application app = null;
Bob Leee5408332009-09-04 18:31:17 -0700634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635 String appClass = mApplicationInfo.className;
Christopher Tate181fafa2009-05-14 11:12:14 -0700636 if (forceDefaultAppClass || (appClass == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 appClass = "android.app.Application";
638 }
639
640 try {
641 java.lang.ClassLoader cl = getClassLoader();
Dianne Hackborn21556372010-02-04 16:34:40 -0800642 ContextImpl appContext = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 appContext.init(this, null, mActivityThread);
644 app = mActivityThread.mInstrumentation.newApplication(
645 cl, appClass, appContext);
646 appContext.setOuterContext(app);
647 } catch (Exception e) {
648 if (!mActivityThread.mInstrumentation.onException(app, e)) {
649 throw new RuntimeException(
650 "Unable to instantiate application " + appClass
651 + ": " + e.toString(), e);
652 }
653 }
654 mActivityThread.mAllApplications.add(app);
Dianne Hackborn0be1f782009-11-09 12:30:12 -0800655 mApplication = app;
Christopher Tateeb9e9ec2010-03-23 17:14:36 -0700656
Dianne Hackborn0be1f782009-11-09 12:30:12 -0800657 if (instrumentation != null) {
658 try {
659 instrumentation.callApplicationOnCreate(app);
660 } catch (Exception e) {
661 if (!instrumentation.onException(app, e)) {
662 throw new RuntimeException(
663 "Unable to create application " + app.getClass().getName()
664 + ": " + e.toString(), e);
665 }
666 }
667 }
668
669 return app;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 }
Bob Leee5408332009-09-04 18:31:17 -0700671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 public void removeContextRegistrations(Context context,
673 String who, String what) {
674 HashMap<BroadcastReceiver, ReceiverDispatcher> rmap =
675 mReceivers.remove(context);
676 if (rmap != null) {
677 Iterator<ReceiverDispatcher> it = rmap.values().iterator();
678 while (it.hasNext()) {
679 ReceiverDispatcher rd = it.next();
680 IntentReceiverLeaked leak = new IntentReceiverLeaked(
681 what + " " + who + " has leaked IntentReceiver "
682 + rd.getIntentReceiver() + " that was " +
683 "originally registered here. Are you missing a " +
684 "call to unregisterReceiver()?");
685 leak.setStackTrace(rd.getLocation().getStackTrace());
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800686 Slog.e(TAG, leak.getMessage(), leak);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 try {
688 ActivityManagerNative.getDefault().unregisterReceiver(
689 rd.getIIntentReceiver());
690 } catch (RemoteException e) {
691 // system crashed, nothing we can do
692 }
693 }
694 }
695 mUnregisteredReceivers.remove(context);
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700696 //Slog.i(TAG, "Receiver registrations: " + mReceivers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 HashMap<ServiceConnection, ServiceDispatcher> smap =
698 mServices.remove(context);
699 if (smap != null) {
700 Iterator<ServiceDispatcher> it = smap.values().iterator();
701 while (it.hasNext()) {
702 ServiceDispatcher sd = it.next();
703 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
704 what + " " + who + " has leaked ServiceConnection "
705 + sd.getServiceConnection() + " that was originally bound here");
706 leak.setStackTrace(sd.getLocation().getStackTrace());
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800707 Slog.e(TAG, leak.getMessage(), leak);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 try {
709 ActivityManagerNative.getDefault().unbindService(
710 sd.getIServiceConnection());
711 } catch (RemoteException e) {
712 // system crashed, nothing we can do
713 }
714 sd.doForget();
715 }
716 }
717 mUnboundServices.remove(context);
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700718 //Slog.i(TAG, "Service registrations: " + mServices);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 }
720
721 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
722 Context context, Handler handler,
723 Instrumentation instrumentation, boolean registered) {
724 synchronized (mReceivers) {
725 ReceiverDispatcher rd = null;
726 HashMap<BroadcastReceiver, ReceiverDispatcher> map = null;
727 if (registered) {
728 map = mReceivers.get(context);
729 if (map != null) {
730 rd = map.get(r);
731 }
732 }
733 if (rd == null) {
734 rd = new ReceiverDispatcher(r, context, handler,
735 instrumentation, registered);
736 if (registered) {
737 if (map == null) {
738 map = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
739 mReceivers.put(context, map);
740 }
741 map.put(r, rd);
742 }
743 } else {
744 rd.validate(context, handler);
745 }
746 return rd.getIIntentReceiver();
747 }
748 }
749
750 public IIntentReceiver forgetReceiverDispatcher(Context context,
751 BroadcastReceiver r) {
752 synchronized (mReceivers) {
753 HashMap<BroadcastReceiver, ReceiverDispatcher> map = mReceivers.get(context);
754 ReceiverDispatcher rd = null;
755 if (map != null) {
756 rd = map.get(r);
757 if (rd != null) {
758 map.remove(r);
759 if (map.size() == 0) {
760 mReceivers.remove(context);
761 }
762 if (r.getDebugUnregister()) {
763 HashMap<BroadcastReceiver, ReceiverDispatcher> holder
764 = mUnregisteredReceivers.get(context);
765 if (holder == null) {
766 holder = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
767 mUnregisteredReceivers.put(context, holder);
768 }
769 RuntimeException ex = new IllegalArgumentException(
770 "Originally unregistered here:");
771 ex.fillInStackTrace();
772 rd.setUnregisterLocation(ex);
773 holder.put(r, rd);
774 }
775 return rd.getIIntentReceiver();
776 }
777 }
778 HashMap<BroadcastReceiver, ReceiverDispatcher> holder
779 = mUnregisteredReceivers.get(context);
780 if (holder != null) {
781 rd = holder.get(r);
782 if (rd != null) {
783 RuntimeException ex = rd.getUnregisterLocation();
784 throw new IllegalArgumentException(
785 "Unregistering Receiver " + r
786 + " that was already unregistered", ex);
787 }
788 }
789 if (context == null) {
790 throw new IllegalStateException("Unbinding Receiver " + r
791 + " from Context that is no longer in use: " + context);
792 } else {
793 throw new IllegalArgumentException("Receiver not registered: " + r);
794 }
795
796 }
797 }
798
799 static final class ReceiverDispatcher {
800
801 final static class InnerReceiver extends IIntentReceiver.Stub {
802 final WeakReference<ReceiverDispatcher> mDispatcher;
803 final ReceiverDispatcher mStrongRef;
Bob Leee5408332009-09-04 18:31:17 -0700804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 InnerReceiver(ReceiverDispatcher rd, boolean strong) {
806 mDispatcher = new WeakReference<ReceiverDispatcher>(rd);
807 mStrongRef = strong ? rd : null;
808 }
809 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700810 String data, Bundle extras, boolean ordered, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811 ReceiverDispatcher rd = mDispatcher.get();
812 if (DEBUG_BROADCAST) {
813 int seq = intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700814 Slog.i(TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
815 + " to " + (rd != null ? rd.mReceiver : null));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 }
817 if (rd != null) {
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700818 rd.performReceive(intent, resultCode, data, extras,
819 ordered, sticky);
Christopher Tate08a46252009-12-08 13:48:45 -0800820 } else {
821 // The activity manager dispatched a broadcast to a registered
822 // receiver in this process, but before it could be delivered the
823 // receiver was unregistered. Acknowledge the broadcast on its
824 // behalf so that the system's broadcast sequence can continue.
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700825 if (DEBUG_BROADCAST) Slog.i(TAG,
826 "Finishing broadcast to unregistered receiver");
Christopher Tate08a46252009-12-08 13:48:45 -0800827 IActivityManager mgr = ActivityManagerNative.getDefault();
828 try {
829 mgr.finishReceiver(this, resultCode, data, extras, false);
830 } catch (RemoteException e) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800831 Slog.w(TAG, "Couldn't finish broadcast to unregistered receiver");
Christopher Tate08a46252009-12-08 13:48:45 -0800832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 }
834 }
835 }
Bob Leee5408332009-09-04 18:31:17 -0700836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 final IIntentReceiver.Stub mIIntentReceiver;
838 final BroadcastReceiver mReceiver;
839 final Context mContext;
840 final Handler mActivityThread;
841 final Instrumentation mInstrumentation;
842 final boolean mRegistered;
843 final IntentReceiverLeaked mLocation;
844 RuntimeException mUnregisterLocation;
845
846 final class Args implements Runnable {
847 private Intent mCurIntent;
848 private int mCurCode;
849 private String mCurData;
850 private Bundle mCurMap;
851 private boolean mCurOrdered;
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700852 private boolean mCurSticky;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853
854 public void run() {
855 BroadcastReceiver receiver = mReceiver;
856 if (DEBUG_BROADCAST) {
857 int seq = mCurIntent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700858 Slog.i(TAG, "Dispatching broadcast " + mCurIntent.getAction()
Christopher Tate08a46252009-12-08 13:48:45 -0800859 + " seq=" + seq + " to " + mReceiver);
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700860 Slog.i(TAG, " mRegistered=" + mRegistered
861 + " mCurOrdered=" + mCurOrdered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 IActivityManager mgr = ActivityManagerNative.getDefault();
865 Intent intent = mCurIntent;
866 mCurIntent = null;
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700867
868 if (receiver == null) {
869 if (mRegistered && mCurOrdered) {
870 try {
871 if (DEBUG_BROADCAST) Slog.i(TAG,
872 "Finishing null broadcast to " + mReceiver);
873 mgr.finishReceiver(mIIntentReceiver,
874 mCurCode, mCurData, mCurMap, false);
875 } catch (RemoteException ex) {
876 }
877 }
878 return;
879 }
880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 try {
882 ClassLoader cl = mReceiver.getClass().getClassLoader();
883 intent.setExtrasClassLoader(cl);
884 if (mCurMap != null) {
885 mCurMap.setClassLoader(cl);
886 }
887 receiver.setOrderedHint(true);
888 receiver.setResult(mCurCode, mCurData, mCurMap);
889 receiver.clearAbortBroadcast();
890 receiver.setOrderedHint(mCurOrdered);
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700891 receiver.setInitialStickyHint(mCurSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 receiver.onReceive(mContext, intent);
893 } catch (Exception e) {
894 if (mRegistered && mCurOrdered) {
895 try {
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700896 if (DEBUG_BROADCAST) Slog.i(TAG,
897 "Finishing failed broadcast to " + mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 mgr.finishReceiver(mIIntentReceiver,
899 mCurCode, mCurData, mCurMap, false);
900 } catch (RemoteException ex) {
901 }
902 }
903 if (mInstrumentation == null ||
904 !mInstrumentation.onException(mReceiver, e)) {
905 throw new RuntimeException(
906 "Error receiving broadcast " + intent
907 + " in " + mReceiver, e);
908 }
909 }
910 if (mRegistered && mCurOrdered) {
911 try {
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700912 if (DEBUG_BROADCAST) Slog.i(TAG,
913 "Finishing broadcast to " + mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 mgr.finishReceiver(mIIntentReceiver,
915 receiver.getResultCode(),
916 receiver.getResultData(),
917 receiver.getResultExtras(false),
918 receiver.getAbortBroadcast());
919 } catch (RemoteException ex) {
920 }
921 }
922 }
923 }
924
925 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
926 Handler activityThread, Instrumentation instrumentation,
927 boolean registered) {
928 if (activityThread == null) {
929 throw new NullPointerException("Handler must not be null");
930 }
931
932 mIIntentReceiver = new InnerReceiver(this, !registered);
933 mReceiver = receiver;
934 mContext = context;
935 mActivityThread = activityThread;
936 mInstrumentation = instrumentation;
937 mRegistered = registered;
938 mLocation = new IntentReceiverLeaked(null);
939 mLocation.fillInStackTrace();
940 }
941
942 void validate(Context context, Handler activityThread) {
943 if (mContext != context) {
944 throw new IllegalStateException(
945 "Receiver " + mReceiver +
946 " registered with differing Context (was " +
947 mContext + " now " + context + ")");
948 }
949 if (mActivityThread != activityThread) {
950 throw new IllegalStateException(
951 "Receiver " + mReceiver +
952 " registered with differing handler (was " +
953 mActivityThread + " now " + activityThread + ")");
954 }
955 }
956
957 IntentReceiverLeaked getLocation() {
958 return mLocation;
959 }
960
961 BroadcastReceiver getIntentReceiver() {
962 return mReceiver;
963 }
Bob Leee5408332009-09-04 18:31:17 -0700964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 IIntentReceiver getIIntentReceiver() {
966 return mIIntentReceiver;
967 }
968
969 void setUnregisterLocation(RuntimeException ex) {
970 mUnregisterLocation = ex;
971 }
972
973 RuntimeException getUnregisterLocation() {
974 return mUnregisterLocation;
975 }
976
977 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700978 String data, Bundle extras, boolean ordered, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 if (DEBUG_BROADCAST) {
980 int seq = intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700981 Slog.i(TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 + " to " + mReceiver);
983 }
984 Args args = new Args();
985 args.mCurIntent = intent;
986 args.mCurCode = resultCode;
987 args.mCurData = data;
988 args.mCurMap = extras;
989 args.mCurOrdered = ordered;
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700990 args.mCurSticky = sticky;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 if (!mActivityThread.post(args)) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700992 if (mRegistered && ordered) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 IActivityManager mgr = ActivityManagerNative.getDefault();
994 try {
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700995 if (DEBUG_BROADCAST) Slog.i(TAG,
996 "Finishing sync broadcast to " + mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 mgr.finishReceiver(mIIntentReceiver, args.mCurCode,
998 args.mCurData, args.mCurMap, false);
999 } catch (RemoteException ex) {
1000 }
1001 }
1002 }
1003 }
1004
1005 }
1006
1007 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
1008 Context context, Handler handler, int flags) {
1009 synchronized (mServices) {
1010 ServiceDispatcher sd = null;
1011 HashMap<ServiceConnection, ServiceDispatcher> map = mServices.get(context);
1012 if (map != null) {
1013 sd = map.get(c);
1014 }
1015 if (sd == null) {
1016 sd = new ServiceDispatcher(c, context, handler, flags);
1017 if (map == null) {
1018 map = new HashMap<ServiceConnection, ServiceDispatcher>();
1019 mServices.put(context, map);
1020 }
1021 map.put(c, sd);
1022 } else {
1023 sd.validate(context, handler);
1024 }
1025 return sd.getIServiceConnection();
1026 }
1027 }
1028
1029 public final IServiceConnection forgetServiceDispatcher(Context context,
1030 ServiceConnection c) {
1031 synchronized (mServices) {
1032 HashMap<ServiceConnection, ServiceDispatcher> map
1033 = mServices.get(context);
1034 ServiceDispatcher sd = null;
1035 if (map != null) {
1036 sd = map.get(c);
1037 if (sd != null) {
1038 map.remove(c);
1039 sd.doForget();
1040 if (map.size() == 0) {
1041 mServices.remove(context);
1042 }
1043 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
1044 HashMap<ServiceConnection, ServiceDispatcher> holder
1045 = mUnboundServices.get(context);
1046 if (holder == null) {
1047 holder = new HashMap<ServiceConnection, ServiceDispatcher>();
1048 mUnboundServices.put(context, holder);
1049 }
1050 RuntimeException ex = new IllegalArgumentException(
1051 "Originally unbound here:");
1052 ex.fillInStackTrace();
1053 sd.setUnbindLocation(ex);
1054 holder.put(c, sd);
1055 }
1056 return sd.getIServiceConnection();
1057 }
1058 }
1059 HashMap<ServiceConnection, ServiceDispatcher> holder
1060 = mUnboundServices.get(context);
1061 if (holder != null) {
1062 sd = holder.get(c);
1063 if (sd != null) {
1064 RuntimeException ex = sd.getUnbindLocation();
1065 throw new IllegalArgumentException(
1066 "Unbinding Service " + c
1067 + " that was already unbound", ex);
1068 }
1069 }
1070 if (context == null) {
1071 throw new IllegalStateException("Unbinding Service " + c
1072 + " from Context that is no longer in use: " + context);
1073 } else {
1074 throw new IllegalArgumentException("Service not registered: " + c);
1075 }
1076 }
1077 }
1078
1079 static final class ServiceDispatcher {
1080 private final InnerConnection mIServiceConnection;
1081 private final ServiceConnection mConnection;
1082 private final Context mContext;
1083 private final Handler mActivityThread;
1084 private final ServiceConnectionLeaked mLocation;
1085 private final int mFlags;
1086
1087 private RuntimeException mUnbindLocation;
1088
1089 private boolean mDied;
1090
1091 private static class ConnectionInfo {
1092 IBinder binder;
1093 IBinder.DeathRecipient deathMonitor;
1094 }
1095
1096 private static class InnerConnection extends IServiceConnection.Stub {
1097 final WeakReference<ServiceDispatcher> mDispatcher;
Bob Leee5408332009-09-04 18:31:17 -07001098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 InnerConnection(ServiceDispatcher sd) {
1100 mDispatcher = new WeakReference<ServiceDispatcher>(sd);
1101 }
1102
1103 public void connected(ComponentName name, IBinder service) throws RemoteException {
1104 ServiceDispatcher sd = mDispatcher.get();
1105 if (sd != null) {
1106 sd.connected(name, service);
1107 }
1108 }
1109 }
Bob Leee5408332009-09-04 18:31:17 -07001110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 private final HashMap<ComponentName, ConnectionInfo> mActiveConnections
1112 = new HashMap<ComponentName, ConnectionInfo>();
1113
1114 ServiceDispatcher(ServiceConnection conn,
1115 Context context, Handler activityThread, int flags) {
1116 mIServiceConnection = new InnerConnection(this);
1117 mConnection = conn;
1118 mContext = context;
1119 mActivityThread = activityThread;
1120 mLocation = new ServiceConnectionLeaked(null);
1121 mLocation.fillInStackTrace();
1122 mFlags = flags;
1123 }
1124
1125 void validate(Context context, Handler activityThread) {
1126 if (mContext != context) {
1127 throw new RuntimeException(
1128 "ServiceConnection " + mConnection +
1129 " registered with differing Context (was " +
1130 mContext + " now " + context + ")");
1131 }
1132 if (mActivityThread != activityThread) {
1133 throw new RuntimeException(
1134 "ServiceConnection " + mConnection +
1135 " registered with differing handler (was " +
1136 mActivityThread + " now " + activityThread + ")");
1137 }
1138 }
1139
1140 void doForget() {
1141 synchronized(this) {
1142 Iterator<ConnectionInfo> it = mActiveConnections.values().iterator();
1143 while (it.hasNext()) {
1144 ConnectionInfo ci = it.next();
1145 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1146 }
1147 mActiveConnections.clear();
1148 }
1149 }
1150
1151 ServiceConnectionLeaked getLocation() {
1152 return mLocation;
1153 }
1154
1155 ServiceConnection getServiceConnection() {
1156 return mConnection;
1157 }
1158
1159 IServiceConnection getIServiceConnection() {
1160 return mIServiceConnection;
1161 }
Bob Leee5408332009-09-04 18:31:17 -07001162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 int getFlags() {
1164 return mFlags;
1165 }
1166
1167 void setUnbindLocation(RuntimeException ex) {
1168 mUnbindLocation = ex;
1169 }
1170
1171 RuntimeException getUnbindLocation() {
1172 return mUnbindLocation;
1173 }
1174
1175 public void connected(ComponentName name, IBinder service) {
1176 if (mActivityThread != null) {
1177 mActivityThread.post(new RunConnection(name, service, 0));
1178 } else {
1179 doConnected(name, service);
1180 }
1181 }
1182
1183 public void death(ComponentName name, IBinder service) {
1184 ConnectionInfo old;
1185
1186 synchronized (this) {
1187 mDied = true;
1188 old = mActiveConnections.remove(name);
1189 if (old == null || old.binder != service) {
1190 // Death for someone different than who we last
1191 // reported... just ignore it.
1192 return;
1193 }
1194 old.binder.unlinkToDeath(old.deathMonitor, 0);
1195 }
1196
1197 if (mActivityThread != null) {
1198 mActivityThread.post(new RunConnection(name, service, 1));
1199 } else {
1200 doDeath(name, service);
1201 }
1202 }
1203
1204 public void doConnected(ComponentName name, IBinder service) {
1205 ConnectionInfo old;
1206 ConnectionInfo info;
1207
1208 synchronized (this) {
1209 old = mActiveConnections.get(name);
1210 if (old != null && old.binder == service) {
1211 // Huh, already have this one. Oh well!
1212 return;
1213 }
1214
1215 if (service != null) {
1216 // A new service is being connected... set it all up.
1217 mDied = false;
1218 info = new ConnectionInfo();
1219 info.binder = service;
1220 info.deathMonitor = new DeathMonitor(name, service);
1221 try {
1222 service.linkToDeath(info.deathMonitor, 0);
1223 mActiveConnections.put(name, info);
1224 } catch (RemoteException e) {
1225 // This service was dead before we got it... just
1226 // don't do anything with it.
1227 mActiveConnections.remove(name);
1228 return;
1229 }
1230
1231 } else {
1232 // The named service is being disconnected... clean up.
1233 mActiveConnections.remove(name);
1234 }
1235
1236 if (old != null) {
1237 old.binder.unlinkToDeath(old.deathMonitor, 0);
1238 }
1239 }
1240
1241 // If there was an old service, it is not disconnected.
1242 if (old != null) {
1243 mConnection.onServiceDisconnected(name);
1244 }
1245 // If there is a new service, it is now connected.
1246 if (service != null) {
1247 mConnection.onServiceConnected(name, service);
1248 }
1249 }
1250
1251 public void doDeath(ComponentName name, IBinder service) {
1252 mConnection.onServiceDisconnected(name);
1253 }
1254
1255 private final class RunConnection implements Runnable {
1256 RunConnection(ComponentName name, IBinder service, int command) {
1257 mName = name;
1258 mService = service;
1259 mCommand = command;
1260 }
1261
1262 public void run() {
1263 if (mCommand == 0) {
1264 doConnected(mName, mService);
1265 } else if (mCommand == 1) {
1266 doDeath(mName, mService);
1267 }
1268 }
1269
1270 final ComponentName mName;
1271 final IBinder mService;
1272 final int mCommand;
1273 }
1274
1275 private final class DeathMonitor implements IBinder.DeathRecipient
1276 {
1277 DeathMonitor(ComponentName name, IBinder service) {
1278 mName = name;
1279 mService = service;
1280 }
1281
1282 public void binderDied() {
1283 death(mName, mService);
1284 }
1285
1286 final ComponentName mName;
1287 final IBinder mService;
1288 }
1289 }
1290 }
1291
Dianne Hackborn21556372010-02-04 16:34:40 -08001292 private static ContextImpl mSystemContext = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293
1294 private static final class ActivityRecord {
1295 IBinder token;
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001296 int ident;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001297 Intent intent;
1298 Bundle state;
1299 Activity activity;
1300 Window window;
1301 Activity parent;
1302 String embeddedID;
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001303 Activity.NonConfigurationInstances lastNonConfigurationInstances;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304 boolean paused;
1305 boolean stopped;
1306 boolean hideForNow;
1307 Configuration newConfig;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001308 Configuration createdConfig;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001309 ActivityRecord nextIdle;
1310
1311 ActivityInfo activityInfo;
1312 PackageInfo packageInfo;
1313
1314 List<ResultInfo> pendingResults;
1315 List<Intent> pendingIntents;
1316
1317 boolean startsNotResumed;
1318 boolean isForward;
1319
1320 ActivityRecord() {
1321 parent = null;
1322 embeddedID = null;
1323 paused = false;
1324 stopped = false;
1325 hideForNow = false;
1326 nextIdle = null;
1327 }
1328
1329 public String toString() {
1330 ComponentName componentName = intent.getComponent();
1331 return "ActivityRecord{"
1332 + Integer.toHexString(System.identityHashCode(this))
1333 + " token=" + token + " " + (componentName == null
1334 ? "no component name" : componentName.toShortString())
1335 + "}";
1336 }
1337 }
1338
1339 private final class ProviderRecord implements IBinder.DeathRecipient {
1340 final String mName;
1341 final IContentProvider mProvider;
1342 final ContentProvider mLocalProvider;
1343
1344 ProviderRecord(String name, IContentProvider provider,
1345 ContentProvider localProvider) {
1346 mName = name;
1347 mProvider = provider;
1348 mLocalProvider = localProvider;
1349 }
1350
1351 public void binderDied() {
1352 removeDeadProvider(mName, mProvider);
1353 }
1354 }
1355
1356 private static final class NewIntentData {
1357 List<Intent> intents;
1358 IBinder token;
1359 public String toString() {
1360 return "NewIntentData{intents=" + intents + " token=" + token + "}";
1361 }
1362 }
1363
1364 private static final class ReceiverData {
1365 Intent intent;
1366 ActivityInfo info;
1367 int resultCode;
1368 String resultData;
1369 Bundle resultExtras;
1370 boolean sync;
1371 boolean resultAbort;
1372 public String toString() {
1373 return "ReceiverData{intent=" + intent + " packageName=" +
1374 info.packageName + " resultCode=" + resultCode
1375 + " resultData=" + resultData + " resultExtras=" + resultExtras + "}";
1376 }
1377 }
1378
Christopher Tate181fafa2009-05-14 11:12:14 -07001379 private static final class CreateBackupAgentData {
1380 ApplicationInfo appInfo;
1381 int backupMode;
1382 public String toString() {
1383 return "CreateBackupAgentData{appInfo=" + appInfo
1384 + " backupAgent=" + appInfo.backupAgentName
1385 + " mode=" + backupMode + "}";
1386 }
1387 }
Bob Leee5408332009-09-04 18:31:17 -07001388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 private static final class CreateServiceData {
1390 IBinder token;
1391 ServiceInfo info;
1392 Intent intent;
1393 public String toString() {
1394 return "CreateServiceData{token=" + token + " className="
1395 + info.name + " packageName=" + info.packageName
1396 + " intent=" + intent + "}";
1397 }
1398 }
1399
1400 private static final class BindServiceData {
1401 IBinder token;
1402 Intent intent;
1403 boolean rebind;
1404 public String toString() {
1405 return "BindServiceData{token=" + token + " intent=" + intent + "}";
1406 }
1407 }
1408
1409 private static final class ServiceArgsData {
1410 IBinder token;
1411 int startId;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07001412 int flags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 Intent args;
1414 public String toString() {
1415 return "ServiceArgsData{token=" + token + " startId=" + startId
1416 + " args=" + args + "}";
1417 }
1418 }
1419
1420 private static final class AppBindData {
1421 PackageInfo info;
1422 String processName;
1423 ApplicationInfo appInfo;
1424 List<ProviderInfo> providers;
1425 ComponentName instrumentationName;
1426 String profileFile;
1427 Bundle instrumentationArgs;
1428 IInstrumentationWatcher instrumentationWatcher;
1429 int debugMode;
Christopher Tate181fafa2009-05-14 11:12:14 -07001430 boolean restrictedBackupMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431 Configuration config;
1432 boolean handlingProfiling;
1433 public String toString() {
1434 return "AppBindData{appInfo=" + appInfo + "}";
1435 }
1436 }
1437
1438 private static final class DumpServiceInfo {
1439 FileDescriptor fd;
1440 IBinder service;
1441 String[] args;
1442 boolean dumped;
1443 }
1444
1445 private static final class ResultData {
1446 IBinder token;
1447 List<ResultInfo> results;
1448 public String toString() {
1449 return "ResultData{token=" + token + " results" + results + "}";
1450 }
1451 }
1452
1453 private static final class ContextCleanupInfo {
Dianne Hackborn21556372010-02-04 16:34:40 -08001454 ContextImpl context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 String what;
1456 String who;
1457 }
1458
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07001459 private static final class ProfilerControlData {
1460 String path;
1461 ParcelFileDescriptor fd;
1462 }
1463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 private final class ApplicationThread extends ApplicationThreadNative {
1465 private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
1466 private static final String ONE_COUNT_COLUMN = "%17s %8d";
1467 private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
Vasu Nori90a367262010-04-12 12:49:09 -07001468 private static final String DB_INFO_FORMAT = " %4d %6d %8d %14s %s";
Bob Leee5408332009-09-04 18:31:17 -07001469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 // Formatting for checkin service - update version if row format changes
1471 private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
Bob Leee5408332009-09-04 18:31:17 -07001472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 public final void schedulePauseActivity(IBinder token, boolean finished,
1474 boolean userLeaving, int configChanges) {
1475 queueOrSendMessage(
1476 finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
1477 token,
1478 (userLeaving ? 1 : 0),
1479 configChanges);
1480 }
1481
1482 public final void scheduleStopActivity(IBinder token, boolean showWindow,
1483 int configChanges) {
1484 queueOrSendMessage(
1485 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
1486 token, 0, configChanges);
1487 }
1488
1489 public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
1490 queueOrSendMessage(
1491 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
1492 token);
1493 }
1494
1495 public final void scheduleResumeActivity(IBinder token, boolean isForward) {
1496 queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
1497 }
1498
1499 public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
1500 ResultData res = new ResultData();
1501 res.token = token;
1502 res.results = results;
1503 queueOrSendMessage(H.SEND_RESULT, res);
1504 }
1505
1506 // we use token to identify this activity without having to send the
1507 // activity itself back to the activity manager. (matters more with ipc)
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001508 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
1510 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
1511 ActivityRecord r = new ActivityRecord();
1512
1513 r.token = token;
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001514 r.ident = ident;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 r.intent = intent;
1516 r.activityInfo = info;
1517 r.state = state;
1518
1519 r.pendingResults = pendingResults;
1520 r.pendingIntents = pendingNewIntents;
1521
1522 r.startsNotResumed = notResumed;
1523 r.isForward = isForward;
1524
1525 queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
1526 }
1527
1528 public final void scheduleRelaunchActivity(IBinder token,
1529 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -08001530 int configChanges, boolean notResumed, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 ActivityRecord r = new ActivityRecord();
1532
1533 r.token = token;
1534 r.pendingResults = pendingResults;
1535 r.pendingIntents = pendingNewIntents;
1536 r.startsNotResumed = notResumed;
Dianne Hackborn871ecdc2009-12-11 15:24:33 -08001537 r.createdConfig = config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001539 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 mRelaunchingActivities.add(r);
1541 }
Bob Leee5408332009-09-04 18:31:17 -07001542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges);
1544 }
1545
1546 public final void scheduleNewIntent(List<Intent> intents, IBinder token) {
1547 NewIntentData data = new NewIntentData();
1548 data.intents = intents;
1549 data.token = token;
1550
1551 queueOrSendMessage(H.NEW_INTENT, data);
1552 }
1553
1554 public final void scheduleDestroyActivity(IBinder token, boolean finishing,
1555 int configChanges) {
1556 queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
1557 configChanges);
1558 }
1559
1560 public final void scheduleReceiver(Intent intent, ActivityInfo info,
1561 int resultCode, String data, Bundle extras, boolean sync) {
1562 ReceiverData r = new ReceiverData();
1563
1564 r.intent = intent;
1565 r.info = info;
1566 r.resultCode = resultCode;
1567 r.resultData = data;
1568 r.resultExtras = extras;
1569 r.sync = sync;
1570
1571 queueOrSendMessage(H.RECEIVER, r);
1572 }
1573
Christopher Tate181fafa2009-05-14 11:12:14 -07001574 public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) {
1575 CreateBackupAgentData d = new CreateBackupAgentData();
1576 d.appInfo = app;
1577 d.backupMode = backupMode;
1578
1579 queueOrSendMessage(H.CREATE_BACKUP_AGENT, d);
1580 }
1581
1582 public final void scheduleDestroyBackupAgent(ApplicationInfo app) {
1583 CreateBackupAgentData d = new CreateBackupAgentData();
1584 d.appInfo = app;
1585
1586 queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d);
1587 }
1588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 public final void scheduleCreateService(IBinder token,
1590 ServiceInfo info) {
1591 CreateServiceData s = new CreateServiceData();
1592 s.token = token;
1593 s.info = info;
1594
1595 queueOrSendMessage(H.CREATE_SERVICE, s);
1596 }
1597
1598 public final void scheduleBindService(IBinder token, Intent intent,
1599 boolean rebind) {
1600 BindServiceData s = new BindServiceData();
1601 s.token = token;
1602 s.intent = intent;
1603 s.rebind = rebind;
1604
1605 queueOrSendMessage(H.BIND_SERVICE, s);
1606 }
1607
1608 public final void scheduleUnbindService(IBinder token, Intent intent) {
1609 BindServiceData s = new BindServiceData();
1610 s.token = token;
1611 s.intent = intent;
1612
1613 queueOrSendMessage(H.UNBIND_SERVICE, s);
1614 }
1615
1616 public final void scheduleServiceArgs(IBinder token, int startId,
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07001617 int flags ,Intent args) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 ServiceArgsData s = new ServiceArgsData();
1619 s.token = token;
1620 s.startId = startId;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07001621 s.flags = flags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 s.args = args;
1623
1624 queueOrSendMessage(H.SERVICE_ARGS, s);
1625 }
1626
1627 public final void scheduleStopService(IBinder token) {
1628 queueOrSendMessage(H.STOP_SERVICE, token);
1629 }
1630
1631 public final void bindApplication(String processName,
1632 ApplicationInfo appInfo, List<ProviderInfo> providers,
1633 ComponentName instrumentationName, String profileFile,
1634 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
Christopher Tate181fafa2009-05-14 11:12:14 -07001635 int debugMode, boolean isRestrictedBackupMode, Configuration config,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 Map<String, IBinder> services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637
1638 if (services != null) {
1639 // Setup the service cache in the ServiceManager
1640 ServiceManager.initServiceCache(services);
1641 }
1642
1643 AppBindData data = new AppBindData();
1644 data.processName = processName;
1645 data.appInfo = appInfo;
1646 data.providers = providers;
1647 data.instrumentationName = instrumentationName;
1648 data.profileFile = profileFile;
1649 data.instrumentationArgs = instrumentationArgs;
1650 data.instrumentationWatcher = instrumentationWatcher;
1651 data.debugMode = debugMode;
Christopher Tate181fafa2009-05-14 11:12:14 -07001652 data.restrictedBackupMode = isRestrictedBackupMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 data.config = config;
1654 queueOrSendMessage(H.BIND_APPLICATION, data);
1655 }
1656
1657 public final void scheduleExit() {
1658 queueOrSendMessage(H.EXIT_APPLICATION, null);
1659 }
1660
Christopher Tate5e1ab332009-09-01 20:32:49 -07001661 public final void scheduleSuicide() {
1662 queueOrSendMessage(H.SUICIDE, null);
1663 }
1664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 public void requestThumbnail(IBinder token) {
1666 queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
1667 }
1668
1669 public void scheduleConfigurationChanged(Configuration config) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001670 synchronized (mPackages) {
1671 if (mPendingConfiguration == null ||
1672 mPendingConfiguration.isOtherSeqNewer(config)) {
1673 mPendingConfiguration = config;
1674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 }
1676 queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
1677 }
1678
1679 public void updateTimeZone() {
1680 TimeZone.setDefault(null);
1681 }
1682
1683 public void processInBackground() {
1684 mH.removeMessages(H.GC_WHEN_IDLE);
1685 mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
1686 }
1687
1688 public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
1689 DumpServiceInfo data = new DumpServiceInfo();
1690 data.fd = fd;
1691 data.service = servicetoken;
1692 data.args = args;
1693 data.dumped = false;
1694 queueOrSendMessage(H.DUMP_SERVICE, data);
1695 synchronized (data) {
1696 while (!data.dumped) {
1697 try {
1698 data.wait();
1699 } catch (InterruptedException e) {
1700 // no need to do anything here, we will keep waiting until
1701 // dumped is set
1702 }
1703 }
1704 }
1705 }
1706
1707 // This function exists to make sure all receiver dispatching is
1708 // correctly ordered, since these are one-way calls and the binder driver
1709 // applies transaction ordering per object for such calls.
1710 public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07001711 int resultCode, String dataStr, Bundle extras, boolean ordered,
1712 boolean sticky) throws RemoteException {
1713 receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 }
Bob Leee5408332009-09-04 18:31:17 -07001715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 public void scheduleLowMemory() {
1717 queueOrSendMessage(H.LOW_MEMORY, null);
1718 }
1719
1720 public void scheduleActivityConfigurationChanged(IBinder token) {
1721 queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
1722 }
1723
1724 public void requestPss() {
1725 try {
1726 ActivityManagerNative.getDefault().reportPss(this,
1727 (int)Process.getPss(Process.myPid()));
1728 } catch (RemoteException e) {
1729 }
1730 }
Bob Leee5408332009-09-04 18:31:17 -07001731
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07001732 public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
1733 ProfilerControlData pcd = new ProfilerControlData();
1734 pcd.path = path;
1735 pcd.fd = fd;
1736 queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001737 }
1738
Dianne Hackborn06de2ea2009-05-21 12:56:43 -07001739 public void setSchedulingGroup(int group) {
1740 // Note: do this immediately, since going into the foreground
1741 // should happen regardless of what pending work we have to do
1742 // and the activity manager will wait for us to report back that
1743 // we are done before sending us to the background.
1744 try {
1745 Process.setProcessGroup(Process.myPid(), group);
1746 } catch (Exception e) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08001747 Slog.w(TAG, "Failed setting process group to " + group, e);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -07001748 }
1749 }
Bob Leee5408332009-09-04 18:31:17 -07001750
Dianne Hackborn3025ef32009-08-31 21:31:47 -07001751 public void getMemoryInfo(Debug.MemoryInfo outInfo) {
1752 Debug.getMemoryInfo(outInfo);
1753 }
Bob Leee5408332009-09-04 18:31:17 -07001754
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07001755 public void dispatchPackageBroadcast(int cmd, String[] packages) {
1756 queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
1757 }
1758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 @Override
1760 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1761 long nativeMax = Debug.getNativeHeapSize() / 1024;
1762 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
1763 long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
1764
1765 Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
1766 Debug.getMemoryInfo(memInfo);
1767
1768 final int nativeShared = memInfo.nativeSharedDirty;
1769 final int dalvikShared = memInfo.dalvikSharedDirty;
1770 final int otherShared = memInfo.otherSharedDirty;
1771
1772 final int nativePrivate = memInfo.nativePrivateDirty;
1773 final int dalvikPrivate = memInfo.dalvikPrivateDirty;
1774 final int otherPrivate = memInfo.otherPrivateDirty;
1775
1776 Runtime runtime = Runtime.getRuntime();
1777
1778 long dalvikMax = runtime.totalMemory() / 1024;
1779 long dalvikFree = runtime.freeMemory() / 1024;
1780 long dalvikAllocated = dalvikMax - dalvikFree;
1781 long viewInstanceCount = ViewDebug.getViewInstanceCount();
1782 long viewRootInstanceCount = ViewDebug.getViewRootInstanceCount();
Dianne Hackborn21556372010-02-04 16:34:40 -08001783 long appContextInstanceCount = ContextImpl.getInstanceCount();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 long activityInstanceCount = Activity.getInstanceCount();
1785 int globalAssetCount = AssetManager.getGlobalAssetCount();
1786 int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
1787 int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
1788 int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
1789 int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
1790 int openSslSocketCount = OpenSSLSocketImpl.getInstanceCount();
1791 long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024;
Vasu Noric3849202010-03-09 10:47:25 -08001792 SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
Bob Leee5408332009-09-04 18:31:17 -07001793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 // Check to see if we were called by checkin server. If so, print terse format.
1795 boolean doCheckinFormat = false;
1796 if (args != null) {
1797 for (String arg : args) {
1798 if ("-c".equals(arg)) doCheckinFormat = true;
1799 }
1800 }
Bob Leee5408332009-09-04 18:31:17 -07001801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 // For checkin, we print one long comma-separated list of values
1803 if (doCheckinFormat) {
1804 // NOTE: if you change anything significant below, also consider changing
1805 // ACTIVITY_THREAD_CHECKIN_VERSION.
Bob Leee5408332009-09-04 18:31:17 -07001806 String processName = (mBoundApplication != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001807 ? mBoundApplication.processName : "unknown";
Bob Leee5408332009-09-04 18:31:17 -07001808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 // Header
1810 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
1811 pw.print(Process.myPid()); pw.print(',');
1812 pw.print(processName); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 // Heap info - max
1815 pw.print(nativeMax); pw.print(',');
1816 pw.print(dalvikMax); pw.print(',');
1817 pw.print("N/A,");
1818 pw.print(nativeMax + dalvikMax); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 // Heap info - allocated
1821 pw.print(nativeAllocated); pw.print(',');
1822 pw.print(dalvikAllocated); pw.print(',');
1823 pw.print("N/A,");
1824 pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001826 // Heap info - free
1827 pw.print(nativeFree); pw.print(',');
1828 pw.print(dalvikFree); pw.print(',');
1829 pw.print("N/A,");
1830 pw.print(nativeFree + dalvikFree); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 // Heap info - proportional set size
1833 pw.print(memInfo.nativePss); pw.print(',');
1834 pw.print(memInfo.dalvikPss); pw.print(',');
1835 pw.print(memInfo.otherPss); pw.print(',');
1836 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838 // Heap info - shared
Bob Leee5408332009-09-04 18:31:17 -07001839 pw.print(nativeShared); pw.print(',');
1840 pw.print(dalvikShared); pw.print(',');
1841 pw.print(otherShared); pw.print(',');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001842 pw.print(nativeShared + dalvikShared + otherShared); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 // Heap info - private
Bob Leee5408332009-09-04 18:31:17 -07001845 pw.print(nativePrivate); pw.print(',');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 pw.print(dalvikPrivate); pw.print(',');
1847 pw.print(otherPrivate); pw.print(',');
1848 pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 // Object counts
1851 pw.print(viewInstanceCount); pw.print(',');
1852 pw.print(viewRootInstanceCount); pw.print(',');
1853 pw.print(appContextInstanceCount); pw.print(',');
1854 pw.print(activityInstanceCount); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 pw.print(globalAssetCount); pw.print(',');
1857 pw.print(globalAssetManagerCount); pw.print(',');
1858 pw.print(binderLocalObjectCount); pw.print(',');
1859 pw.print(binderProxyObjectCount); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 pw.print(binderDeathObjectCount); pw.print(',');
1862 pw.print(openSslSocketCount); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864 // SQL
1865 pw.print(sqliteAllocated); pw.print(',');
Vasu Noric3849202010-03-09 10:47:25 -08001866 pw.print(stats.memoryUsed / 1024); pw.print(',');
1867 pw.print(stats.pageCacheOverflo / 1024); pw.print(',');
1868 pw.print(stats.largestMemAlloc / 1024); pw.print(',');
1869 for (int i = 0; i < stats.dbStats.size(); i++) {
1870 DbStats dbStats = stats.dbStats.get(i);
1871 printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
Vasu Nori90a367262010-04-12 12:49:09 -07001872 dbStats.lookaside, dbStats.cache, dbStats.dbName);
Vasu Noric3849202010-03-09 10:47:25 -08001873 pw.print(',');
1874 }
Bob Leee5408332009-09-04 18:31:17 -07001875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 return;
1877 }
Bob Leee5408332009-09-04 18:31:17 -07001878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 // otherwise, show human-readable format
1880 printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total");
1881 printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
1882 printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
1883 nativeAllocated + dalvikAllocated);
1884 printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A",
1885 nativeFree + dalvikFree);
1886
1887 printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
1888 memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);
1889
1890 printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared,
1891 nativeShared + dalvikShared + otherShared);
1892 printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
1893 nativePrivate + dalvikPrivate + otherPrivate);
1894
1895 pw.println(" ");
1896 pw.println(" Objects");
1897 printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRoots:",
1898 viewRootInstanceCount);
1899
1900 printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
1901 "Activities:", activityInstanceCount);
1902
1903 printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
1904 "AssetManagers:", globalAssetManagerCount);
1905
1906 printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
1907 "Proxy Binders:", binderProxyObjectCount);
1908 printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount);
1909
1910 printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount);
Bob Leee5408332009-09-04 18:31:17 -07001911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 // SQLite mem info
1913 pw.println(" ");
1914 pw.println(" SQL");
Vasu Noric3849202010-03-09 10:47:25 -08001915 printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "memoryUsed:",
1916 stats.memoryUsed / 1024);
1917 printRow(pw, TWO_COUNT_COLUMNS, "pageCacheOverflo:", stats.pageCacheOverflo / 1024,
1918 "largestMemAlloc:", stats.largestMemAlloc / 1024);
1919 pw.println(" ");
1920 int N = stats.dbStats.size();
1921 if (N > 0) {
1922 pw.println(" DATABASES");
Vasu Nori90a367262010-04-12 12:49:09 -07001923 printRow(pw, " %4s %6s %8s %14s %s", "pgsz", "dbsz", "lkaside", "cache",
1924 "Dbname");
Vasu Noric3849202010-03-09 10:47:25 -08001925 for (int i = 0; i < N; i++) {
1926 DbStats dbStats = stats.dbStats.get(i);
1927 printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
Vasu Nori90a367262010-04-12 12:49:09 -07001928 dbStats.lookaside, dbStats.cache, dbStats.dbName);
Vasu Noric3849202010-03-09 10:47:25 -08001929 }
1930 }
Bob Leee5408332009-09-04 18:31:17 -07001931
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001932 // Asset details.
1933 String assetAlloc = AssetManager.getAssetAllocations();
1934 if (assetAlloc != null) {
1935 pw.println(" ");
1936 pw.println(" Asset Allocations");
1937 pw.print(assetAlloc);
1938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 }
1940
1941 private void printRow(PrintWriter pw, String format, Object...objs) {
1942 pw.println(String.format(format, objs));
1943 }
1944 }
1945
1946 private final class H extends Handler {
Bob Leee5408332009-09-04 18:31:17 -07001947 private H() {
1948 SamplingProfiler.getInstance().setEventThread(mLooper.getThread());
1949 }
1950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001951 public static final int LAUNCH_ACTIVITY = 100;
1952 public static final int PAUSE_ACTIVITY = 101;
1953 public static final int PAUSE_ACTIVITY_FINISHING= 102;
1954 public static final int STOP_ACTIVITY_SHOW = 103;
1955 public static final int STOP_ACTIVITY_HIDE = 104;
1956 public static final int SHOW_WINDOW = 105;
1957 public static final int HIDE_WINDOW = 106;
1958 public static final int RESUME_ACTIVITY = 107;
1959 public static final int SEND_RESULT = 108;
1960 public static final int DESTROY_ACTIVITY = 109;
1961 public static final int BIND_APPLICATION = 110;
1962 public static final int EXIT_APPLICATION = 111;
1963 public static final int NEW_INTENT = 112;
1964 public static final int RECEIVER = 113;
1965 public static final int CREATE_SERVICE = 114;
1966 public static final int SERVICE_ARGS = 115;
1967 public static final int STOP_SERVICE = 116;
1968 public static final int REQUEST_THUMBNAIL = 117;
1969 public static final int CONFIGURATION_CHANGED = 118;
1970 public static final int CLEAN_UP_CONTEXT = 119;
1971 public static final int GC_WHEN_IDLE = 120;
1972 public static final int BIND_SERVICE = 121;
1973 public static final int UNBIND_SERVICE = 122;
1974 public static final int DUMP_SERVICE = 123;
1975 public static final int LOW_MEMORY = 124;
1976 public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
1977 public static final int RELAUNCH_ACTIVITY = 126;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001978 public static final int PROFILER_CONTROL = 127;
Christopher Tate181fafa2009-05-14 11:12:14 -07001979 public static final int CREATE_BACKUP_AGENT = 128;
Christopher Tate5e1ab332009-09-01 20:32:49 -07001980 public static final int DESTROY_BACKUP_AGENT = 129;
1981 public static final int SUICIDE = 130;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001982 public static final int REMOVE_PROVIDER = 131;
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08001983 public static final int ENABLE_JIT = 132;
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07001984 public static final int DISPATCH_PACKAGE_BROADCAST = 133;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 String codeToString(int code) {
1986 if (localLOGV) {
1987 switch (code) {
1988 case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
1989 case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
1990 case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
1991 case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
1992 case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
1993 case SHOW_WINDOW: return "SHOW_WINDOW";
1994 case HIDE_WINDOW: return "HIDE_WINDOW";
1995 case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
1996 case SEND_RESULT: return "SEND_RESULT";
1997 case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
1998 case BIND_APPLICATION: return "BIND_APPLICATION";
1999 case EXIT_APPLICATION: return "EXIT_APPLICATION";
2000 case NEW_INTENT: return "NEW_INTENT";
2001 case RECEIVER: return "RECEIVER";
2002 case CREATE_SERVICE: return "CREATE_SERVICE";
2003 case SERVICE_ARGS: return "SERVICE_ARGS";
2004 case STOP_SERVICE: return "STOP_SERVICE";
2005 case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
2006 case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
2007 case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
2008 case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
2009 case BIND_SERVICE: return "BIND_SERVICE";
2010 case UNBIND_SERVICE: return "UNBIND_SERVICE";
2011 case DUMP_SERVICE: return "DUMP_SERVICE";
2012 case LOW_MEMORY: return "LOW_MEMORY";
2013 case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
2014 case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08002015 case PROFILER_CONTROL: return "PROFILER_CONTROL";
Christopher Tate181fafa2009-05-14 11:12:14 -07002016 case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
2017 case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
Christopher Tate5e1ab332009-09-01 20:32:49 -07002018 case SUICIDE: return "SUICIDE";
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07002019 case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002020 case ENABLE_JIT: return "ENABLE_JIT";
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07002021 case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002022 }
2023 }
2024 return "(unknown)";
2025 }
2026 public void handleMessage(Message msg) {
2027 switch (msg.what) {
2028 case LAUNCH_ACTIVITY: {
2029 ActivityRecord r = (ActivityRecord)msg.obj;
2030
2031 r.packageInfo = getPackageInfoNoCheck(
2032 r.activityInfo.applicationInfo);
Christopher Tateb70f3df2009-04-07 16:07:59 -07002033 handleLaunchActivity(r, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002034 } break;
2035 case RELAUNCH_ACTIVITY: {
2036 ActivityRecord r = (ActivityRecord)msg.obj;
2037 handleRelaunchActivity(r, msg.arg1);
2038 } break;
2039 case PAUSE_ACTIVITY:
2040 handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
Bob Leee5408332009-09-04 18:31:17 -07002041 maybeSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002042 break;
2043 case PAUSE_ACTIVITY_FINISHING:
2044 handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
2045 break;
2046 case STOP_ACTIVITY_SHOW:
2047 handleStopActivity((IBinder)msg.obj, true, msg.arg2);
2048 break;
2049 case STOP_ACTIVITY_HIDE:
2050 handleStopActivity((IBinder)msg.obj, false, msg.arg2);
2051 break;
2052 case SHOW_WINDOW:
2053 handleWindowVisibility((IBinder)msg.obj, true);
2054 break;
2055 case HIDE_WINDOW:
2056 handleWindowVisibility((IBinder)msg.obj, false);
2057 break;
2058 case RESUME_ACTIVITY:
2059 handleResumeActivity((IBinder)msg.obj, true,
2060 msg.arg1 != 0);
2061 break;
2062 case SEND_RESULT:
2063 handleSendResult((ResultData)msg.obj);
2064 break;
2065 case DESTROY_ACTIVITY:
2066 handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
2067 msg.arg2, false);
2068 break;
2069 case BIND_APPLICATION:
2070 AppBindData data = (AppBindData)msg.obj;
2071 handleBindApplication(data);
2072 break;
2073 case EXIT_APPLICATION:
2074 if (mInitialApplication != null) {
2075 mInitialApplication.onTerminate();
2076 }
2077 Looper.myLooper().quit();
2078 break;
2079 case NEW_INTENT:
2080 handleNewIntent((NewIntentData)msg.obj);
2081 break;
2082 case RECEIVER:
2083 handleReceiver((ReceiverData)msg.obj);
Bob Leee5408332009-09-04 18:31:17 -07002084 maybeSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 break;
2086 case CREATE_SERVICE:
2087 handleCreateService((CreateServiceData)msg.obj);
2088 break;
2089 case BIND_SERVICE:
2090 handleBindService((BindServiceData)msg.obj);
2091 break;
2092 case UNBIND_SERVICE:
2093 handleUnbindService((BindServiceData)msg.obj);
2094 break;
2095 case SERVICE_ARGS:
2096 handleServiceArgs((ServiceArgsData)msg.obj);
2097 break;
2098 case STOP_SERVICE:
2099 handleStopService((IBinder)msg.obj);
Bob Leee5408332009-09-04 18:31:17 -07002100 maybeSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002101 break;
2102 case REQUEST_THUMBNAIL:
2103 handleRequestThumbnail((IBinder)msg.obj);
2104 break;
2105 case CONFIGURATION_CHANGED:
2106 handleConfigurationChanged((Configuration)msg.obj);
2107 break;
2108 case CLEAN_UP_CONTEXT:
2109 ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
2110 cci.context.performFinalCleanup(cci.who, cci.what);
2111 break;
2112 case GC_WHEN_IDLE:
2113 scheduleGcIdler();
2114 break;
2115 case DUMP_SERVICE:
2116 handleDumpService((DumpServiceInfo)msg.obj);
2117 break;
2118 case LOW_MEMORY:
2119 handleLowMemory();
2120 break;
2121 case ACTIVITY_CONFIGURATION_CHANGED:
2122 handleActivityConfigurationChanged((IBinder)msg.obj);
2123 break;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08002124 case PROFILER_CONTROL:
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07002125 handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08002126 break;
Christopher Tate181fafa2009-05-14 11:12:14 -07002127 case CREATE_BACKUP_AGENT:
2128 handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
2129 break;
2130 case DESTROY_BACKUP_AGENT:
2131 handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
2132 break;
Christopher Tate5e1ab332009-09-01 20:32:49 -07002133 case SUICIDE:
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07002134 Process.killProcess(Process.myPid());
2135 break;
2136 case REMOVE_PROVIDER:
2137 completeRemoveProvider((IContentProvider)msg.obj);
Christopher Tate5e1ab332009-09-01 20:32:49 -07002138 break;
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002139 case ENABLE_JIT:
2140 ensureJitEnabled();
2141 break;
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07002142 case DISPATCH_PACKAGE_BROADCAST:
2143 handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
2144 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002145 }
2146 }
Bob Leee5408332009-09-04 18:31:17 -07002147
2148 void maybeSnapshot() {
2149 if (mBoundApplication != null) {
2150 SamplingProfilerIntegration.writeSnapshot(
2151 mBoundApplication.processName);
2152 }
2153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 }
2155
2156 private final class Idler implements MessageQueue.IdleHandler {
2157 public final boolean queueIdle() {
2158 ActivityRecord a = mNewActivities;
2159 if (a != null) {
2160 mNewActivities = null;
2161 IActivityManager am = ActivityManagerNative.getDefault();
2162 ActivityRecord prev;
2163 do {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002164 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165 TAG, "Reporting idle of " + a +
2166 " finished=" +
2167 (a.activity != null ? a.activity.mFinished : false));
2168 if (a.activity != null && !a.activity.mFinished) {
2169 try {
Dianne Hackborne88846e2009-09-30 21:34:25 -07002170 am.activityIdle(a.token, a.createdConfig);
2171 a.createdConfig = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 } catch (RemoteException ex) {
2173 }
2174 }
2175 prev = a;
2176 a = a.nextIdle;
2177 prev.nextIdle = null;
2178 } while (a != null);
2179 }
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002180 ensureJitEnabled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 return false;
2182 }
2183 }
2184
2185 final class GcIdler implements MessageQueue.IdleHandler {
2186 public final boolean queueIdle() {
2187 doGcIfNeeded();
2188 return false;
2189 }
2190 }
2191
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07002192 private final static class ResourcesKey {
2193 final private String mResDir;
2194 final private float mScale;
2195 final private int mHash;
Bob Leee5408332009-09-04 18:31:17 -07002196
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07002197 ResourcesKey(String resDir, float scale) {
2198 mResDir = resDir;
2199 mScale = scale;
2200 mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
2201 }
Bob Leee5408332009-09-04 18:31:17 -07002202
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07002203 @Override
2204 public int hashCode() {
2205 return mHash;
2206 }
2207
2208 @Override
2209 public boolean equals(Object obj) {
2210 if (!(obj instanceof ResourcesKey)) {
2211 return false;
2212 }
2213 ResourcesKey peer = (ResourcesKey) obj;
2214 return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
2215 }
2216 }
2217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 static IPackageManager sPackageManager;
2219
2220 final ApplicationThread mAppThread = new ApplicationThread();
2221 final Looper mLooper = Looper.myLooper();
2222 final H mH = new H();
2223 final HashMap<IBinder, ActivityRecord> mActivities
2224 = new HashMap<IBinder, ActivityRecord>();
2225 // List of new activities (via ActivityRecord.nextIdle) that should
2226 // be reported when next we idle.
2227 ActivityRecord mNewActivities = null;
2228 // Number of activities that are currently visible on-screen.
2229 int mNumVisibleActivities = 0;
2230 final HashMap<IBinder, Service> mServices
2231 = new HashMap<IBinder, Service>();
2232 AppBindData mBoundApplication;
2233 Configuration mConfiguration;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002234 Configuration mResConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002235 Application mInitialApplication;
2236 final ArrayList<Application> mAllApplications
2237 = new ArrayList<Application>();
Christopher Tate181fafa2009-05-14 11:12:14 -07002238 // set of instantiated backup agents, keyed by package name
2239 final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002240 static final ThreadLocal sThreadLocal = new ThreadLocal();
2241 Instrumentation mInstrumentation;
2242 String mInstrumentationAppDir = null;
2243 String mInstrumentationAppPackage = null;
2244 String mInstrumentedAppDir = null;
2245 boolean mSystemThread = false;
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002246 boolean mJitEnabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002248 // These can be accessed by multiple threads; mPackages is the lock.
2249 // XXX For now we keep around information about all packages we have
2250 // seen, not removing entries from this map.
2251 final HashMap<String, WeakReference<PackageInfo>> mPackages
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07002252 = new HashMap<String, WeakReference<PackageInfo>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 final HashMap<String, WeakReference<PackageInfo>> mResourcePackages
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07002254 = new HashMap<String, WeakReference<PackageInfo>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002255 Display mDisplay = null;
2256 DisplayMetrics mDisplayMetrics = null;
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07002257 final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
2258 = new HashMap<ResourcesKey, WeakReference<Resources> >();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002259 final ArrayList<ActivityRecord> mRelaunchingActivities
2260 = new ArrayList<ActivityRecord>();
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07002261 Configuration mPendingConfiguration = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002262
2263 // The lock of mProviderMap protects the following variables.
2264 final HashMap<String, ProviderRecord> mProviderMap
2265 = new HashMap<String, ProviderRecord>();
2266 final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
2267 = new HashMap<IBinder, ProviderRefCount>();
2268 final HashMap<IBinder, ProviderRecord> mLocalProviders
2269 = new HashMap<IBinder, ProviderRecord>();
2270
2271 final GcIdler mGcIdler = new GcIdler();
2272 boolean mGcIdlerScheduled = false;
2273
2274 public final PackageInfo getPackageInfo(String packageName, int flags) {
2275 synchronized (mPackages) {
2276 WeakReference<PackageInfo> ref;
2277 if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
2278 ref = mPackages.get(packageName);
2279 } else {
2280 ref = mResourcePackages.get(packageName);
2281 }
2282 PackageInfo packageInfo = ref != null ? ref.get() : null;
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002283 //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07002284 //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
2285 // + ": " + packageInfo.mResources.getAssets().isUpToDate());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002286 if (packageInfo != null && (packageInfo.mResources == null
2287 || packageInfo.mResources.getAssets().isUpToDate())) {
2288 if (packageInfo.isSecurityViolation()
2289 && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
2290 throw new SecurityException(
2291 "Requesting code from " + packageName
2292 + " to be run in process "
2293 + mBoundApplication.processName
2294 + "/" + mBoundApplication.appInfo.uid);
2295 }
2296 return packageInfo;
2297 }
2298 }
2299
2300 ApplicationInfo ai = null;
2301 try {
2302 ai = getPackageManager().getApplicationInfo(packageName,
2303 PackageManager.GET_SHARED_LIBRARY_FILES);
2304 } catch (RemoteException e) {
2305 }
2306
2307 if (ai != null) {
2308 return getPackageInfo(ai, flags);
2309 }
2310
2311 return null;
2312 }
2313
2314 public final PackageInfo getPackageInfo(ApplicationInfo ai, int flags) {
2315 boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
2316 boolean securityViolation = includeCode && ai.uid != 0
2317 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
2318 ? ai.uid != mBoundApplication.appInfo.uid : true);
2319 if ((flags&(Context.CONTEXT_INCLUDE_CODE
2320 |Context.CONTEXT_IGNORE_SECURITY))
2321 == Context.CONTEXT_INCLUDE_CODE) {
2322 if (securityViolation) {
2323 String msg = "Requesting code from " + ai.packageName
2324 + " (with uid " + ai.uid + ")";
2325 if (mBoundApplication != null) {
2326 msg = msg + " to be run in process "
2327 + mBoundApplication.processName + " (with uid "
2328 + mBoundApplication.appInfo.uid + ")";
2329 }
2330 throw new SecurityException(msg);
2331 }
2332 }
2333 return getPackageInfo(ai, null, securityViolation, includeCode);
2334 }
2335
2336 public final PackageInfo getPackageInfoNoCheck(ApplicationInfo ai) {
2337 return getPackageInfo(ai, null, false, true);
2338 }
2339
2340 private final PackageInfo getPackageInfo(ApplicationInfo aInfo,
2341 ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
2342 synchronized (mPackages) {
2343 WeakReference<PackageInfo> ref;
2344 if (includeCode) {
2345 ref = mPackages.get(aInfo.packageName);
2346 } else {
2347 ref = mResourcePackages.get(aInfo.packageName);
2348 }
2349 PackageInfo packageInfo = ref != null ? ref.get() : null;
2350 if (packageInfo == null || (packageInfo.mResources != null
2351 && !packageInfo.mResources.getAssets().isUpToDate())) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002352 if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353 : "Loading resource-only package ") + aInfo.packageName
2354 + " (in " + (mBoundApplication != null
2355 ? mBoundApplication.processName : null)
2356 + ")");
2357 packageInfo =
2358 new PackageInfo(this, aInfo, this, baseLoader,
2359 securityViolation, includeCode &&
2360 (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
2361 if (includeCode) {
2362 mPackages.put(aInfo.packageName,
2363 new WeakReference<PackageInfo>(packageInfo));
2364 } else {
2365 mResourcePackages.put(aInfo.packageName,
2366 new WeakReference<PackageInfo>(packageInfo));
2367 }
2368 }
2369 return packageInfo;
2370 }
2371 }
2372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 ActivityThread() {
2374 }
2375
2376 public ApplicationThread getApplicationThread()
2377 {
2378 return mAppThread;
2379 }
2380
2381 public Instrumentation getInstrumentation()
2382 {
2383 return mInstrumentation;
2384 }
2385
2386 public Configuration getConfiguration() {
2387 return mConfiguration;
2388 }
2389
2390 public boolean isProfiling() {
2391 return mBoundApplication != null && mBoundApplication.profileFile != null;
2392 }
2393
2394 public String getProfileFilePath() {
2395 return mBoundApplication.profileFile;
2396 }
2397
2398 public Looper getLooper() {
2399 return mLooper;
2400 }
2401
2402 public Application getApplication() {
2403 return mInitialApplication;
2404 }
Bob Leee5408332009-09-04 18:31:17 -07002405
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -07002406 public String getProcessName() {
2407 return mBoundApplication.processName;
2408 }
Bob Leee5408332009-09-04 18:31:17 -07002409
Dianne Hackborn21556372010-02-04 16:34:40 -08002410 public ContextImpl getSystemContext() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002411 synchronized (this) {
2412 if (mSystemContext == null) {
Dianne Hackborn21556372010-02-04 16:34:40 -08002413 ContextImpl context =
2414 ContextImpl.createSystemContext(this);
Mike Cleron432b7132009-09-24 15:28:29 -07002415 PackageInfo info = new PackageInfo(this, "android", context, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002416 context.init(info, null, this);
2417 context.getResources().updateConfiguration(
2418 getConfiguration(), getDisplayMetricsLocked(false));
2419 mSystemContext = context;
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002420 //Slog.i(TAG, "Created system resources " + context.getResources()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002421 // + ": " + context.getResources().getConfiguration());
2422 }
2423 }
2424 return mSystemContext;
2425 }
2426
Mike Cleron432b7132009-09-24 15:28:29 -07002427 public void installSystemApplicationInfo(ApplicationInfo info) {
2428 synchronized (this) {
Dianne Hackborn21556372010-02-04 16:34:40 -08002429 ContextImpl context = getSystemContext();
Mike Cleron432b7132009-09-24 15:28:29 -07002430 context.init(new PackageInfo(this, "android", context, info), null, this);
2431 }
2432 }
2433
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002434 void ensureJitEnabled() {
2435 if (!mJitEnabled) {
2436 mJitEnabled = true;
2437 dalvik.system.VMRuntime.getRuntime().startJitCompilation();
2438 }
2439 }
2440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002441 void scheduleGcIdler() {
2442 if (!mGcIdlerScheduled) {
2443 mGcIdlerScheduled = true;
2444 Looper.myQueue().addIdleHandler(mGcIdler);
2445 }
2446 mH.removeMessages(H.GC_WHEN_IDLE);
2447 }
2448
2449 void unscheduleGcIdler() {
2450 if (mGcIdlerScheduled) {
2451 mGcIdlerScheduled = false;
2452 Looper.myQueue().removeIdleHandler(mGcIdler);
2453 }
2454 mH.removeMessages(H.GC_WHEN_IDLE);
2455 }
2456
2457 void doGcIfNeeded() {
2458 mGcIdlerScheduled = false;
2459 final long now = SystemClock.uptimeMillis();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002460 //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002461 // + "m now=" + now);
2462 if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002463 //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002464 BinderInternal.forceGc("bg");
2465 }
2466 }
2467
2468 public final ActivityInfo resolveActivityInfo(Intent intent) {
2469 ActivityInfo aInfo = intent.resolveActivityInfo(
2470 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
2471 if (aInfo == null) {
2472 // Throw an exception.
2473 Instrumentation.checkStartActivityResult(
2474 IActivityManager.START_CLASS_NOT_FOUND, intent);
2475 }
2476 return aInfo;
2477 }
Bob Leee5408332009-09-04 18:31:17 -07002478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002479 public final Activity startActivityNow(Activity parent, String id,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002480 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07002481 Activity.NonConfigurationInstances lastNonConfigurationInstances) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 ActivityRecord r = new ActivityRecord();
2483 r.token = token;
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002484 r.ident = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002485 r.intent = intent;
2486 r.state = state;
2487 r.parent = parent;
2488 r.embeddedID = id;
2489 r.activityInfo = activityInfo;
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07002490 r.lastNonConfigurationInstances = lastNonConfigurationInstances;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002491 if (localLOGV) {
2492 ComponentName compname = intent.getComponent();
2493 String name;
2494 if (compname != null) {
2495 name = compname.toShortString();
2496 } else {
2497 name = "(Intent " + intent + ").getComponent() returned null";
2498 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002499 Slog.v(TAG, "Performing launch: action=" + intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 + ", comp=" + name
2501 + ", token=" + token);
2502 }
Christopher Tateb70f3df2009-04-07 16:07:59 -07002503 return performLaunchActivity(r, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002504 }
2505
2506 public final Activity getActivity(IBinder token) {
2507 return mActivities.get(token).activity;
2508 }
2509
2510 public final void sendActivityResult(
2511 IBinder token, String id, int requestCode,
2512 int resultCode, Intent data) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002513 if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id
Chris Tate8a7dc172009-03-24 20:11:42 -07002514 + " req=" + requestCode + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
2516 list.add(new ResultInfo(id, requestCode, resultCode, data));
2517 mAppThread.scheduleSendResult(token, list);
2518 }
2519
2520 // if the thread hasn't started yet, we don't have the handler, so just
2521 // save the messages until we're ready.
2522 private final void queueOrSendMessage(int what, Object obj) {
2523 queueOrSendMessage(what, obj, 0, 0);
2524 }
2525
2526 private final void queueOrSendMessage(int what, Object obj, int arg1) {
2527 queueOrSendMessage(what, obj, arg1, 0);
2528 }
2529
2530 private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
2531 synchronized (this) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002532 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
2534 + ": " + arg1 + " / " + obj);
2535 Message msg = Message.obtain();
2536 msg.what = what;
2537 msg.obj = obj;
2538 msg.arg1 = arg1;
2539 msg.arg2 = arg2;
2540 mH.sendMessage(msg);
2541 }
2542 }
2543
Dianne Hackborn21556372010-02-04 16:34:40 -08002544 final void scheduleContextCleanup(ContextImpl context, String who,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 String what) {
2546 ContextCleanupInfo cci = new ContextCleanupInfo();
2547 cci.context = context;
2548 cci.who = who;
2549 cci.what = what;
2550 queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
2551 }
2552
Christopher Tateb70f3df2009-04-07 16:07:59 -07002553 private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
2555
2556 ActivityInfo aInfo = r.activityInfo;
2557 if (r.packageInfo == null) {
2558 r.packageInfo = getPackageInfo(aInfo.applicationInfo,
2559 Context.CONTEXT_INCLUDE_CODE);
2560 }
Bob Leee5408332009-09-04 18:31:17 -07002561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 ComponentName component = r.intent.getComponent();
2563 if (component == null) {
2564 component = r.intent.resolveActivity(
2565 mInitialApplication.getPackageManager());
2566 r.intent.setComponent(component);
2567 }
2568
2569 if (r.activityInfo.targetActivity != null) {
2570 component = new ComponentName(r.activityInfo.packageName,
2571 r.activityInfo.targetActivity);
2572 }
2573
2574 Activity activity = null;
2575 try {
2576 java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
2577 activity = mInstrumentation.newActivity(
2578 cl, component.getClassName(), r.intent);
2579 r.intent.setExtrasClassLoader(cl);
2580 if (r.state != null) {
2581 r.state.setClassLoader(cl);
2582 }
2583 } catch (Exception e) {
2584 if (!mInstrumentation.onException(activity, e)) {
2585 throw new RuntimeException(
2586 "Unable to instantiate activity " + component
2587 + ": " + e.toString(), e);
2588 }
2589 }
2590
2591 try {
Dianne Hackborn0be1f782009-11-09 12:30:12 -08002592 Application app = r.packageInfo.makeApplication(false, mInstrumentation);
Bob Leee5408332009-09-04 18:31:17 -07002593
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002594 if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
2595 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596 TAG, r + ": app=" + app
2597 + ", appName=" + app.getPackageName()
2598 + ", pkg=" + r.packageInfo.getPackageName()
2599 + ", comp=" + r.intent.getComponent().toShortString()
2600 + ", dir=" + r.packageInfo.getAppDir());
2601
2602 if (activity != null) {
Dianne Hackborn21556372010-02-04 16:34:40 -08002603 ContextImpl appContext = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 appContext.init(r.packageInfo, r.token, this);
2605 appContext.setOuterContext(activity);
2606 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
2607 Configuration config = new Configuration(mConfiguration);
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002608 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07002609 + r.activityInfo.name + " with config " + config);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002610 activity.attach(appContext, this, getInstrumentation(), r.token,
2611 r.ident, app, r.intent, r.activityInfo, title, r.parent,
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07002612 r.embeddedID, r.lastNonConfigurationInstances, config);
Bob Leee5408332009-09-04 18:31:17 -07002613
Christopher Tateb70f3df2009-04-07 16:07:59 -07002614 if (customIntent != null) {
2615 activity.mIntent = customIntent;
2616 }
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07002617 r.lastNonConfigurationInstances = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618 activity.mStartedActivity = false;
2619 int theme = r.activityInfo.getThemeResource();
2620 if (theme != 0) {
2621 activity.setTheme(theme);
2622 }
2623
2624 activity.mCalled = false;
2625 mInstrumentation.callActivityOnCreate(activity, r.state);
2626 if (!activity.mCalled) {
2627 throw new SuperNotCalledException(
2628 "Activity " + r.intent.getComponent().toShortString() +
2629 " did not call through to super.onCreate()");
2630 }
2631 r.activity = activity;
2632 r.stopped = true;
2633 if (!r.activity.mFinished) {
2634 activity.performStart();
2635 r.stopped = false;
2636 }
2637 if (!r.activity.mFinished) {
2638 if (r.state != null) {
2639 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
2640 }
2641 }
2642 if (!r.activity.mFinished) {
2643 activity.mCalled = false;
2644 mInstrumentation.callActivityOnPostCreate(activity, r.state);
2645 if (!activity.mCalled) {
2646 throw new SuperNotCalledException(
2647 "Activity " + r.intent.getComponent().toShortString() +
2648 " did not call through to super.onPostCreate()");
2649 }
2650 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 }
2652 r.paused = true;
2653
2654 mActivities.put(r.token, r);
2655
2656 } catch (SuperNotCalledException e) {
2657 throw e;
2658
2659 } catch (Exception e) {
2660 if (!mInstrumentation.onException(activity, e)) {
2661 throw new RuntimeException(
2662 "Unable to start activity " + component
2663 + ": " + e.toString(), e);
2664 }
2665 }
2666
2667 return activity;
2668 }
2669
Christopher Tateb70f3df2009-04-07 16:07:59 -07002670 private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 // If we are getting ready to gc after going to the background, well
2672 // we are back active so skip it.
2673 unscheduleGcIdler();
2674
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002675 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 TAG, "Handling launch of " + r);
Christopher Tateb70f3df2009-04-07 16:07:59 -07002677 Activity a = performLaunchActivity(r, customIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002678
2679 if (a != null) {
Dianne Hackborn871ecdc2009-12-11 15:24:33 -08002680 r.createdConfig = new Configuration(mConfiguration);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08002681 Bundle oldState = r.state;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002682 handleResumeActivity(r.token, false, r.isForward);
2683
2684 if (!r.activity.mFinished && r.startsNotResumed) {
2685 // The activity manager actually wants this one to start out
2686 // paused, because it needs to be visible but isn't in the
2687 // foreground. We accomplish this by going through the
2688 // normal startup (because activities expect to go through
2689 // onResume() the first time they run, before their window
2690 // is displayed), and then pausing it. However, in this case
2691 // we do -not- need to do the full pause cycle (of freezing
2692 // and such) because the activity manager assumes it can just
2693 // retain the current state it has.
2694 try {
2695 r.activity.mCalled = false;
2696 mInstrumentation.callActivityOnPause(r.activity);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08002697 // We need to keep around the original state, in case
2698 // we need to be created again.
2699 r.state = oldState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002700 if (!r.activity.mCalled) {
2701 throw new SuperNotCalledException(
2702 "Activity " + r.intent.getComponent().toShortString() +
2703 " did not call through to super.onPause()");
2704 }
2705
2706 } catch (SuperNotCalledException e) {
2707 throw e;
2708
2709 } catch (Exception e) {
2710 if (!mInstrumentation.onException(r.activity, e)) {
2711 throw new RuntimeException(
2712 "Unable to pause activity "
2713 + r.intent.getComponent().toShortString()
2714 + ": " + e.toString(), e);
2715 }
2716 }
2717 r.paused = true;
2718 }
2719 } else {
2720 // If there was an error, for any reason, tell the activity
2721 // manager to stop us.
2722 try {
2723 ActivityManagerNative.getDefault()
2724 .finishActivity(r.token, Activity.RESULT_CANCELED, null);
2725 } catch (RemoteException ex) {
2726 }
2727 }
2728 }
2729
2730 private final void deliverNewIntents(ActivityRecord r,
2731 List<Intent> intents) {
2732 final int N = intents.size();
2733 for (int i=0; i<N; i++) {
2734 Intent intent = intents.get(i);
2735 intent.setExtrasClassLoader(r.activity.getClassLoader());
2736 mInstrumentation.callActivityOnNewIntent(r.activity, intent);
2737 }
2738 }
2739
2740 public final void performNewIntents(IBinder token,
2741 List<Intent> intents) {
2742 ActivityRecord r = mActivities.get(token);
2743 if (r != null) {
2744 final boolean resumed = !r.paused;
2745 if (resumed) {
2746 mInstrumentation.callActivityOnPause(r.activity);
2747 }
2748 deliverNewIntents(r, intents);
2749 if (resumed) {
2750 mInstrumentation.callActivityOnResume(r.activity);
2751 }
2752 }
2753 }
Bob Leee5408332009-09-04 18:31:17 -07002754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 private final void handleNewIntent(NewIntentData data) {
2756 performNewIntents(data.token, data.intents);
2757 }
2758
2759 private final void handleReceiver(ReceiverData data) {
2760 // If we are getting ready to gc after going to the background, well
2761 // we are back active so skip it.
2762 unscheduleGcIdler();
2763
2764 String component = data.intent.getComponent().getClassName();
2765
2766 PackageInfo packageInfo = getPackageInfoNoCheck(
2767 data.info.applicationInfo);
2768
2769 IActivityManager mgr = ActivityManagerNative.getDefault();
2770
2771 BroadcastReceiver receiver = null;
2772 try {
2773 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2774 data.intent.setExtrasClassLoader(cl);
2775 if (data.resultExtras != null) {
2776 data.resultExtras.setClassLoader(cl);
2777 }
2778 receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
2779 } catch (Exception e) {
2780 try {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002781 if (DEBUG_BROADCAST) Slog.i(TAG,
2782 "Finishing failed broadcast to " + data.intent.getComponent());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002783 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
2784 data.resultData, data.resultExtras, data.resultAbort);
2785 } catch (RemoteException ex) {
2786 }
2787 throw new RuntimeException(
2788 "Unable to instantiate receiver " + component
2789 + ": " + e.toString(), e);
2790 }
2791
2792 try {
Dianne Hackborn0be1f782009-11-09 12:30:12 -08002793 Application app = packageInfo.makeApplication(false, mInstrumentation);
Bob Leee5408332009-09-04 18:31:17 -07002794
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002795 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002796 TAG, "Performing receive of " + data.intent
2797 + ": app=" + app
2798 + ", appName=" + app.getPackageName()
2799 + ", pkg=" + packageInfo.getPackageName()
2800 + ", comp=" + data.intent.getComponent().toShortString()
2801 + ", dir=" + packageInfo.getAppDir());
2802
Dianne Hackborn21556372010-02-04 16:34:40 -08002803 ContextImpl context = (ContextImpl)app.getBaseContext();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002804 receiver.setOrderedHint(true);
2805 receiver.setResult(data.resultCode, data.resultData,
2806 data.resultExtras);
2807 receiver.setOrderedHint(data.sync);
2808 receiver.onReceive(context.getReceiverRestrictedContext(),
2809 data.intent);
2810 } catch (Exception e) {
2811 try {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002812 if (DEBUG_BROADCAST) Slog.i(TAG,
2813 "Finishing failed broadcast to " + data.intent.getComponent());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002814 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
2815 data.resultData, data.resultExtras, data.resultAbort);
2816 } catch (RemoteException ex) {
2817 }
2818 if (!mInstrumentation.onException(receiver, e)) {
2819 throw new RuntimeException(
2820 "Unable to start receiver " + component
2821 + ": " + e.toString(), e);
2822 }
2823 }
2824
2825 try {
2826 if (data.sync) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002827 if (DEBUG_BROADCAST) Slog.i(TAG,
2828 "Finishing ordered broadcast to " + data.intent.getComponent());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002829 mgr.finishReceiver(
2830 mAppThread.asBinder(), receiver.getResultCode(),
2831 receiver.getResultData(), receiver.getResultExtras(false),
2832 receiver.getAbortBroadcast());
2833 } else {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002834 if (DEBUG_BROADCAST) Slog.i(TAG,
2835 "Finishing broadcast to " + data.intent.getComponent());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002836 mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false);
2837 }
2838 } catch (RemoteException ex) {
2839 }
2840 }
2841
Christopher Tate181fafa2009-05-14 11:12:14 -07002842 // Instantiate a BackupAgent and tell it that it's alive
2843 private final void handleCreateBackupAgent(CreateBackupAgentData data) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002844 if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
Christopher Tate181fafa2009-05-14 11:12:14 -07002845
2846 // no longer idle; we have backup work to do
2847 unscheduleGcIdler();
2848
2849 // instantiate the BackupAgent class named in the manifest
2850 PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
2851 String packageName = packageInfo.mPackageName;
2852 if (mBackupAgents.get(packageName) != null) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002853 Slog.d(TAG, "BackupAgent " + " for " + packageName
Christopher Tate181fafa2009-05-14 11:12:14 -07002854 + " already exists");
2855 return;
2856 }
Bob Leee5408332009-09-04 18:31:17 -07002857
Christopher Tate181fafa2009-05-14 11:12:14 -07002858 BackupAgent agent = null;
2859 String classname = data.appInfo.backupAgentName;
2860 if (classname == null) {
2861 if (data.backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08002862 Slog.e(TAG, "Attempted incremental backup but no defined agent for "
Christopher Tate181fafa2009-05-14 11:12:14 -07002863 + packageName);
2864 return;
2865 }
2866 classname = "android.app.FullBackupAgent";
2867 }
2868 try {
Christopher Tated1475e02009-07-09 15:36:17 -07002869 IBinder binder = null;
2870 try {
2871 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2872 agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance();
2873
2874 // set up the agent's context
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002875 if (DEBUG_BACKUP) Slog.v(TAG, "Initializing BackupAgent "
Christopher Tated1475e02009-07-09 15:36:17 -07002876 + data.appInfo.backupAgentName);
2877
Dianne Hackborn21556372010-02-04 16:34:40 -08002878 ContextImpl context = new ContextImpl();
Christopher Tated1475e02009-07-09 15:36:17 -07002879 context.init(packageInfo, null, this);
2880 context.setOuterContext(agent);
2881 agent.attach(context);
2882
2883 agent.onCreate();
2884 binder = agent.onBind();
2885 mBackupAgents.put(packageName, agent);
2886 } catch (Exception e) {
2887 // If this is during restore, fail silently; otherwise go
2888 // ahead and let the user see the crash.
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08002889 Slog.e(TAG, "Agent threw during creation: " + e);
Christopher Tated1475e02009-07-09 15:36:17 -07002890 if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE) {
2891 throw e;
2892 }
2893 // falling through with 'binder' still null
2894 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002895
2896 // tell the OS that we're live now
Christopher Tate181fafa2009-05-14 11:12:14 -07002897 try {
2898 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
2899 } catch (RemoteException e) {
2900 // nothing to do.
2901 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002902 } catch (Exception e) {
2903 throw new RuntimeException("Unable to create BackupAgent "
2904 + data.appInfo.backupAgentName + ": " + e.toString(), e);
2905 }
2906 }
2907
2908 // Tear down a BackupAgent
2909 private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002910 if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
Bob Leee5408332009-09-04 18:31:17 -07002911
Christopher Tate181fafa2009-05-14 11:12:14 -07002912 PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
2913 String packageName = packageInfo.mPackageName;
2914 BackupAgent agent = mBackupAgents.get(packageName);
2915 if (agent != null) {
2916 try {
2917 agent.onDestroy();
2918 } catch (Exception e) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08002919 Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
Christopher Tate181fafa2009-05-14 11:12:14 -07002920 e.printStackTrace();
2921 }
2922 mBackupAgents.remove(packageName);
2923 } else {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08002924 Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
Christopher Tate181fafa2009-05-14 11:12:14 -07002925 }
2926 }
2927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 private final void handleCreateService(CreateServiceData data) {
2929 // If we are getting ready to gc after going to the background, well
2930 // we are back active so skip it.
2931 unscheduleGcIdler();
2932
2933 PackageInfo packageInfo = getPackageInfoNoCheck(
2934 data.info.applicationInfo);
2935 Service service = null;
2936 try {
2937 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2938 service = (Service) cl.loadClass(data.info.name).newInstance();
2939 } catch (Exception e) {
2940 if (!mInstrumentation.onException(service, e)) {
2941 throw new RuntimeException(
2942 "Unable to instantiate service " + data.info.name
2943 + ": " + e.toString(), e);
2944 }
2945 }
2946
2947 try {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07002948 if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949
Dianne Hackborn21556372010-02-04 16:34:40 -08002950 ContextImpl context = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 context.init(packageInfo, null, this);
2952
Dianne Hackborn0be1f782009-11-09 12:30:12 -08002953 Application app = packageInfo.makeApplication(false, mInstrumentation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 context.setOuterContext(service);
2955 service.attach(context, this, data.info.name, data.token, app,
2956 ActivityManagerNative.getDefault());
2957 service.onCreate();
2958 mServices.put(data.token, service);
2959 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07002960 ActivityManagerNative.getDefault().serviceDoneExecuting(
2961 data.token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002962 } catch (RemoteException e) {
2963 // nothing to do.
2964 }
2965 } catch (Exception e) {
2966 if (!mInstrumentation.onException(service, e)) {
2967 throw new RuntimeException(
2968 "Unable to create service " + data.info.name
2969 + ": " + e.toString(), e);
2970 }
2971 }
2972 }
2973
2974 private final void handleBindService(BindServiceData data) {
2975 Service s = mServices.get(data.token);
2976 if (s != null) {
2977 try {
2978 data.intent.setExtrasClassLoader(s.getClassLoader());
2979 try {
2980 if (!data.rebind) {
2981 IBinder binder = s.onBind(data.intent);
2982 ActivityManagerNative.getDefault().publishService(
2983 data.token, data.intent, binder);
2984 } else {
2985 s.onRebind(data.intent);
2986 ActivityManagerNative.getDefault().serviceDoneExecuting(
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07002987 data.token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002988 }
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002989 ensureJitEnabled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 } catch (RemoteException ex) {
2991 }
2992 } catch (Exception e) {
2993 if (!mInstrumentation.onException(s, e)) {
2994 throw new RuntimeException(
2995 "Unable to bind to service " + s
2996 + " with " + data.intent + ": " + e.toString(), e);
2997 }
2998 }
2999 }
3000 }
3001
3002 private final void handleUnbindService(BindServiceData data) {
3003 Service s = mServices.get(data.token);
3004 if (s != null) {
3005 try {
3006 data.intent.setExtrasClassLoader(s.getClassLoader());
3007 boolean doRebind = s.onUnbind(data.intent);
3008 try {
3009 if (doRebind) {
3010 ActivityManagerNative.getDefault().unbindFinished(
3011 data.token, data.intent, doRebind);
3012 } else {
3013 ActivityManagerNative.getDefault().serviceDoneExecuting(
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07003014 data.token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003015 }
3016 } catch (RemoteException ex) {
3017 }
3018 } catch (Exception e) {
3019 if (!mInstrumentation.onException(s, e)) {
3020 throw new RuntimeException(
3021 "Unable to unbind to service " + s
3022 + " with " + data.intent + ": " + e.toString(), e);
3023 }
3024 }
3025 }
3026 }
3027
3028 private void handleDumpService(DumpServiceInfo info) {
3029 try {
3030 Service s = mServices.get(info.service);
3031 if (s != null) {
3032 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
3033 s.dump(info.fd, pw, info.args);
3034 pw.close();
3035 }
3036 } finally {
3037 synchronized (info) {
3038 info.dumped = true;
3039 info.notifyAll();
3040 }
3041 }
3042 }
3043
3044 private final void handleServiceArgs(ServiceArgsData data) {
3045 Service s = mServices.get(data.token);
3046 if (s != null) {
3047 try {
3048 if (data.args != null) {
3049 data.args.setExtrasClassLoader(s.getClassLoader());
3050 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07003051 int res = s.onStartCommand(data.args, data.flags, data.startId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07003053 ActivityManagerNative.getDefault().serviceDoneExecuting(
3054 data.token, 1, data.startId, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 } catch (RemoteException e) {
3056 // nothing to do.
3057 }
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08003058 ensureJitEnabled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003059 } catch (Exception e) {
3060 if (!mInstrumentation.onException(s, e)) {
3061 throw new RuntimeException(
3062 "Unable to start service " + s
3063 + " with " + data.args + ": " + e.toString(), e);
3064 }
3065 }
3066 }
3067 }
3068
3069 private final void handleStopService(IBinder token) {
3070 Service s = mServices.remove(token);
3071 if (s != null) {
3072 try {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003073 if (localLOGV) Slog.v(TAG, "Destroying service " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003074 s.onDestroy();
3075 Context context = s.getBaseContext();
Dianne Hackborn21556372010-02-04 16:34:40 -08003076 if (context instanceof ContextImpl) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 final String who = s.getClassName();
Dianne Hackborn21556372010-02-04 16:34:40 -08003078 ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003079 }
3080 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07003081 ActivityManagerNative.getDefault().serviceDoneExecuting(
3082 token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 } catch (RemoteException e) {
3084 // nothing to do.
3085 }
3086 } catch (Exception e) {
3087 if (!mInstrumentation.onException(s, e)) {
3088 throw new RuntimeException(
3089 "Unable to stop service " + s
3090 + ": " + e.toString(), e);
3091 }
3092 }
3093 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003094 //Slog.i(TAG, "Running services: " + mServices);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003095 }
3096
3097 public final ActivityRecord performResumeActivity(IBinder token,
3098 boolean clearHide) {
3099 ActivityRecord r = mActivities.get(token);
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003100 if (localLOGV) Slog.v(TAG, "Performing resume of " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 + " finished=" + r.activity.mFinished);
3102 if (r != null && !r.activity.mFinished) {
3103 if (clearHide) {
3104 r.hideForNow = false;
3105 r.activity.mStartedActivity = false;
3106 }
3107 try {
3108 if (r.pendingIntents != null) {
3109 deliverNewIntents(r, r.pendingIntents);
3110 r.pendingIntents = null;
3111 }
3112 if (r.pendingResults != null) {
3113 deliverResults(r, r.pendingResults);
3114 r.pendingResults = null;
3115 }
3116 r.activity.performResume();
3117
Bob Leee5408332009-09-04 18:31:17 -07003118 EventLog.writeEvent(LOG_ON_RESUME_CALLED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003119 r.activity.getComponentName().getClassName());
Bob Leee5408332009-09-04 18:31:17 -07003120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 r.paused = false;
3122 r.stopped = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003123 r.state = null;
3124 } catch (Exception e) {
3125 if (!mInstrumentation.onException(r.activity, e)) {
3126 throw new RuntimeException(
3127 "Unable to resume activity "
3128 + r.intent.getComponent().toShortString()
3129 + ": " + e.toString(), e);
3130 }
3131 }
3132 }
3133 return r;
3134 }
3135
3136 final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
3137 // If we are getting ready to gc after going to the background, well
3138 // we are back active so skip it.
3139 unscheduleGcIdler();
3140
3141 ActivityRecord r = performResumeActivity(token, clearHide);
3142
3143 if (r != null) {
3144 final Activity a = r.activity;
3145
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003146 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003147 TAG, "Resume " + r + " started activity: " +
3148 a.mStartedActivity + ", hideForNow: " + r.hideForNow
3149 + ", finished: " + a.mFinished);
3150
3151 final int forwardBit = isForward ?
3152 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
Bob Leee5408332009-09-04 18:31:17 -07003153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003154 // If the window hasn't yet been added to the window manager,
3155 // and this guy didn't finish itself or start another activity,
3156 // then go ahead and add the window.
Dianne Hackborn061d58a2010-03-12 15:07:06 -08003157 boolean willBeVisible = !a.mStartedActivity;
3158 if (!willBeVisible) {
3159 try {
3160 willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
3161 a.getActivityToken());
3162 } catch (RemoteException e) {
3163 }
3164 }
3165 if (r.window == null && !a.mFinished && willBeVisible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 r.window = r.activity.getWindow();
3167 View decor = r.window.getDecorView();
3168 decor.setVisibility(View.INVISIBLE);
3169 ViewManager wm = a.getWindowManager();
3170 WindowManager.LayoutParams l = r.window.getAttributes();
3171 a.mDecor = decor;
3172 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
3173 l.softInputMode |= forwardBit;
3174 if (a.mVisibleFromClient) {
3175 a.mWindowAdded = true;
3176 wm.addView(decor, l);
3177 }
3178
3179 // If the window has already been added, but during resume
3180 // we started another activity, then don't yet make the
Dianne Hackborn061d58a2010-03-12 15:07:06 -08003181 // window visible.
3182 } else if (!willBeVisible) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003183 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003184 TAG, "Launch " + r + " mStartedActivity set");
3185 r.hideForNow = true;
3186 }
3187
3188 // The window is now visible if it has been added, we are not
3189 // simply finishing, and we are not starting another activity.
Dianne Hackborn061d58a2010-03-12 15:07:06 -08003190 if (!r.activity.mFinished && willBeVisible
Dianne Hackbornc1e605e2009-09-25 17:18:15 -07003191 && r.activity.mDecor != null && !r.hideForNow) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003192 if (r.newConfig != null) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003193 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003194 + r.activityInfo.name + " with newConfig " + r.newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 performConfigurationChanged(r.activity, r.newConfig);
3196 r.newConfig = null;
3197 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003198 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199 + isForward);
3200 WindowManager.LayoutParams l = r.window.getAttributes();
3201 if ((l.softInputMode
3202 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
3203 != forwardBit) {
3204 l.softInputMode = (l.softInputMode
3205 & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
3206 | forwardBit;
Dianne Hackbornc1e605e2009-09-25 17:18:15 -07003207 if (r.activity.mVisibleFromClient) {
3208 ViewManager wm = a.getWindowManager();
3209 View decor = r.window.getDecorView();
3210 wm.updateViewLayout(decor, l);
3211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212 }
3213 r.activity.mVisibleFromServer = true;
3214 mNumVisibleActivities++;
3215 if (r.activity.mVisibleFromClient) {
3216 r.activity.makeVisible();
3217 }
3218 }
3219
3220 r.nextIdle = mNewActivities;
3221 mNewActivities = r;
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003222 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003223 TAG, "Scheduling idle handler for " + r);
3224 Looper.myQueue().addIdleHandler(new Idler());
3225
3226 } else {
3227 // If an exception was thrown when trying to resume, then
3228 // just end this activity.
3229 try {
3230 ActivityManagerNative.getDefault()
3231 .finishActivity(token, Activity.RESULT_CANCELED, null);
3232 } catch (RemoteException ex) {
3233 }
3234 }
3235 }
3236
3237 private int mThumbnailWidth = -1;
3238 private int mThumbnailHeight = -1;
3239
3240 private final Bitmap createThumbnailBitmap(ActivityRecord r) {
3241 Bitmap thumbnail = null;
3242 try {
3243 int w = mThumbnailWidth;
3244 int h;
3245 if (w < 0) {
3246 Resources res = r.activity.getResources();
3247 mThumbnailHeight = h =
3248 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
3249
3250 mThumbnailWidth = w =
3251 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
3252 } else {
3253 h = mThumbnailHeight;
3254 }
3255
3256 // XXX Only set hasAlpha if needed?
3257 thumbnail = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
3258 thumbnail.eraseColor(0);
3259 Canvas cv = new Canvas(thumbnail);
3260 if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
3261 thumbnail = null;
3262 }
3263 } catch (Exception e) {
3264 if (!mInstrumentation.onException(r.activity, e)) {
3265 throw new RuntimeException(
3266 "Unable to create thumbnail of "
3267 + r.intent.getComponent().toShortString()
3268 + ": " + e.toString(), e);
3269 }
3270 thumbnail = null;
3271 }
3272
3273 return thumbnail;
3274 }
3275
3276 private final void handlePauseActivity(IBinder token, boolean finished,
3277 boolean userLeaving, int configChanges) {
3278 ActivityRecord r = mActivities.get(token);
3279 if (r != null) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003280 //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003281 if (userLeaving) {
3282 performUserLeavingActivity(r);
3283 }
Bob Leee5408332009-09-04 18:31:17 -07003284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285 r.activity.mConfigChangeFlags |= configChanges;
3286 Bundle state = performPauseActivity(token, finished, true);
3287
3288 // Tell the activity manager we have paused.
3289 try {
3290 ActivityManagerNative.getDefault().activityPaused(token, state);
3291 } catch (RemoteException ex) {
3292 }
3293 }
3294 }
3295
3296 final void performUserLeavingActivity(ActivityRecord r) {
3297 mInstrumentation.callActivityOnUserLeaving(r.activity);
3298 }
3299
3300 final Bundle performPauseActivity(IBinder token, boolean finished,
3301 boolean saveState) {
3302 ActivityRecord r = mActivities.get(token);
3303 return r != null ? performPauseActivity(r, finished, saveState) : null;
3304 }
3305
3306 final Bundle performPauseActivity(ActivityRecord r, boolean finished,
3307 boolean saveState) {
3308 if (r.paused) {
3309 if (r.activity.mFinished) {
3310 // If we are finishing, we won't call onResume() in certain cases.
3311 // So here we likewise don't want to call onPause() if the activity
3312 // isn't resumed.
3313 return null;
3314 }
3315 RuntimeException e = new RuntimeException(
3316 "Performing pause of activity that is not resumed: "
3317 + r.intent.getComponent().toShortString());
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08003318 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 }
3320 Bundle state = null;
3321 if (finished) {
3322 r.activity.mFinished = true;
3323 }
3324 try {
3325 // Next have the activity save its current state and managed dialogs...
3326 if (!r.activity.mFinished && saveState) {
3327 state = new Bundle();
3328 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
3329 r.state = state;
3330 }
3331 // Now we are idle.
3332 r.activity.mCalled = false;
3333 mInstrumentation.callActivityOnPause(r.activity);
3334 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
3335 if (!r.activity.mCalled) {
3336 throw new SuperNotCalledException(
3337 "Activity " + r.intent.getComponent().toShortString() +
3338 " did not call through to super.onPause()");
3339 }
3340
3341 } catch (SuperNotCalledException e) {
3342 throw e;
3343
3344 } catch (Exception e) {
3345 if (!mInstrumentation.onException(r.activity, e)) {
3346 throw new RuntimeException(
3347 "Unable to pause activity "
3348 + r.intent.getComponent().toShortString()
3349 + ": " + e.toString(), e);
3350 }
3351 }
3352 r.paused = true;
3353 return state;
3354 }
3355
3356 final void performStopActivity(IBinder token) {
3357 ActivityRecord r = mActivities.get(token);
3358 performStopActivityInner(r, null, false);
3359 }
3360
3361 private static class StopInfo {
3362 Bitmap thumbnail;
3363 CharSequence description;
3364 }
3365
3366 private final class ProviderRefCount {
3367 public int count;
3368 ProviderRefCount(int pCount) {
3369 count = pCount;
3370 }
3371 }
3372
3373 private final void performStopActivityInner(ActivityRecord r,
3374 StopInfo info, boolean keepShown) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003375 if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003376 if (r != null) {
3377 if (!keepShown && r.stopped) {
3378 if (r.activity.mFinished) {
3379 // If we are finishing, we won't call onResume() in certain
3380 // cases. So here we likewise don't want to call onStop()
3381 // if the activity isn't resumed.
3382 return;
3383 }
3384 RuntimeException e = new RuntimeException(
3385 "Performing stop of activity that is not resumed: "
3386 + r.intent.getComponent().toShortString());
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08003387 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 }
3389
3390 if (info != null) {
3391 try {
3392 // First create a thumbnail for the activity...
3393 //info.thumbnail = createThumbnailBitmap(r);
3394 info.description = r.activity.onCreateDescription();
3395 } catch (Exception e) {
3396 if (!mInstrumentation.onException(r.activity, e)) {
3397 throw new RuntimeException(
3398 "Unable to save state of activity "
3399 + r.intent.getComponent().toShortString()
3400 + ": " + e.toString(), e);
3401 }
3402 }
3403 }
3404
3405 if (!keepShown) {
3406 try {
3407 // Now we are idle.
3408 r.activity.performStop();
3409 } catch (Exception e) {
3410 if (!mInstrumentation.onException(r.activity, e)) {
3411 throw new RuntimeException(
3412 "Unable to stop activity "
3413 + r.intent.getComponent().toShortString()
3414 + ": " + e.toString(), e);
3415 }
3416 }
3417 r.stopped = true;
3418 }
3419
3420 r.paused = true;
3421 }
3422 }
3423
3424 private final void updateVisibility(ActivityRecord r, boolean show) {
3425 View v = r.activity.mDecor;
3426 if (v != null) {
3427 if (show) {
3428 if (!r.activity.mVisibleFromServer) {
3429 r.activity.mVisibleFromServer = true;
3430 mNumVisibleActivities++;
3431 if (r.activity.mVisibleFromClient) {
3432 r.activity.makeVisible();
3433 }
3434 }
3435 if (r.newConfig != null) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003436 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003437 + r.activityInfo.name + " with new config " + r.newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003438 performConfigurationChanged(r.activity, r.newConfig);
3439 r.newConfig = null;
3440 }
3441 } else {
3442 if (r.activity.mVisibleFromServer) {
3443 r.activity.mVisibleFromServer = false;
3444 mNumVisibleActivities--;
3445 v.setVisibility(View.INVISIBLE);
3446 }
3447 }
3448 }
3449 }
3450
3451 private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
3452 ActivityRecord r = mActivities.get(token);
3453 r.activity.mConfigChangeFlags |= configChanges;
3454
3455 StopInfo info = new StopInfo();
3456 performStopActivityInner(r, info, show);
3457
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003458 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003459 TAG, "Finishing stop of " + r + ": show=" + show
3460 + " win=" + r.window);
3461
3462 updateVisibility(r, show);
Bob Leee5408332009-09-04 18:31:17 -07003463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 // Tell activity manager we have been stopped.
3465 try {
3466 ActivityManagerNative.getDefault().activityStopped(
3467 r.token, info.thumbnail, info.description);
3468 } catch (RemoteException ex) {
3469 }
3470 }
3471
3472 final void performRestartActivity(IBinder token) {
3473 ActivityRecord r = mActivities.get(token);
3474 if (r.stopped) {
3475 r.activity.performRestart();
3476 r.stopped = false;
3477 }
3478 }
3479
3480 private final void handleWindowVisibility(IBinder token, boolean show) {
3481 ActivityRecord r = mActivities.get(token);
3482 if (!show && !r.stopped) {
3483 performStopActivityInner(r, null, show);
3484 } else if (show && r.stopped) {
3485 // If we are getting ready to gc after going to the background, well
3486 // we are back active so skip it.
3487 unscheduleGcIdler();
3488
3489 r.activity.performRestart();
3490 r.stopped = false;
3491 }
3492 if (r.activity.mDecor != null) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003493 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494 TAG, "Handle window " + r + " visibility: " + show);
3495 updateVisibility(r, show);
3496 }
3497 }
3498
3499 private final void deliverResults(ActivityRecord r, List<ResultInfo> results) {
3500 final int N = results.size();
3501 for (int i=0; i<N; i++) {
3502 ResultInfo ri = results.get(i);
3503 try {
3504 if (ri.mData != null) {
3505 ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
3506 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003507 if (DEBUG_RESULTS) Slog.v(TAG,
Chris Tate8a7dc172009-03-24 20:11:42 -07003508 "Delivering result to activity " + r + " : " + ri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003509 r.activity.dispatchActivityResult(ri.mResultWho,
3510 ri.mRequestCode, ri.mResultCode, ri.mData);
3511 } catch (Exception e) {
3512 if (!mInstrumentation.onException(r.activity, e)) {
3513 throw new RuntimeException(
3514 "Failure delivering result " + ri + " to activity "
3515 + r.intent.getComponent().toShortString()
3516 + ": " + e.toString(), e);
3517 }
3518 }
3519 }
3520 }
3521
3522 private final void handleSendResult(ResultData res) {
3523 ActivityRecord r = mActivities.get(res.token);
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003524 if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003525 if (r != null) {
3526 final boolean resumed = !r.paused;
3527 if (!r.activity.mFinished && r.activity.mDecor != null
3528 && r.hideForNow && resumed) {
3529 // We had hidden the activity because it started another
3530 // one... we have gotten a result back and we are not
3531 // paused, so make sure our window is visible.
3532 updateVisibility(r, true);
3533 }
3534 if (resumed) {
3535 try {
3536 // Now we are idle.
3537 r.activity.mCalled = false;
3538 mInstrumentation.callActivityOnPause(r.activity);
3539 if (!r.activity.mCalled) {
3540 throw new SuperNotCalledException(
3541 "Activity " + r.intent.getComponent().toShortString()
3542 + " did not call through to super.onPause()");
3543 }
3544 } catch (SuperNotCalledException e) {
3545 throw e;
3546 } catch (Exception e) {
3547 if (!mInstrumentation.onException(r.activity, e)) {
3548 throw new RuntimeException(
3549 "Unable to pause activity "
3550 + r.intent.getComponent().toShortString()
3551 + ": " + e.toString(), e);
3552 }
3553 }
3554 }
3555 deliverResults(r, res.results);
3556 if (resumed) {
3557 mInstrumentation.callActivityOnResume(r.activity);
3558 }
3559 }
3560 }
3561
3562 public final ActivityRecord performDestroyActivity(IBinder token, boolean finishing) {
3563 return performDestroyActivity(token, finishing, 0, false);
3564 }
3565
3566 private final ActivityRecord performDestroyActivity(IBinder token, boolean finishing,
3567 int configChanges, boolean getNonConfigInstance) {
3568 ActivityRecord r = mActivities.get(token);
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003569 if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 if (r != null) {
3571 r.activity.mConfigChangeFlags |= configChanges;
3572 if (finishing) {
3573 r.activity.mFinished = true;
3574 }
Jeff Hamilton3d32f6e2010-04-01 00:04:16 -05003575 if (getNonConfigInstance) {
3576 r.activity.mChangingConfigurations = true;
3577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 if (!r.paused) {
3579 try {
3580 r.activity.mCalled = false;
3581 mInstrumentation.callActivityOnPause(r.activity);
Bob Leee5408332009-09-04 18:31:17 -07003582 EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 r.activity.getComponentName().getClassName());
3584 if (!r.activity.mCalled) {
3585 throw new SuperNotCalledException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003586 "Activity " + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003587 + " did not call through to super.onPause()");
3588 }
3589 } catch (SuperNotCalledException e) {
3590 throw e;
3591 } catch (Exception e) {
3592 if (!mInstrumentation.onException(r.activity, e)) {
3593 throw new RuntimeException(
3594 "Unable to pause activity "
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003595 + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003596 + ": " + e.toString(), e);
3597 }
3598 }
3599 r.paused = true;
3600 }
3601 if (!r.stopped) {
3602 try {
3603 r.activity.performStop();
3604 } catch (SuperNotCalledException e) {
3605 throw e;
3606 } catch (Exception e) {
3607 if (!mInstrumentation.onException(r.activity, e)) {
3608 throw new RuntimeException(
3609 "Unable to stop activity "
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003610 + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 + ": " + e.toString(), e);
3612 }
3613 }
3614 r.stopped = true;
3615 }
3616 if (getNonConfigInstance) {
3617 try {
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07003618 r.lastNonConfigurationInstances
3619 = r.activity.retainNonConfigurationInstances();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 } catch (Exception e) {
3621 if (!mInstrumentation.onException(r.activity, e)) {
3622 throw new RuntimeException(
3623 "Unable to retain activity "
3624 + r.intent.getComponent().toShortString()
3625 + ": " + e.toString(), e);
3626 }
3627 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 }
3629 try {
3630 r.activity.mCalled = false;
Dianne Hackborn2dedce62010-04-15 14:45:25 -07003631 mInstrumentation.callActivityOnDestroy(r.activity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003632 if (!r.activity.mCalled) {
3633 throw new SuperNotCalledException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003634 "Activity " + safeToComponentShortString(r.intent) +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003635 " did not call through to super.onDestroy()");
3636 }
3637 if (r.window != null) {
3638 r.window.closeAllPanels();
3639 }
3640 } catch (SuperNotCalledException e) {
3641 throw e;
3642 } catch (Exception e) {
3643 if (!mInstrumentation.onException(r.activity, e)) {
3644 throw new RuntimeException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003645 "Unable to destroy activity " + safeToComponentShortString(r.intent)
3646 + ": " + e.toString(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 }
3648 }
3649 }
3650 mActivities.remove(token);
3651
3652 return r;
3653 }
3654
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003655 private static String safeToComponentShortString(Intent intent) {
3656 ComponentName component = intent.getComponent();
3657 return component == null ? "[Unknown]" : component.toShortString();
3658 }
3659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 private final void handleDestroyActivity(IBinder token, boolean finishing,
3661 int configChanges, boolean getNonConfigInstance) {
3662 ActivityRecord r = performDestroyActivity(token, finishing,
3663 configChanges, getNonConfigInstance);
3664 if (r != null) {
3665 WindowManager wm = r.activity.getWindowManager();
3666 View v = r.activity.mDecor;
3667 if (v != null) {
3668 if (r.activity.mVisibleFromServer) {
3669 mNumVisibleActivities--;
3670 }
3671 IBinder wtoken = v.getWindowToken();
3672 if (r.activity.mWindowAdded) {
3673 wm.removeViewImmediate(v);
3674 }
3675 if (wtoken != null) {
3676 WindowManagerImpl.getDefault().closeAll(wtoken,
3677 r.activity.getClass().getName(), "Activity");
3678 }
3679 r.activity.mDecor = null;
3680 }
3681 WindowManagerImpl.getDefault().closeAll(token,
3682 r.activity.getClass().getName(), "Activity");
3683
3684 // Mocked out contexts won't be participating in the normal
3685 // process lifecycle, but if we're running with a proper
3686 // ApplicationContext we need to have it tear down things
3687 // cleanly.
3688 Context c = r.activity.getBaseContext();
Dianne Hackborn21556372010-02-04 16:34:40 -08003689 if (c instanceof ContextImpl) {
3690 ((ContextImpl) c).scheduleFinalCleanup(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 r.activity.getClass().getName(), "Activity");
3692 }
3693 }
3694 if (finishing) {
3695 try {
3696 ActivityManagerNative.getDefault().activityDestroyed(token);
3697 } catch (RemoteException ex) {
3698 // If the system process has died, it's game over for everyone.
3699 }
3700 }
3701 }
3702
3703 private final void handleRelaunchActivity(ActivityRecord tmp, int configChanges) {
3704 // If we are getting ready to gc after going to the background, well
3705 // we are back active so skip it.
3706 unscheduleGcIdler();
3707
3708 Configuration changedConfig = null;
Bob Leee5408332009-09-04 18:31:17 -07003709
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003710 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003711 + tmp.token + " with configChanges=0x"
3712 + Integer.toHexString(configChanges));
3713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714 // First: make sure we have the most recent configuration and most
3715 // recent version of the activity, or skip it if some previous call
3716 // had taken a more recent version.
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003717 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 int N = mRelaunchingActivities.size();
3719 IBinder token = tmp.token;
3720 tmp = null;
3721 for (int i=0; i<N; i++) {
3722 ActivityRecord r = mRelaunchingActivities.get(i);
3723 if (r.token == token) {
3724 tmp = r;
3725 mRelaunchingActivities.remove(i);
3726 i--;
3727 N--;
3728 }
3729 }
Bob Leee5408332009-09-04 18:31:17 -07003730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003731 if (tmp == null) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003732 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003733 return;
3734 }
Bob Leee5408332009-09-04 18:31:17 -07003735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003736 if (mPendingConfiguration != null) {
3737 changedConfig = mPendingConfiguration;
3738 mPendingConfiguration = null;
3739 }
3740 }
Bob Leee5408332009-09-04 18:31:17 -07003741
Dianne Hackborn871ecdc2009-12-11 15:24:33 -08003742 if (tmp.createdConfig != null) {
3743 // If the activity manager is passing us its current config,
3744 // assume that is really what we want regardless of what we
3745 // may have pending.
3746 if (mConfiguration == null
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003747 || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
3748 && mConfiguration.diff(tmp.createdConfig) != 0)) {
3749 if (changedConfig == null
3750 || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
3751 changedConfig = tmp.createdConfig;
3752 }
Dianne Hackborn871ecdc2009-12-11 15:24:33 -08003753 }
3754 }
3755
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003756 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003757 + tmp.token + ": changedConfig=" + changedConfig);
3758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003759 // If there was a pending configuration change, execute it first.
3760 if (changedConfig != null) {
3761 handleConfigurationChanged(changedConfig);
3762 }
Bob Leee5408332009-09-04 18:31:17 -07003763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 ActivityRecord r = mActivities.get(tmp.token);
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003765 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003766 if (r == null) {
3767 return;
3768 }
Bob Leee5408332009-09-04 18:31:17 -07003769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003770 r.activity.mConfigChangeFlags |= configChanges;
Christopher Tateb70f3df2009-04-07 16:07:59 -07003771 Intent currentIntent = r.activity.mIntent;
Bob Leee5408332009-09-04 18:31:17 -07003772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 Bundle savedState = null;
3774 if (!r.paused) {
3775 savedState = performPauseActivity(r.token, false, true);
3776 }
Bob Leee5408332009-09-04 18:31:17 -07003777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 handleDestroyActivity(r.token, false, configChanges, true);
Bob Leee5408332009-09-04 18:31:17 -07003779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003780 r.activity = null;
3781 r.window = null;
3782 r.hideForNow = false;
3783 r.nextIdle = null;
The Android Open Source Project10592532009-03-18 17:39:46 -07003784 // Merge any pending results and pending intents; don't just replace them
3785 if (tmp.pendingResults != null) {
3786 if (r.pendingResults == null) {
3787 r.pendingResults = tmp.pendingResults;
3788 } else {
3789 r.pendingResults.addAll(tmp.pendingResults);
3790 }
3791 }
3792 if (tmp.pendingIntents != null) {
3793 if (r.pendingIntents == null) {
3794 r.pendingIntents = tmp.pendingIntents;
3795 } else {
3796 r.pendingIntents.addAll(tmp.pendingIntents);
3797 }
3798 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 r.startsNotResumed = tmp.startsNotResumed;
3800 if (savedState != null) {
3801 r.state = savedState;
3802 }
Bob Leee5408332009-09-04 18:31:17 -07003803
Christopher Tateb70f3df2009-04-07 16:07:59 -07003804 handleLaunchActivity(r, currentIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 }
3806
3807 private final void handleRequestThumbnail(IBinder token) {
3808 ActivityRecord r = mActivities.get(token);
3809 Bitmap thumbnail = createThumbnailBitmap(r);
3810 CharSequence description = null;
3811 try {
3812 description = r.activity.onCreateDescription();
3813 } catch (Exception e) {
3814 if (!mInstrumentation.onException(r.activity, e)) {
3815 throw new RuntimeException(
3816 "Unable to create description of activity "
3817 + r.intent.getComponent().toShortString()
3818 + ": " + e.toString(), e);
3819 }
3820 }
3821 //System.out.println("Reporting top thumbnail " + thumbnail);
3822 try {
3823 ActivityManagerNative.getDefault().reportThumbnail(
3824 token, thumbnail, description);
3825 } catch (RemoteException ex) {
3826 }
3827 }
3828
3829 ArrayList<ComponentCallbacks> collectComponentCallbacksLocked(
3830 boolean allActivities, Configuration newConfig) {
3831 ArrayList<ComponentCallbacks> callbacks
3832 = new ArrayList<ComponentCallbacks>();
Bob Leee5408332009-09-04 18:31:17 -07003833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003834 if (mActivities.size() > 0) {
3835 Iterator<ActivityRecord> it = mActivities.values().iterator();
3836 while (it.hasNext()) {
3837 ActivityRecord ar = it.next();
3838 Activity a = ar.activity;
3839 if (a != null) {
3840 if (!ar.activity.mFinished && (allActivities ||
3841 (a != null && !ar.paused))) {
3842 // If the activity is currently resumed, its configuration
3843 // needs to change right now.
3844 callbacks.add(a);
3845 } else if (newConfig != null) {
3846 // Otherwise, we will tell it about the change
3847 // the next time it is resumed or shown. Note that
3848 // the activity manager may, before then, decide the
3849 // activity needs to be destroyed to handle its new
3850 // configuration.
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003851 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Setting activity "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003852 + ar.activityInfo.name + " newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003853 ar.newConfig = newConfig;
3854 }
3855 }
3856 }
3857 }
3858 if (mServices.size() > 0) {
3859 Iterator<Service> it = mServices.values().iterator();
3860 while (it.hasNext()) {
3861 callbacks.add(it.next());
3862 }
3863 }
3864 synchronized (mProviderMap) {
3865 if (mLocalProviders.size() > 0) {
3866 Iterator<ProviderRecord> it = mLocalProviders.values().iterator();
3867 while (it.hasNext()) {
3868 callbacks.add(it.next().mLocalProvider);
3869 }
3870 }
3871 }
3872 final int N = mAllApplications.size();
3873 for (int i=0; i<N; i++) {
3874 callbacks.add(mAllApplications.get(i));
3875 }
Bob Leee5408332009-09-04 18:31:17 -07003876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 return callbacks;
3878 }
Bob Leee5408332009-09-04 18:31:17 -07003879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003880 private final void performConfigurationChanged(
3881 ComponentCallbacks cb, Configuration config) {
3882 // Only for Activity objects, check that they actually call up to their
3883 // superclass implementation. ComponentCallbacks is an interface, so
3884 // we check the runtime type and act accordingly.
3885 Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
3886 if (activity != null) {
3887 activity.mCalled = false;
3888 }
Bob Leee5408332009-09-04 18:31:17 -07003889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 boolean shouldChangeConfig = false;
3891 if ((activity == null) || (activity.mCurrentConfig == null)) {
3892 shouldChangeConfig = true;
3893 } else {
Bob Leee5408332009-09-04 18:31:17 -07003894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003895 // If the new config is the same as the config this Activity
3896 // is already running with then don't bother calling
3897 // onConfigurationChanged
3898 int diff = activity.mCurrentConfig.diff(config);
3899 if (diff != 0) {
Bob Leee5408332009-09-04 18:31:17 -07003900
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003901 // If this activity doesn't handle any of the config changes
3902 // then don't bother calling onConfigurationChanged as we're
3903 // going to destroy it.
3904 if ((~activity.mActivityInfo.configChanges & diff) == 0) {
3905 shouldChangeConfig = true;
3906 }
3907 }
3908 }
Bob Leee5408332009-09-04 18:31:17 -07003909
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003910 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003911 + ": shouldChangeConfig=" + shouldChangeConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003912 if (shouldChangeConfig) {
3913 cb.onConfigurationChanged(config);
Bob Leee5408332009-09-04 18:31:17 -07003914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003915 if (activity != null) {
3916 if (!activity.mCalled) {
3917 throw new SuperNotCalledException(
3918 "Activity " + activity.getLocalClassName() +
3919 " did not call through to super.onConfigurationChanged()");
3920 }
3921 activity.mConfigChangeFlags = 0;
3922 activity.mCurrentConfig = new Configuration(config);
3923 }
3924 }
3925 }
3926
Dianne Hackbornae078162010-03-18 11:29:37 -07003927 final boolean applyConfigurationToResourcesLocked(Configuration config) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003928 if (mResConfiguration == null) {
3929 mResConfiguration = new Configuration();
3930 }
3931 if (!mResConfiguration.isOtherSeqNewer(config)) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003932 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003933 + mResConfiguration.seq + ", newSeq=" + config.seq);
Dianne Hackbornae078162010-03-18 11:29:37 -07003934 return false;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003935 }
Dianne Hackbornae078162010-03-18 11:29:37 -07003936 int changes = mResConfiguration.updateFrom(config);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003937 DisplayMetrics dm = getDisplayMetricsLocked(true);
Bob Leee5408332009-09-04 18:31:17 -07003938
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003939 // set it for java, this also affects newly created Resources
3940 if (config.locale != null) {
3941 Locale.setDefault(config.locale);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 }
Bob Leee5408332009-09-04 18:31:17 -07003943
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003944 Resources.updateSystemConfiguration(config, dm);
Bob Leee5408332009-09-04 18:31:17 -07003945
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003946 ContextImpl.ApplicationPackageManager.configurationChanged();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003947 //Slog.i(TAG, "Configuration changed in " + currentPackageName());
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003948
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003949 Iterator<WeakReference<Resources>> it =
3950 mActiveResources.values().iterator();
3951 //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
3952 // mActiveResources.entrySet().iterator();
3953 while (it.hasNext()) {
3954 WeakReference<Resources> v = it.next();
3955 Resources r = v.get();
3956 if (r != null) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003957 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
Dianne Hackborn694f79b2010-03-17 19:44:59 -07003958 + r + " config to: " + config);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003959 r.updateConfiguration(config, dm);
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003960 //Slog.i(TAG, "Updated app resources " + v.getKey()
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003961 // + " " + r + ": " + r.getConfiguration());
3962 } else {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003963 //Slog.i(TAG, "Removing old resources " + v.getKey());
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003964 it.remove();
3965 }
3966 }
Dianne Hackbornae078162010-03-18 11:29:37 -07003967
3968 return changes != 0;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003969 }
3970
3971 final void handleConfigurationChanged(Configuration config) {
3972
3973 ArrayList<ComponentCallbacks> callbacks = null;
3974
3975 synchronized (mPackages) {
3976 if (mPendingConfiguration != null) {
3977 if (!mPendingConfiguration.isOtherSeqNewer(config)) {
3978 config = mPendingConfiguration;
3979 }
3980 mPendingConfiguration = null;
3981 }
3982
3983 if (config == null) {
3984 return;
3985 }
3986
Dianne Hackborn399cccb2010-04-13 22:57:49 -07003987 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003988 + config);
3989
3990 applyConfigurationToResourcesLocked(config);
3991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003992 if (mConfiguration == null) {
3993 mConfiguration = new Configuration();
3994 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003995 if (!mConfiguration.isOtherSeqNewer(config)) {
3996 return;
3997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003998 mConfiguration.updateFrom(config);
Bob Leee5408332009-09-04 18:31:17 -07003999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 callbacks = collectComponentCallbacksLocked(false, config);
4001 }
Bob Leee5408332009-09-04 18:31:17 -07004002
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004003 if (callbacks != null) {
4004 final int N = callbacks.size();
4005 for (int i=0; i<N; i++) {
4006 performConfigurationChanged(callbacks.get(i), config);
4007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004008 }
4009 }
4010
4011 final void handleActivityConfigurationChanged(IBinder token) {
4012 ActivityRecord r = mActivities.get(token);
4013 if (r == null || r.activity == null) {
4014 return;
4015 }
Bob Leee5408332009-09-04 18:31:17 -07004016
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004017 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07004018 + r.activityInfo.name);
4019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004020 performConfigurationChanged(r.activity, mConfiguration);
4021 }
4022
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07004023 final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08004024 if (start) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08004025 try {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07004026 Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
4027 8 * 1024 * 1024, 0);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08004028 } catch (RuntimeException e) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08004029 Slog.w(TAG, "Profiling failed on path " + pcd.path
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08004030 + " -- can the process access this path?");
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07004031 } finally {
4032 try {
4033 pcd.fd.close();
4034 } catch (IOException e) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08004035 Slog.w(TAG, "Failure closing profile fd", e);
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07004036 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08004037 }
4038 } else {
4039 Debug.stopMethodTracing();
4040 }
4041 }
Bob Leee5408332009-09-04 18:31:17 -07004042
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07004043 final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
4044 boolean hasPkgInfo = false;
4045 if (packages != null) {
4046 for (int i=packages.length-1; i>=0; i--) {
4047 //Slog.i(TAG, "Cleaning old package: " + packages[i]);
4048 if (!hasPkgInfo) {
4049 WeakReference<PackageInfo> ref;
4050 ref = mPackages.get(packages[i]);
4051 if (ref != null && ref.get() != null) {
4052 hasPkgInfo = true;
4053 } else {
4054 ref = mResourcePackages.get(packages[i]);
4055 if (ref != null && ref.get() != null) {
4056 hasPkgInfo = true;
4057 }
4058 }
4059 }
4060 mPackages.remove(packages[i]);
4061 mResourcePackages.remove(packages[i]);
4062 }
4063 }
4064 ContextImpl.ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
4065 hasPkgInfo);
4066 }
4067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004068 final void handleLowMemory() {
4069 ArrayList<ComponentCallbacks> callbacks
4070 = new ArrayList<ComponentCallbacks>();
4071
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004072 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004073 callbacks = collectComponentCallbacksLocked(true, null);
4074 }
Bob Leee5408332009-09-04 18:31:17 -07004075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004076 final int N = callbacks.size();
4077 for (int i=0; i<N; i++) {
4078 callbacks.get(i).onLowMemory();
4079 }
4080
Chris Tatece229052009-03-25 16:44:52 -07004081 // Ask SQLite to free up as much memory as it can, mostly from its page caches.
4082 if (Process.myUid() != Process.SYSTEM_UID) {
4083 int sqliteReleased = SQLiteDatabase.releaseMemory();
4084 EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
4085 }
Bob Leee5408332009-09-04 18:31:17 -07004086
Mike Reedcaf0df12009-04-27 14:32:05 -04004087 // Ask graphics to free up as much as possible (font/image caches)
4088 Canvas.freeCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004089
4090 BinderInternal.forceGc("mem");
4091 }
4092
4093 private final void handleBindApplication(AppBindData data) {
4094 mBoundApplication = data;
4095 mConfiguration = new Configuration(data.config);
4096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 // send up app name; do this *before* waiting for debugger
Christopher Tate8ee038d2009-11-06 11:30:20 -08004098 Process.setArgV0(data.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 android.ddm.DdmHandleAppName.setAppName(data.processName);
4100
4101 /*
4102 * Before spawning a new process, reset the time zone to be the system time zone.
4103 * This needs to be done because the system time zone could have changed after the
4104 * the spawning of this process. Without doing this this process would have the incorrect
4105 * system time zone.
4106 */
4107 TimeZone.setDefault(null);
4108
4109 /*
4110 * Initialize the default locale in this process for the reasons we set the time zone.
4111 */
4112 Locale.setDefault(data.config.locale);
4113
Suchi Amalapurapuc9843292009-06-24 17:02:25 -07004114 /*
4115 * Update the system configuration since its preloaded and might not
4116 * reflect configuration changes. The configuration object passed
4117 * in AppBindData can be safely assumed to be up to date
4118 */
4119 Resources.getSystem().updateConfiguration(mConfiguration, null);
4120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 data.info = getPackageInfoNoCheck(data.appInfo);
4122
Dianne Hackborn96e240f2009-07-26 17:42:30 -07004123 /**
4124 * Switch this process to density compatibility mode if needed.
4125 */
4126 if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
4127 == 0) {
4128 Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
4129 }
Bob Leee5408332009-09-04 18:31:17 -07004130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004131 if (data.debugMode != IApplicationThread.DEBUG_OFF) {
4132 // XXX should have option to change the port.
4133 Debug.changeDebugPort(8100);
4134 if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004135 Slog.w(TAG, "Application " + data.info.getPackageName()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004136 + " is waiting for the debugger on port 8100...");
4137
4138 IActivityManager mgr = ActivityManagerNative.getDefault();
4139 try {
4140 mgr.showWaitingForDebugger(mAppThread, true);
4141 } catch (RemoteException ex) {
4142 }
4143
4144 Debug.waitForDebugger();
4145
4146 try {
4147 mgr.showWaitingForDebugger(mAppThread, false);
4148 } catch (RemoteException ex) {
4149 }
4150
4151 } else {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004152 Slog.w(TAG, "Application " + data.info.getPackageName()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004153 + " can be debugged on port 8100...");
4154 }
4155 }
4156
4157 if (data.instrumentationName != null) {
Dianne Hackborn21556372010-02-04 16:34:40 -08004158 ContextImpl appContext = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004159 appContext.init(data.info, null, this);
4160 InstrumentationInfo ii = null;
4161 try {
4162 ii = appContext.getPackageManager().
4163 getInstrumentationInfo(data.instrumentationName, 0);
4164 } catch (PackageManager.NameNotFoundException e) {
4165 }
4166 if (ii == null) {
4167 throw new RuntimeException(
4168 "Unable to find instrumentation info for: "
4169 + data.instrumentationName);
4170 }
4171
4172 mInstrumentationAppDir = ii.sourceDir;
4173 mInstrumentationAppPackage = ii.packageName;
4174 mInstrumentedAppDir = data.info.getAppDir();
4175
4176 ApplicationInfo instrApp = new ApplicationInfo();
4177 instrApp.packageName = ii.packageName;
4178 instrApp.sourceDir = ii.sourceDir;
4179 instrApp.publicSourceDir = ii.publicSourceDir;
4180 instrApp.dataDir = ii.dataDir;
4181 PackageInfo pi = getPackageInfo(instrApp,
4182 appContext.getClassLoader(), false, true);
Dianne Hackborn21556372010-02-04 16:34:40 -08004183 ContextImpl instrContext = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004184 instrContext.init(pi, null, this);
4185
4186 try {
4187 java.lang.ClassLoader cl = instrContext.getClassLoader();
4188 mInstrumentation = (Instrumentation)
4189 cl.loadClass(data.instrumentationName.getClassName()).newInstance();
4190 } catch (Exception e) {
4191 throw new RuntimeException(
4192 "Unable to instantiate instrumentation "
4193 + data.instrumentationName + ": " + e.toString(), e);
4194 }
4195
4196 mInstrumentation.init(this, instrContext, appContext,
4197 new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
4198
4199 if (data.profileFile != null && !ii.handleProfiling) {
4200 data.handlingProfiling = true;
4201 File file = new File(data.profileFile);
4202 file.getParentFile().mkdirs();
4203 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
4204 }
4205
4206 try {
4207 mInstrumentation.onCreate(data.instrumentationArgs);
4208 }
4209 catch (Exception e) {
4210 throw new RuntimeException(
4211 "Exception thrown in onCreate() of "
4212 + data.instrumentationName + ": " + e.toString(), e);
4213 }
4214
4215 } else {
4216 mInstrumentation = new Instrumentation();
4217 }
4218
Christopher Tate181fafa2009-05-14 11:12:14 -07004219 // If the app is being launched for full backup or restore, bring it up in
4220 // a restricted environment with the base application class.
Dianne Hackborn0be1f782009-11-09 12:30:12 -08004221 Application app = data.info.makeApplication(data.restrictedBackupMode, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004222 mInitialApplication = app;
4223
4224 List<ProviderInfo> providers = data.providers;
4225 if (providers != null) {
4226 installContentProviders(app, providers);
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08004227 // For process that contain content providers, we want to
4228 // ensure that the JIT is enabled "at some point".
4229 mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 }
4231
4232 try {
4233 mInstrumentation.callApplicationOnCreate(app);
4234 } catch (Exception e) {
4235 if (!mInstrumentation.onException(app, e)) {
4236 throw new RuntimeException(
4237 "Unable to create application " + app.getClass().getName()
4238 + ": " + e.toString(), e);
4239 }
4240 }
4241 }
4242
4243 /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
4244 IActivityManager am = ActivityManagerNative.getDefault();
4245 if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) {
4246 Debug.stopMethodTracing();
4247 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004248 //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 // + ", app thr: " + mAppThread);
4250 try {
4251 am.finishInstrumentation(mAppThread, resultCode, results);
4252 } catch (RemoteException ex) {
4253 }
4254 }
4255
4256 private final void installContentProviders(
4257 Context context, List<ProviderInfo> providers) {
4258 final ArrayList<IActivityManager.ContentProviderHolder> results =
4259 new ArrayList<IActivityManager.ContentProviderHolder>();
4260
4261 Iterator<ProviderInfo> i = providers.iterator();
4262 while (i.hasNext()) {
4263 ProviderInfo cpi = i.next();
4264 StringBuilder buf = new StringBuilder(128);
4265 buf.append("Publishing provider ");
4266 buf.append(cpi.authority);
4267 buf.append(": ");
4268 buf.append(cpi.name);
4269 Log.i(TAG, buf.toString());
4270 IContentProvider cp = installProvider(context, null, cpi, false);
4271 if (cp != null) {
4272 IActivityManager.ContentProviderHolder cph =
4273 new IActivityManager.ContentProviderHolder(cpi);
4274 cph.provider = cp;
4275 results.add(cph);
4276 // Don't ever unload this provider from the process.
4277 synchronized(mProviderMap) {
4278 mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
4279 }
4280 }
4281 }
4282
4283 try {
4284 ActivityManagerNative.getDefault().publishContentProviders(
4285 getApplicationThread(), results);
4286 } catch (RemoteException ex) {
4287 }
4288 }
4289
4290 private final IContentProvider getProvider(Context context, String name) {
4291 synchronized(mProviderMap) {
4292 final ProviderRecord pr = mProviderMap.get(name);
4293 if (pr != null) {
4294 return pr.mProvider;
4295 }
4296 }
4297
4298 IActivityManager.ContentProviderHolder holder = null;
4299 try {
4300 holder = ActivityManagerNative.getDefault().getContentProvider(
4301 getApplicationThread(), name);
4302 } catch (RemoteException ex) {
4303 }
4304 if (holder == null) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08004305 Slog.e(TAG, "Failed to find provider info for " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004306 return null;
4307 }
4308 if (holder.permissionFailure != null) {
4309 throw new SecurityException("Permission " + holder.permissionFailure
4310 + " required for provider " + name);
4311 }
4312
4313 IContentProvider prov = installProvider(context, holder.provider,
4314 holder.info, true);
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004315 //Slog.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004316 if (holder.noReleaseNeeded || holder.provider == null) {
4317 // We are not going to release the provider if it is an external
4318 // provider that doesn't care about being released, or if it is
4319 // a local provider running in this process.
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004320 //Slog.i(TAG, "*** NO RELEASE NEEDED");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004321 synchronized(mProviderMap) {
4322 mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
4323 }
4324 }
4325 return prov;
4326 }
4327
4328 public final IContentProvider acquireProvider(Context c, String name) {
4329 IContentProvider provider = getProvider(c, name);
4330 if(provider == null)
4331 return null;
4332 IBinder jBinder = provider.asBinder();
4333 synchronized(mProviderMap) {
4334 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4335 if(prc == null) {
4336 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
4337 } else {
4338 prc.count++;
4339 } //end else
4340 } //end synchronized
4341 return provider;
4342 }
4343
4344 public final boolean releaseProvider(IContentProvider provider) {
4345 if(provider == null) {
4346 return false;
4347 }
4348 IBinder jBinder = provider.asBinder();
4349 synchronized(mProviderMap) {
4350 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4351 if(prc == null) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004352 if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldnt be here");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004353 return false;
4354 } else {
4355 prc.count--;
4356 if(prc.count == 0) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004357 // Schedule the actual remove asynchronously, since we
4358 // don't know the context this will be called in.
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004359 // TODO: it would be nice to post a delayed message, so
4360 // if we come back and need the same provider quickly
4361 // we will still have it available.
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004362 Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
4363 mH.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004364 } //end if
4365 } //end else
4366 } //end synchronized
4367 return true;
4368 }
4369
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004370 final void completeRemoveProvider(IContentProvider provider) {
4371 IBinder jBinder = provider.asBinder();
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004372 String name = null;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004373 synchronized(mProviderMap) {
4374 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4375 if(prc != null && prc.count == 0) {
4376 mProviderRefCountMap.remove(jBinder);
4377 //invoke removeProvider to dereference provider
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004378 name = removeProviderLocked(provider);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004379 }
4380 }
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004381
4382 if (name != null) {
4383 try {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004384 if(localLOGV) Slog.v(TAG, "removeProvider::Invoking " +
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004385 "ActivityManagerNative.removeContentProvider(" + name);
4386 ActivityManagerNative.getDefault().removeContentProvider(
4387 getApplicationThread(), name);
4388 } catch (RemoteException e) {
4389 //do nothing content provider object is dead any way
4390 } //end catch
4391 }
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004392 }
4393
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004394 public final String removeProviderLocked(IContentProvider provider) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004395 if (provider == null) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004396 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 }
4398 IBinder providerBinder = provider.asBinder();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004399
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004400 String name = null;
4401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004402 // remove the provider from mProviderMap
4403 Iterator<ProviderRecord> iter = mProviderMap.values().iterator();
4404 while (iter.hasNext()) {
4405 ProviderRecord pr = iter.next();
4406 IBinder myBinder = pr.mProvider.asBinder();
4407 if (myBinder == providerBinder) {
4408 //find if its published by this process itself
4409 if(pr.mLocalProvider != null) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004410 if(localLOGV) Slog.i(TAG, "removeProvider::found local provider returning");
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004411 return name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004413 if(localLOGV) Slog.v(TAG, "removeProvider::Not local provider Unlinking " +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004414 "death recipient");
4415 //content provider is in another process
4416 myBinder.unlinkToDeath(pr, 0);
4417 iter.remove();
4418 //invoke remove only once for the very first name seen
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004419 if(name == null) {
4420 name = pr.mName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004421 }
4422 } //end if myBinder
4423 } //end while iter
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004424
4425 return name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004426 }
4427
4428 final void removeDeadProvider(String name, IContentProvider provider) {
4429 synchronized(mProviderMap) {
4430 ProviderRecord pr = mProviderMap.get(name);
4431 if (pr.mProvider.asBinder() == provider.asBinder()) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004432 Slog.i(TAG, "Removing dead content provider: " + name);
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004433 ProviderRecord removed = mProviderMap.remove(name);
4434 if (removed != null) {
4435 removed.mProvider.asBinder().unlinkToDeath(removed, 0);
4436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004437 }
4438 }
4439 }
4440
4441 final void removeDeadProviderLocked(String name, IContentProvider provider) {
4442 ProviderRecord pr = mProviderMap.get(name);
4443 if (pr.mProvider.asBinder() == provider.asBinder()) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004444 Slog.i(TAG, "Removing dead content provider: " + name);
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004445 ProviderRecord removed = mProviderMap.remove(name);
4446 if (removed != null) {
4447 removed.mProvider.asBinder().unlinkToDeath(removed, 0);
4448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004449 }
4450 }
4451
4452 private final IContentProvider installProvider(Context context,
4453 IContentProvider provider, ProviderInfo info, boolean noisy) {
4454 ContentProvider localProvider = null;
4455 if (provider == null) {
4456 if (noisy) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004457 Slog.d(TAG, "Loading provider " + info.authority + ": "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 + info.name);
4459 }
4460 Context c = null;
4461 ApplicationInfo ai = info.applicationInfo;
4462 if (context.getPackageName().equals(ai.packageName)) {
4463 c = context;
4464 } else if (mInitialApplication != null &&
4465 mInitialApplication.getPackageName().equals(ai.packageName)) {
4466 c = mInitialApplication;
4467 } else {
4468 try {
4469 c = context.createPackageContext(ai.packageName,
4470 Context.CONTEXT_INCLUDE_CODE);
4471 } catch (PackageManager.NameNotFoundException e) {
4472 }
4473 }
4474 if (c == null) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08004475 Slog.w(TAG, "Unable to get context for package " +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 ai.packageName +
4477 " while loading content provider " +
4478 info.name);
4479 return null;
4480 }
4481 try {
4482 final java.lang.ClassLoader cl = c.getClassLoader();
4483 localProvider = (ContentProvider)cl.
4484 loadClass(info.name).newInstance();
4485 provider = localProvider.getIContentProvider();
4486 if (provider == null) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08004487 Slog.e(TAG, "Failed to instantiate class " +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 info.name + " from sourceDir " +
4489 info.applicationInfo.sourceDir);
4490 return null;
4491 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004492 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 TAG, "Instantiating local provider " + info.name);
4494 // XXX Need to create the correct context for this provider.
4495 localProvider.attachInfo(c, info);
4496 } catch (java.lang.Exception e) {
4497 if (!mInstrumentation.onException(null, e)) {
4498 throw new RuntimeException(
4499 "Unable to get provider " + info.name
4500 + ": " + e.toString(), e);
4501 }
4502 return null;
4503 }
4504 } else if (localLOGV) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004505 Slog.v(TAG, "Installing external provider " + info.authority + ": "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 + info.name);
4507 }
4508
4509 synchronized (mProviderMap) {
4510 // Cache the pointer for the remote provider.
4511 String names[] = PATTERN_SEMICOLON.split(info.authority);
4512 for (int i=0; i<names.length; i++) {
4513 ProviderRecord pr = new ProviderRecord(names[i], provider,
4514 localProvider);
4515 try {
4516 provider.asBinder().linkToDeath(pr, 0);
4517 mProviderMap.put(names[i], pr);
4518 } catch (RemoteException e) {
4519 return null;
4520 }
4521 }
4522 if (localProvider != null) {
4523 mLocalProviders.put(provider.asBinder(),
4524 new ProviderRecord(null, provider, localProvider));
4525 }
4526 }
4527
4528 return provider;
4529 }
4530
4531 private final void attach(boolean system) {
4532 sThreadLocal.set(this);
4533 mSystemThread = system;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 if (!system) {
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08004535 ViewRoot.addFirstDrawHandler(new Runnable() {
4536 public void run() {
4537 ensureJitEnabled();
4538 }
4539 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004540 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
4541 RuntimeInit.setApplicationObject(mAppThread.asBinder());
4542 IActivityManager mgr = ActivityManagerNative.getDefault();
4543 try {
4544 mgr.attachApplication(mAppThread);
4545 } catch (RemoteException ex) {
4546 }
4547 } else {
4548 // Don't set application object here -- if the system crashes,
4549 // we can't display an alert, we just want to die die die.
4550 android.ddm.DdmHandleAppName.setAppName("system_process");
4551 try {
4552 mInstrumentation = new Instrumentation();
Dianne Hackborn21556372010-02-04 16:34:40 -08004553 ContextImpl context = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 context.init(getSystemContext().mPackageInfo, null, this);
4555 Application app = Instrumentation.newApplication(Application.class, context);
4556 mAllApplications.add(app);
4557 mInitialApplication = app;
4558 app.onCreate();
4559 } catch (Exception e) {
4560 throw new RuntimeException(
4561 "Unable to instantiate Application():" + e.toString(), e);
4562 }
4563 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004564
4565 ViewRoot.addConfigCallback(new ComponentCallbacks() {
4566 public void onConfigurationChanged(Configuration newConfig) {
4567 synchronized (mPackages) {
Dianne Hackbornae078162010-03-18 11:29:37 -07004568 // We need to apply this change to the resources
4569 // immediately, because upon returning the view
4570 // hierarchy will be informed about it.
4571 if (applyConfigurationToResourcesLocked(newConfig)) {
4572 // This actually changed the resources! Tell
4573 // everyone about it.
4574 if (mPendingConfiguration == null ||
4575 mPendingConfiguration.isOtherSeqNewer(newConfig)) {
4576 mPendingConfiguration = newConfig;
4577
4578 queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
4579 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004580 }
4581 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004582 }
4583 public void onLowMemory() {
4584 }
4585 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 }
4587
4588 private final void detach()
4589 {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004590 sThreadLocal.set(null);
4591 }
4592
4593 public static final ActivityThread systemMain() {
4594 ActivityThread thread = new ActivityThread();
4595 thread.attach(true);
4596 return thread;
4597 }
4598
4599 public final void installSystemProviders(List providers) {
4600 if (providers != null) {
4601 installContentProviders(mInitialApplication,
4602 (List<ProviderInfo>)providers);
4603 }
4604 }
4605
4606 public static final void main(String[] args) {
Bob Leee5408332009-09-04 18:31:17 -07004607 SamplingProfilerIntegration.start();
4608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004609 Process.setArgV0("<pre-initialized>");
4610
4611 Looper.prepareMainLooper();
4612
4613 ActivityThread thread = new ActivityThread();
4614 thread.attach(false);
4615
4616 Looper.loop();
4617
4618 if (Process.supportsProcesses()) {
4619 throw new RuntimeException("Main thread loop unexpectedly exited");
4620 }
4621
4622 thread.detach();
Bob Leeeec2f412009-09-10 11:01:24 +02004623 String name = (thread.mInitialApplication != null)
4624 ? thread.mInitialApplication.getPackageName()
4625 : "<unknown>";
Dianne Hackborn399cccb2010-04-13 22:57:49 -07004626 Slog.i(TAG, "Main thread of " + name + " is now exiting");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 }
4628}