blob: 7b5b63e1d21a267b2e3ad53cf85f6b3e6059bc0e [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) {
153 //Log.v("PackageManager", "returning cur default = " + sPackageManager);
154 return sPackageManager;
155 }
156 IBinder b = ServiceManager.getService("package");
157 //Log.v("PackageManager", "default service binder = " + b);
158 sPackageManager = IPackageManager.Stub.asInterface(b);
159 //Log.v("PackageManager", "default service = " + sPackageManager);
160 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);
173 //Log.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
174 // + 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) {
192 Log.w(TAG, "getTopLevelResources: " + resDir + " / "
193 + 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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 if (r != null && r.getAssets().isUpToDate()) {
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700198 if (false) {
199 Log.w(TAG, "Returning cached resources " + r + " " + resDir
200 + ": appScale=" + r.getCompatibilityInfo().applicationScale);
201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 return r;
203 }
Dianne Hackbornf9315202009-11-17 18:28:55 -0800204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205
Dianne Hackbornf9315202009-11-17 18:28:55 -0800206 //if (r != null) {
207 // Log.w(TAG, "Throwing away out-of-date resources!!!! "
208 // + r + " " + resDir);
209 //}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210
Dianne Hackbornf9315202009-11-17 18:28:55 -0800211 AssetManager assets = new AssetManager();
212 if (assets.addAssetPath(resDir) == 0) {
213 return null;
214 }
215
216 //Log.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
217 DisplayMetrics metrics = getDisplayMetricsLocked(false);
218 r = new Resources(assets, metrics, getConfiguration(), compInfo);
219 if (false) {
220 Log.i(TAG, "Created app resources " + resDir + " " + r + ": "
221 + r.getConfiguration() + " appScale="
222 + r.getCompatibilityInfo().applicationScale);
223 }
224
225 synchronized (mPackages) {
226 WeakReference<Resources> wr = mActiveResources.get(key);
227 Resources existing = wr != null ? wr.get() : null;
228 if (existing != null && existing.getAssets().isUpToDate()) {
229 // Someone else already created the resources while we were
230 // unlocked; go ahead and use theirs.
231 r.getAssets().close();
232 return existing;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 }
Dianne Hackbornf9315202009-11-17 18:28:55 -0800234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 // XXX need to remove entries when weak references go away
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700236 mActiveResources.put(key, new WeakReference<Resources>(r));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 return r;
238 }
239 }
240
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700241 /**
242 * Creates the top level resources for the given package.
243 */
244 Resources getTopLevelResources(String resDir, PackageInfo pkgInfo) {
245 return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo);
246 }
247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 final Handler getHandler() {
249 return mH;
250 }
251
252 public final static class PackageInfo {
253
254 private final ActivityThread mActivityThread;
255 private final ApplicationInfo mApplicationInfo;
256 private final String mPackageName;
257 private final String mAppDir;
258 private final String mResDir;
259 private final String[] mSharedLibraries;
260 private final String mDataDir;
261 private final File mDataDirFile;
262 private final ClassLoader mBaseClassLoader;
263 private final boolean mSecurityViolation;
264 private final boolean mIncludeCode;
265 private Resources mResources;
266 private ClassLoader mClassLoader;
267 private Application mApplication;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700268 private CompatibilityInfo mCompatibilityInfo;
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
271 = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
272 private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mUnregisteredReceivers
273 = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
274 private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mServices
275 = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
276 private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mUnboundServices
277 = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
278
279 int mClientCount = 0;
280
281 public PackageInfo(ActivityThread activityThread, ApplicationInfo aInfo,
282 ActivityThread mainThread, ClassLoader baseLoader,
283 boolean securityViolation, boolean includeCode) {
284 mActivityThread = activityThread;
285 mApplicationInfo = aInfo;
286 mPackageName = aInfo.packageName;
287 mAppDir = aInfo.sourceDir;
288 mResDir = aInfo.uid == Process.myUid() ? aInfo.sourceDir
289 : aInfo.publicSourceDir;
290 mSharedLibraries = aInfo.sharedLibraryFiles;
291 mDataDir = aInfo.dataDir;
292 mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
293 mBaseClassLoader = baseLoader;
294 mSecurityViolation = securityViolation;
295 mIncludeCode = includeCode;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700296 mCompatibilityInfo = new CompatibilityInfo(aInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297
298 if (mAppDir == null) {
299 if (mSystemContext == null) {
300 mSystemContext =
Dianne Hackborn21556372010-02-04 16:34:40 -0800301 ContextImpl.createSystemContext(mainThread);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 mSystemContext.getResources().updateConfiguration(
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700303 mainThread.getConfiguration(),
304 mainThread.getDisplayMetricsLocked(false));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 //Log.i(TAG, "Created system resources "
306 // + mSystemContext.getResources() + ": "
307 // + mSystemContext.getResources().getConfiguration());
308 }
309 mClassLoader = mSystemContext.getClassLoader();
310 mResources = mSystemContext.getResources();
311 }
312 }
313
314 public PackageInfo(ActivityThread activityThread, String name,
Mike Cleron432b7132009-09-24 15:28:29 -0700315 Context systemContext, ApplicationInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 mActivityThread = activityThread;
Mike Cleron432b7132009-09-24 15:28:29 -0700317 mApplicationInfo = info != null ? info : new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 mApplicationInfo.packageName = name;
319 mPackageName = name;
320 mAppDir = null;
321 mResDir = null;
322 mSharedLibraries = null;
323 mDataDir = null;
324 mDataDirFile = null;
325 mBaseClassLoader = null;
326 mSecurityViolation = false;
327 mIncludeCode = true;
328 mClassLoader = systemContext.getClassLoader();
329 mResources = systemContext.getResources();
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700330 mCompatibilityInfo = new CompatibilityInfo(mApplicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 }
332
333 public String getPackageName() {
334 return mPackageName;
335 }
336
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700337 public ApplicationInfo getApplicationInfo() {
338 return mApplicationInfo;
339 }
Bob Leee5408332009-09-04 18:31:17 -0700340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 public boolean isSecurityViolation() {
342 return mSecurityViolation;
343 }
344
345 /**
346 * Gets the array of shared libraries that are listed as
347 * used by the given package.
Bob Leee5408332009-09-04 18:31:17 -0700348 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 * @param packageName the name of the package (note: not its
350 * file name)
351 * @return null-ok; the array of shared libraries, each one
352 * a fully-qualified path
353 */
354 private static String[] getLibrariesFor(String packageName) {
355 ApplicationInfo ai = null;
356 try {
357 ai = getPackageManager().getApplicationInfo(packageName,
358 PackageManager.GET_SHARED_LIBRARY_FILES);
359 } catch (RemoteException e) {
360 throw new AssertionError(e);
361 }
362
363 if (ai == null) {
364 return null;
365 }
366
367 return ai.sharedLibraryFiles;
368 }
369
370 /**
371 * Combines two arrays (of library names) such that they are
372 * concatenated in order but are devoid of duplicates. The
373 * result is a single string with the names of the libraries
374 * separated by colons, or <code>null</code> if both lists
375 * were <code>null</code> or empty.
Bob Leee5408332009-09-04 18:31:17 -0700376 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 * @param list1 null-ok; the first list
378 * @param list2 null-ok; the second list
379 * @return null-ok; the combination
380 */
381 private static String combineLibs(String[] list1, String[] list2) {
382 StringBuilder result = new StringBuilder(300);
383 boolean first = true;
384
385 if (list1 != null) {
386 for (String s : list1) {
387 if (first) {
388 first = false;
389 } else {
390 result.append(':');
391 }
392 result.append(s);
393 }
394 }
395
396 // Only need to check for duplicates if list1 was non-empty.
397 boolean dupCheck = !first;
398
399 if (list2 != null) {
400 for (String s : list2) {
401 if (dupCheck && ArrayUtils.contains(list1, s)) {
402 continue;
403 }
Bob Leee5408332009-09-04 18:31:17 -0700404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 if (first) {
406 first = false;
407 } else {
408 result.append(':');
409 }
410 result.append(s);
411 }
412 }
413
414 return result.toString();
415 }
Bob Leee5408332009-09-04 18:31:17 -0700416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 public ClassLoader getClassLoader() {
418 synchronized (this) {
419 if (mClassLoader != null) {
420 return mClassLoader;
421 }
422
423 if (mIncludeCode && !mPackageName.equals("android")) {
424 String zip = mAppDir;
425
426 /*
427 * The following is a bit of a hack to inject
428 * instrumentation into the system: If the app
429 * being started matches one of the instrumentation names,
430 * then we combine both the "instrumentation" and
431 * "instrumented" app into the path, along with the
432 * concatenation of both apps' shared library lists.
433 */
434
435 String instrumentationAppDir =
436 mActivityThread.mInstrumentationAppDir;
437 String instrumentationAppPackage =
438 mActivityThread.mInstrumentationAppPackage;
439 String instrumentedAppDir =
440 mActivityThread.mInstrumentedAppDir;
441 String[] instrumentationLibs = null;
442
443 if (mAppDir.equals(instrumentationAppDir)
444 || mAppDir.equals(instrumentedAppDir)) {
445 zip = instrumentationAppDir + ":" + instrumentedAppDir;
446 if (! instrumentedAppDir.equals(instrumentationAppDir)) {
447 instrumentationLibs =
448 getLibrariesFor(instrumentationAppPackage);
449 }
450 }
451
452 if ((mSharedLibraries != null) ||
453 (instrumentationLibs != null)) {
Bob Leee5408332009-09-04 18:31:17 -0700454 zip =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 combineLibs(mSharedLibraries, instrumentationLibs)
456 + ':' + zip;
457 }
458
459 /*
460 * With all the combination done (if necessary, actually
461 * create the class loader.
462 */
463
464 if (localLOGV) Log.v(TAG, "Class path: " + zip);
465
466 mClassLoader =
467 ApplicationLoaders.getDefault().getClassLoader(
468 zip, mDataDir, mBaseClassLoader);
Brian Carlstrom778ce482010-02-09 11:23:40 -0800469 initializeJavaContextClassLoader();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 } else {
471 if (mBaseClassLoader == null) {
472 mClassLoader = ClassLoader.getSystemClassLoader();
473 } else {
474 mClassLoader = mBaseClassLoader;
475 }
476 }
477 return mClassLoader;
478 }
479 }
480
Brian Carlstrom778ce482010-02-09 11:23:40 -0800481 /**
482 * Setup value for Thread.getContextClassLoader(). If the
483 * package will not run in in a VM with other packages, we set
484 * the Java context ClassLoader to the
485 * PackageInfo.getClassLoader value. However, if this VM can
486 * contain multiple packages, we intead set the Java context
487 * ClassLoader to a proxy that will warn about the use of Java
488 * context ClassLoaders and then fall through to use the
489 * system ClassLoader.
490 *
491 * <p> Note that this is similar to but not the same as the
492 * android.content.Context.getClassLoader(). While both
493 * context class loaders are typically set to the
494 * PathClassLoader used to load the package archive in the
495 * single application per VM case, a single Android process
496 * may contain several Contexts executing on one thread with
497 * their own logical ClassLoaders while the Java context
498 * ClassLoader is a thread local. This is why in the case when
499 * we have multiple packages per VM we do not set the Java
500 * context ClassLoader to an arbitrary but instead warn the
501 * user to set their own if we detect that they are using a
502 * Java library that expects it to be set.
503 */
504 private void initializeJavaContextClassLoader() {
505 IPackageManager pm = getPackageManager();
506 android.content.pm.PackageInfo pi;
507 try {
508 pi = pm.getPackageInfo(mPackageName, 0);
509 } catch (RemoteException e) {
510 throw new AssertionError(e);
511 }
512 /*
513 * Two possible indications that this package could be
514 * sharing its virtual machine with other packages:
515 *
516 * 1.) the sharedUserId attribute is set in the manifest,
517 * indicating a request to share a VM with other
518 * packages with the same sharedUserId.
519 *
520 * 2.) the application element of the manifest has an
521 * attribute specifying a non-default process name,
522 * indicating the desire to run in another packages VM.
523 */
524 boolean sharedUserIdSet = (pi.sharedUserId != null);
525 boolean processNameNotDefault =
526 (pi.applicationInfo != null &&
527 !mPackageName.equals(pi.applicationInfo.processName));
528 boolean sharable = (sharedUserIdSet || processNameNotDefault);
529 ClassLoader contextClassLoader =
530 (sharable)
531 ? new WarningContextClassLoader()
532 : mClassLoader;
533 Thread.currentThread().setContextClassLoader(contextClassLoader);
534 }
535
536 private static class WarningContextClassLoader extends ClassLoader {
537
538 private static boolean warned = false;
539
540 private void warn(String methodName) {
541 if (warned) {
542 return;
543 }
544 warned = true;
545 Thread.currentThread().setContextClassLoader(getParent());
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800546 Slog.w(TAG, "ClassLoader." + methodName + ": " +
Brian Carlstrom778ce482010-02-09 11:23:40 -0800547 "The class loader returned by " +
548 "Thread.getContextClassLoader() may fail for processes " +
549 "that host multiple applications. You should explicitly " +
550 "specify a context class loader. For example: " +
551 "Thread.setContextClassLoader(getClass().getClassLoader());");
552 }
553
554 @Override public URL getResource(String resName) {
555 warn("getResource");
556 return getParent().getResource(resName);
557 }
558
559 @Override public Enumeration<URL> getResources(String resName) throws IOException {
560 warn("getResources");
561 return getParent().getResources(resName);
562 }
563
564 @Override public InputStream getResourceAsStream(String resName) {
565 warn("getResourceAsStream");
566 return getParent().getResourceAsStream(resName);
567 }
568
569 @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
570 warn("loadClass");
571 return getParent().loadClass(className);
572 }
573
574 @Override public void setClassAssertionStatus(String cname, boolean enable) {
575 warn("setClassAssertionStatus");
576 getParent().setClassAssertionStatus(cname, enable);
577 }
578
579 @Override public void setPackageAssertionStatus(String pname, boolean enable) {
580 warn("setPackageAssertionStatus");
581 getParent().setPackageAssertionStatus(pname, enable);
582 }
583
584 @Override public void setDefaultAssertionStatus(boolean enable) {
585 warn("setDefaultAssertionStatus");
586 getParent().setDefaultAssertionStatus(enable);
587 }
588
589 @Override public void clearAssertionStatus() {
590 warn("clearAssertionStatus");
591 getParent().clearAssertionStatus();
592 }
593 }
594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 public String getAppDir() {
596 return mAppDir;
597 }
598
599 public String getResDir() {
600 return mResDir;
601 }
602
603 public String getDataDir() {
604 return mDataDir;
605 }
606
607 public File getDataDirFile() {
608 return mDataDirFile;
609 }
610
611 public AssetManager getAssets(ActivityThread mainThread) {
612 return getResources(mainThread).getAssets();
613 }
614
615 public Resources getResources(ActivityThread mainThread) {
616 if (mResources == null) {
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700617 mResources = mainThread.getTopLevelResources(mResDir, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 }
619 return mResources;
620 }
621
Dianne Hackborn0be1f782009-11-09 12:30:12 -0800622 public Application makeApplication(boolean forceDefaultAppClass,
623 Instrumentation instrumentation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 if (mApplication != null) {
625 return mApplication;
626 }
Bob Leee5408332009-09-04 18:31:17 -0700627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 Application app = null;
Bob Leee5408332009-09-04 18:31:17 -0700629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 String appClass = mApplicationInfo.className;
Christopher Tate181fafa2009-05-14 11:12:14 -0700631 if (forceDefaultAppClass || (appClass == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 appClass = "android.app.Application";
633 }
634
635 try {
636 java.lang.ClassLoader cl = getClassLoader();
Dianne Hackborn21556372010-02-04 16:34:40 -0800637 ContextImpl appContext = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 appContext.init(this, null, mActivityThread);
639 app = mActivityThread.mInstrumentation.newApplication(
640 cl, appClass, appContext);
641 appContext.setOuterContext(app);
642 } catch (Exception e) {
643 if (!mActivityThread.mInstrumentation.onException(app, e)) {
644 throw new RuntimeException(
645 "Unable to instantiate application " + appClass
646 + ": " + e.toString(), e);
647 }
648 }
649 mActivityThread.mAllApplications.add(app);
Dianne Hackborn0be1f782009-11-09 12:30:12 -0800650 mApplication = app;
651
652 if (instrumentation != null) {
653 try {
654 instrumentation.callApplicationOnCreate(app);
655 } catch (Exception e) {
656 if (!instrumentation.onException(app, e)) {
657 throw new RuntimeException(
658 "Unable to create application " + app.getClass().getName()
659 + ": " + e.toString(), e);
660 }
661 }
662 }
663
664 return app;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 }
Bob Leee5408332009-09-04 18:31:17 -0700666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 public void removeContextRegistrations(Context context,
668 String who, String what) {
669 HashMap<BroadcastReceiver, ReceiverDispatcher> rmap =
670 mReceivers.remove(context);
671 if (rmap != null) {
672 Iterator<ReceiverDispatcher> it = rmap.values().iterator();
673 while (it.hasNext()) {
674 ReceiverDispatcher rd = it.next();
675 IntentReceiverLeaked leak = new IntentReceiverLeaked(
676 what + " " + who + " has leaked IntentReceiver "
677 + rd.getIntentReceiver() + " that was " +
678 "originally registered here. Are you missing a " +
679 "call to unregisterReceiver()?");
680 leak.setStackTrace(rd.getLocation().getStackTrace());
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800681 Slog.e(TAG, leak.getMessage(), leak);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 try {
683 ActivityManagerNative.getDefault().unregisterReceiver(
684 rd.getIIntentReceiver());
685 } catch (RemoteException e) {
686 // system crashed, nothing we can do
687 }
688 }
689 }
690 mUnregisteredReceivers.remove(context);
691 //Log.i(TAG, "Receiver registrations: " + mReceivers);
692 HashMap<ServiceConnection, ServiceDispatcher> smap =
693 mServices.remove(context);
694 if (smap != null) {
695 Iterator<ServiceDispatcher> it = smap.values().iterator();
696 while (it.hasNext()) {
697 ServiceDispatcher sd = it.next();
698 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
699 what + " " + who + " has leaked ServiceConnection "
700 + sd.getServiceConnection() + " that was originally bound here");
701 leak.setStackTrace(sd.getLocation().getStackTrace());
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800702 Slog.e(TAG, leak.getMessage(), leak);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 try {
704 ActivityManagerNative.getDefault().unbindService(
705 sd.getIServiceConnection());
706 } catch (RemoteException e) {
707 // system crashed, nothing we can do
708 }
709 sd.doForget();
710 }
711 }
712 mUnboundServices.remove(context);
713 //Log.i(TAG, "Service registrations: " + mServices);
714 }
715
716 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
717 Context context, Handler handler,
718 Instrumentation instrumentation, boolean registered) {
719 synchronized (mReceivers) {
720 ReceiverDispatcher rd = null;
721 HashMap<BroadcastReceiver, ReceiverDispatcher> map = null;
722 if (registered) {
723 map = mReceivers.get(context);
724 if (map != null) {
725 rd = map.get(r);
726 }
727 }
728 if (rd == null) {
729 rd = new ReceiverDispatcher(r, context, handler,
730 instrumentation, registered);
731 if (registered) {
732 if (map == null) {
733 map = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
734 mReceivers.put(context, map);
735 }
736 map.put(r, rd);
737 }
738 } else {
739 rd.validate(context, handler);
740 }
741 return rd.getIIntentReceiver();
742 }
743 }
744
745 public IIntentReceiver forgetReceiverDispatcher(Context context,
746 BroadcastReceiver r) {
747 synchronized (mReceivers) {
748 HashMap<BroadcastReceiver, ReceiverDispatcher> map = mReceivers.get(context);
749 ReceiverDispatcher rd = null;
750 if (map != null) {
751 rd = map.get(r);
752 if (rd != null) {
753 map.remove(r);
754 if (map.size() == 0) {
755 mReceivers.remove(context);
756 }
757 if (r.getDebugUnregister()) {
758 HashMap<BroadcastReceiver, ReceiverDispatcher> holder
759 = mUnregisteredReceivers.get(context);
760 if (holder == null) {
761 holder = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
762 mUnregisteredReceivers.put(context, holder);
763 }
764 RuntimeException ex = new IllegalArgumentException(
765 "Originally unregistered here:");
766 ex.fillInStackTrace();
767 rd.setUnregisterLocation(ex);
768 holder.put(r, rd);
769 }
770 return rd.getIIntentReceiver();
771 }
772 }
773 HashMap<BroadcastReceiver, ReceiverDispatcher> holder
774 = mUnregisteredReceivers.get(context);
775 if (holder != null) {
776 rd = holder.get(r);
777 if (rd != null) {
778 RuntimeException ex = rd.getUnregisterLocation();
779 throw new IllegalArgumentException(
780 "Unregistering Receiver " + r
781 + " that was already unregistered", ex);
782 }
783 }
784 if (context == null) {
785 throw new IllegalStateException("Unbinding Receiver " + r
786 + " from Context that is no longer in use: " + context);
787 } else {
788 throw new IllegalArgumentException("Receiver not registered: " + r);
789 }
790
791 }
792 }
793
794 static final class ReceiverDispatcher {
795
796 final static class InnerReceiver extends IIntentReceiver.Stub {
797 final WeakReference<ReceiverDispatcher> mDispatcher;
798 final ReceiverDispatcher mStrongRef;
Bob Leee5408332009-09-04 18:31:17 -0700799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800 InnerReceiver(ReceiverDispatcher rd, boolean strong) {
801 mDispatcher = new WeakReference<ReceiverDispatcher>(rd);
802 mStrongRef = strong ? rd : null;
803 }
804 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700805 String data, Bundle extras, boolean ordered, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 ReceiverDispatcher rd = mDispatcher.get();
807 if (DEBUG_BROADCAST) {
808 int seq = intent.getIntExtra("seq", -1);
809 Log.i(TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
810 + " to " + rd);
811 }
812 if (rd != null) {
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700813 rd.performReceive(intent, resultCode, data, extras,
814 ordered, sticky);
Christopher Tate08a46252009-12-08 13:48:45 -0800815 } else {
816 // The activity manager dispatched a broadcast to a registered
817 // receiver in this process, but before it could be delivered the
818 // receiver was unregistered. Acknowledge the broadcast on its
819 // behalf so that the system's broadcast sequence can continue.
820 if (DEBUG_BROADCAST) {
821 Log.i(TAG, "Broadcast to unregistered receiver");
822 }
823 IActivityManager mgr = ActivityManagerNative.getDefault();
824 try {
825 mgr.finishReceiver(this, resultCode, data, extras, false);
826 } catch (RemoteException e) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -0800827 Slog.w(TAG, "Couldn't finish broadcast to unregistered receiver");
Christopher Tate08a46252009-12-08 13:48:45 -0800828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 }
830 }
831 }
Bob Leee5408332009-09-04 18:31:17 -0700832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 final IIntentReceiver.Stub mIIntentReceiver;
834 final BroadcastReceiver mReceiver;
835 final Context mContext;
836 final Handler mActivityThread;
837 final Instrumentation mInstrumentation;
838 final boolean mRegistered;
839 final IntentReceiverLeaked mLocation;
840 RuntimeException mUnregisterLocation;
841
842 final class Args implements Runnable {
843 private Intent mCurIntent;
844 private int mCurCode;
845 private String mCurData;
846 private Bundle mCurMap;
847 private boolean mCurOrdered;
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700848 private boolean mCurSticky;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849
850 public void run() {
851 BroadcastReceiver receiver = mReceiver;
852 if (DEBUG_BROADCAST) {
853 int seq = mCurIntent.getIntExtra("seq", -1);
Christopher Tate08a46252009-12-08 13:48:45 -0800854 Log.i(TAG, "Dispatching broadcast " + mCurIntent.getAction()
855 + " seq=" + seq + " to " + mReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 }
857 if (receiver == null) {
858 return;
859 }
860
861 IActivityManager mgr = ActivityManagerNative.getDefault();
862 Intent intent = mCurIntent;
863 mCurIntent = null;
864 try {
865 ClassLoader cl = mReceiver.getClass().getClassLoader();
866 intent.setExtrasClassLoader(cl);
867 if (mCurMap != null) {
868 mCurMap.setClassLoader(cl);
869 }
870 receiver.setOrderedHint(true);
871 receiver.setResult(mCurCode, mCurData, mCurMap);
872 receiver.clearAbortBroadcast();
873 receiver.setOrderedHint(mCurOrdered);
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700874 receiver.setInitialStickyHint(mCurSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 receiver.onReceive(mContext, intent);
876 } catch (Exception e) {
877 if (mRegistered && mCurOrdered) {
878 try {
879 mgr.finishReceiver(mIIntentReceiver,
880 mCurCode, mCurData, mCurMap, false);
881 } catch (RemoteException ex) {
882 }
883 }
884 if (mInstrumentation == null ||
885 !mInstrumentation.onException(mReceiver, e)) {
886 throw new RuntimeException(
887 "Error receiving broadcast " + intent
888 + " in " + mReceiver, e);
889 }
890 }
891 if (mRegistered && mCurOrdered) {
892 try {
893 mgr.finishReceiver(mIIntentReceiver,
894 receiver.getResultCode(),
895 receiver.getResultData(),
896 receiver.getResultExtras(false),
897 receiver.getAbortBroadcast());
898 } catch (RemoteException ex) {
899 }
900 }
901 }
902 }
903
904 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
905 Handler activityThread, Instrumentation instrumentation,
906 boolean registered) {
907 if (activityThread == null) {
908 throw new NullPointerException("Handler must not be null");
909 }
910
911 mIIntentReceiver = new InnerReceiver(this, !registered);
912 mReceiver = receiver;
913 mContext = context;
914 mActivityThread = activityThread;
915 mInstrumentation = instrumentation;
916 mRegistered = registered;
917 mLocation = new IntentReceiverLeaked(null);
918 mLocation.fillInStackTrace();
919 }
920
921 void validate(Context context, Handler activityThread) {
922 if (mContext != context) {
923 throw new IllegalStateException(
924 "Receiver " + mReceiver +
925 " registered with differing Context (was " +
926 mContext + " now " + context + ")");
927 }
928 if (mActivityThread != activityThread) {
929 throw new IllegalStateException(
930 "Receiver " + mReceiver +
931 " registered with differing handler (was " +
932 mActivityThread + " now " + activityThread + ")");
933 }
934 }
935
936 IntentReceiverLeaked getLocation() {
937 return mLocation;
938 }
939
940 BroadcastReceiver getIntentReceiver() {
941 return mReceiver;
942 }
Bob Leee5408332009-09-04 18:31:17 -0700943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 IIntentReceiver getIIntentReceiver() {
945 return mIIntentReceiver;
946 }
947
948 void setUnregisterLocation(RuntimeException ex) {
949 mUnregisterLocation = ex;
950 }
951
952 RuntimeException getUnregisterLocation() {
953 return mUnregisterLocation;
954 }
955
956 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700957 String data, Bundle extras, boolean ordered, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 if (DEBUG_BROADCAST) {
959 int seq = intent.getIntExtra("seq", -1);
960 Log.i(TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
961 + " to " + mReceiver);
962 }
963 Args args = new Args();
964 args.mCurIntent = intent;
965 args.mCurCode = resultCode;
966 args.mCurData = data;
967 args.mCurMap = extras;
968 args.mCurOrdered = ordered;
Dianne Hackborn68d881c2009-10-05 13:58:17 -0700969 args.mCurSticky = sticky;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 if (!mActivityThread.post(args)) {
971 if (mRegistered) {
972 IActivityManager mgr = ActivityManagerNative.getDefault();
973 try {
974 mgr.finishReceiver(mIIntentReceiver, args.mCurCode,
975 args.mCurData, args.mCurMap, false);
976 } catch (RemoteException ex) {
977 }
978 }
979 }
980 }
981
982 }
983
984 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
985 Context context, Handler handler, int flags) {
986 synchronized (mServices) {
987 ServiceDispatcher sd = null;
988 HashMap<ServiceConnection, ServiceDispatcher> map = mServices.get(context);
989 if (map != null) {
990 sd = map.get(c);
991 }
992 if (sd == null) {
993 sd = new ServiceDispatcher(c, context, handler, flags);
994 if (map == null) {
995 map = new HashMap<ServiceConnection, ServiceDispatcher>();
996 mServices.put(context, map);
997 }
998 map.put(c, sd);
999 } else {
1000 sd.validate(context, handler);
1001 }
1002 return sd.getIServiceConnection();
1003 }
1004 }
1005
1006 public final IServiceConnection forgetServiceDispatcher(Context context,
1007 ServiceConnection c) {
1008 synchronized (mServices) {
1009 HashMap<ServiceConnection, ServiceDispatcher> map
1010 = mServices.get(context);
1011 ServiceDispatcher sd = null;
1012 if (map != null) {
1013 sd = map.get(c);
1014 if (sd != null) {
1015 map.remove(c);
1016 sd.doForget();
1017 if (map.size() == 0) {
1018 mServices.remove(context);
1019 }
1020 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
1021 HashMap<ServiceConnection, ServiceDispatcher> holder
1022 = mUnboundServices.get(context);
1023 if (holder == null) {
1024 holder = new HashMap<ServiceConnection, ServiceDispatcher>();
1025 mUnboundServices.put(context, holder);
1026 }
1027 RuntimeException ex = new IllegalArgumentException(
1028 "Originally unbound here:");
1029 ex.fillInStackTrace();
1030 sd.setUnbindLocation(ex);
1031 holder.put(c, sd);
1032 }
1033 return sd.getIServiceConnection();
1034 }
1035 }
1036 HashMap<ServiceConnection, ServiceDispatcher> holder
1037 = mUnboundServices.get(context);
1038 if (holder != null) {
1039 sd = holder.get(c);
1040 if (sd != null) {
1041 RuntimeException ex = sd.getUnbindLocation();
1042 throw new IllegalArgumentException(
1043 "Unbinding Service " + c
1044 + " that was already unbound", ex);
1045 }
1046 }
1047 if (context == null) {
1048 throw new IllegalStateException("Unbinding Service " + c
1049 + " from Context that is no longer in use: " + context);
1050 } else {
1051 throw new IllegalArgumentException("Service not registered: " + c);
1052 }
1053 }
1054 }
1055
1056 static final class ServiceDispatcher {
1057 private final InnerConnection mIServiceConnection;
1058 private final ServiceConnection mConnection;
1059 private final Context mContext;
1060 private final Handler mActivityThread;
1061 private final ServiceConnectionLeaked mLocation;
1062 private final int mFlags;
1063
1064 private RuntimeException mUnbindLocation;
1065
1066 private boolean mDied;
1067
1068 private static class ConnectionInfo {
1069 IBinder binder;
1070 IBinder.DeathRecipient deathMonitor;
1071 }
1072
1073 private static class InnerConnection extends IServiceConnection.Stub {
1074 final WeakReference<ServiceDispatcher> mDispatcher;
Bob Leee5408332009-09-04 18:31:17 -07001075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 InnerConnection(ServiceDispatcher sd) {
1077 mDispatcher = new WeakReference<ServiceDispatcher>(sd);
1078 }
1079
1080 public void connected(ComponentName name, IBinder service) throws RemoteException {
1081 ServiceDispatcher sd = mDispatcher.get();
1082 if (sd != null) {
1083 sd.connected(name, service);
1084 }
1085 }
1086 }
Bob Leee5408332009-09-04 18:31:17 -07001087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 private final HashMap<ComponentName, ConnectionInfo> mActiveConnections
1089 = new HashMap<ComponentName, ConnectionInfo>();
1090
1091 ServiceDispatcher(ServiceConnection conn,
1092 Context context, Handler activityThread, int flags) {
1093 mIServiceConnection = new InnerConnection(this);
1094 mConnection = conn;
1095 mContext = context;
1096 mActivityThread = activityThread;
1097 mLocation = new ServiceConnectionLeaked(null);
1098 mLocation.fillInStackTrace();
1099 mFlags = flags;
1100 }
1101
1102 void validate(Context context, Handler activityThread) {
1103 if (mContext != context) {
1104 throw new RuntimeException(
1105 "ServiceConnection " + mConnection +
1106 " registered with differing Context (was " +
1107 mContext + " now " + context + ")");
1108 }
1109 if (mActivityThread != activityThread) {
1110 throw new RuntimeException(
1111 "ServiceConnection " + mConnection +
1112 " registered with differing handler (was " +
1113 mActivityThread + " now " + activityThread + ")");
1114 }
1115 }
1116
1117 void doForget() {
1118 synchronized(this) {
1119 Iterator<ConnectionInfo> it = mActiveConnections.values().iterator();
1120 while (it.hasNext()) {
1121 ConnectionInfo ci = it.next();
1122 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
1123 }
1124 mActiveConnections.clear();
1125 }
1126 }
1127
1128 ServiceConnectionLeaked getLocation() {
1129 return mLocation;
1130 }
1131
1132 ServiceConnection getServiceConnection() {
1133 return mConnection;
1134 }
1135
1136 IServiceConnection getIServiceConnection() {
1137 return mIServiceConnection;
1138 }
Bob Leee5408332009-09-04 18:31:17 -07001139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 int getFlags() {
1141 return mFlags;
1142 }
1143
1144 void setUnbindLocation(RuntimeException ex) {
1145 mUnbindLocation = ex;
1146 }
1147
1148 RuntimeException getUnbindLocation() {
1149 return mUnbindLocation;
1150 }
1151
1152 public void connected(ComponentName name, IBinder service) {
1153 if (mActivityThread != null) {
1154 mActivityThread.post(new RunConnection(name, service, 0));
1155 } else {
1156 doConnected(name, service);
1157 }
1158 }
1159
1160 public void death(ComponentName name, IBinder service) {
1161 ConnectionInfo old;
1162
1163 synchronized (this) {
1164 mDied = true;
1165 old = mActiveConnections.remove(name);
1166 if (old == null || old.binder != service) {
1167 // Death for someone different than who we last
1168 // reported... just ignore it.
1169 return;
1170 }
1171 old.binder.unlinkToDeath(old.deathMonitor, 0);
1172 }
1173
1174 if (mActivityThread != null) {
1175 mActivityThread.post(new RunConnection(name, service, 1));
1176 } else {
1177 doDeath(name, service);
1178 }
1179 }
1180
1181 public void doConnected(ComponentName name, IBinder service) {
1182 ConnectionInfo old;
1183 ConnectionInfo info;
1184
1185 synchronized (this) {
1186 old = mActiveConnections.get(name);
1187 if (old != null && old.binder == service) {
1188 // Huh, already have this one. Oh well!
1189 return;
1190 }
1191
1192 if (service != null) {
1193 // A new service is being connected... set it all up.
1194 mDied = false;
1195 info = new ConnectionInfo();
1196 info.binder = service;
1197 info.deathMonitor = new DeathMonitor(name, service);
1198 try {
1199 service.linkToDeath(info.deathMonitor, 0);
1200 mActiveConnections.put(name, info);
1201 } catch (RemoteException e) {
1202 // This service was dead before we got it... just
1203 // don't do anything with it.
1204 mActiveConnections.remove(name);
1205 return;
1206 }
1207
1208 } else {
1209 // The named service is being disconnected... clean up.
1210 mActiveConnections.remove(name);
1211 }
1212
1213 if (old != null) {
1214 old.binder.unlinkToDeath(old.deathMonitor, 0);
1215 }
1216 }
1217
1218 // If there was an old service, it is not disconnected.
1219 if (old != null) {
1220 mConnection.onServiceDisconnected(name);
1221 }
1222 // If there is a new service, it is now connected.
1223 if (service != null) {
1224 mConnection.onServiceConnected(name, service);
1225 }
1226 }
1227
1228 public void doDeath(ComponentName name, IBinder service) {
1229 mConnection.onServiceDisconnected(name);
1230 }
1231
1232 private final class RunConnection implements Runnable {
1233 RunConnection(ComponentName name, IBinder service, int command) {
1234 mName = name;
1235 mService = service;
1236 mCommand = command;
1237 }
1238
1239 public void run() {
1240 if (mCommand == 0) {
1241 doConnected(mName, mService);
1242 } else if (mCommand == 1) {
1243 doDeath(mName, mService);
1244 }
1245 }
1246
1247 final ComponentName mName;
1248 final IBinder mService;
1249 final int mCommand;
1250 }
1251
1252 private final class DeathMonitor implements IBinder.DeathRecipient
1253 {
1254 DeathMonitor(ComponentName name, IBinder service) {
1255 mName = name;
1256 mService = service;
1257 }
1258
1259 public void binderDied() {
1260 death(mName, mService);
1261 }
1262
1263 final ComponentName mName;
1264 final IBinder mService;
1265 }
1266 }
1267 }
1268
Dianne Hackborn21556372010-02-04 16:34:40 -08001269 private static ContextImpl mSystemContext = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270
1271 private static final class ActivityRecord {
1272 IBinder token;
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001273 int ident;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001274 Intent intent;
1275 Bundle state;
1276 Activity activity;
1277 Window window;
1278 Activity parent;
1279 String embeddedID;
1280 Object lastNonConfigurationInstance;
1281 HashMap<String,Object> lastNonConfigurationChildInstances;
1282 boolean paused;
1283 boolean stopped;
1284 boolean hideForNow;
1285 Configuration newConfig;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001286 Configuration createdConfig;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 ActivityRecord nextIdle;
1288
1289 ActivityInfo activityInfo;
1290 PackageInfo packageInfo;
1291
1292 List<ResultInfo> pendingResults;
1293 List<Intent> pendingIntents;
1294
1295 boolean startsNotResumed;
1296 boolean isForward;
1297
1298 ActivityRecord() {
1299 parent = null;
1300 embeddedID = null;
1301 paused = false;
1302 stopped = false;
1303 hideForNow = false;
1304 nextIdle = null;
1305 }
1306
1307 public String toString() {
1308 ComponentName componentName = intent.getComponent();
1309 return "ActivityRecord{"
1310 + Integer.toHexString(System.identityHashCode(this))
1311 + " token=" + token + " " + (componentName == null
1312 ? "no component name" : componentName.toShortString())
1313 + "}";
1314 }
1315 }
1316
1317 private final class ProviderRecord implements IBinder.DeathRecipient {
1318 final String mName;
1319 final IContentProvider mProvider;
1320 final ContentProvider mLocalProvider;
1321
1322 ProviderRecord(String name, IContentProvider provider,
1323 ContentProvider localProvider) {
1324 mName = name;
1325 mProvider = provider;
1326 mLocalProvider = localProvider;
1327 }
1328
1329 public void binderDied() {
1330 removeDeadProvider(mName, mProvider);
1331 }
1332 }
1333
1334 private static final class NewIntentData {
1335 List<Intent> intents;
1336 IBinder token;
1337 public String toString() {
1338 return "NewIntentData{intents=" + intents + " token=" + token + "}";
1339 }
1340 }
1341
1342 private static final class ReceiverData {
1343 Intent intent;
1344 ActivityInfo info;
1345 int resultCode;
1346 String resultData;
1347 Bundle resultExtras;
1348 boolean sync;
1349 boolean resultAbort;
1350 public String toString() {
1351 return "ReceiverData{intent=" + intent + " packageName=" +
1352 info.packageName + " resultCode=" + resultCode
1353 + " resultData=" + resultData + " resultExtras=" + resultExtras + "}";
1354 }
1355 }
1356
Christopher Tate181fafa2009-05-14 11:12:14 -07001357 private static final class CreateBackupAgentData {
1358 ApplicationInfo appInfo;
1359 int backupMode;
1360 public String toString() {
1361 return "CreateBackupAgentData{appInfo=" + appInfo
1362 + " backupAgent=" + appInfo.backupAgentName
1363 + " mode=" + backupMode + "}";
1364 }
1365 }
Bob Leee5408332009-09-04 18:31:17 -07001366
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 private static final class CreateServiceData {
1368 IBinder token;
1369 ServiceInfo info;
1370 Intent intent;
1371 public String toString() {
1372 return "CreateServiceData{token=" + token + " className="
1373 + info.name + " packageName=" + info.packageName
1374 + " intent=" + intent + "}";
1375 }
1376 }
1377
1378 private static final class BindServiceData {
1379 IBinder token;
1380 Intent intent;
1381 boolean rebind;
1382 public String toString() {
1383 return "BindServiceData{token=" + token + " intent=" + intent + "}";
1384 }
1385 }
1386
1387 private static final class ServiceArgsData {
1388 IBinder token;
1389 int startId;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07001390 int flags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 Intent args;
1392 public String toString() {
1393 return "ServiceArgsData{token=" + token + " startId=" + startId
1394 + " args=" + args + "}";
1395 }
1396 }
1397
1398 private static final class AppBindData {
1399 PackageInfo info;
1400 String processName;
1401 ApplicationInfo appInfo;
1402 List<ProviderInfo> providers;
1403 ComponentName instrumentationName;
1404 String profileFile;
1405 Bundle instrumentationArgs;
1406 IInstrumentationWatcher instrumentationWatcher;
1407 int debugMode;
Christopher Tate181fafa2009-05-14 11:12:14 -07001408 boolean restrictedBackupMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 Configuration config;
1410 boolean handlingProfiling;
1411 public String toString() {
1412 return "AppBindData{appInfo=" + appInfo + "}";
1413 }
1414 }
1415
1416 private static final class DumpServiceInfo {
1417 FileDescriptor fd;
1418 IBinder service;
1419 String[] args;
1420 boolean dumped;
1421 }
1422
1423 private static final class ResultData {
1424 IBinder token;
1425 List<ResultInfo> results;
1426 public String toString() {
1427 return "ResultData{token=" + token + " results" + results + "}";
1428 }
1429 }
1430
1431 private static final class ContextCleanupInfo {
Dianne Hackborn21556372010-02-04 16:34:40 -08001432 ContextImpl context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 String what;
1434 String who;
1435 }
1436
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07001437 private static final class ProfilerControlData {
1438 String path;
1439 ParcelFileDescriptor fd;
1440 }
1441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 private final class ApplicationThread extends ApplicationThreadNative {
1443 private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
1444 private static final String ONE_COUNT_COLUMN = "%17s %8d";
1445 private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
Vasu Noric3849202010-03-09 10:47:25 -08001446 private static final String DB_INFO_FORMAT = " %8d %8d %10d %s";
Bob Leee5408332009-09-04 18:31:17 -07001447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 // Formatting for checkin service - update version if row format changes
1449 private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
Bob Leee5408332009-09-04 18:31:17 -07001450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 public final void schedulePauseActivity(IBinder token, boolean finished,
1452 boolean userLeaving, int configChanges) {
1453 queueOrSendMessage(
1454 finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
1455 token,
1456 (userLeaving ? 1 : 0),
1457 configChanges);
1458 }
1459
1460 public final void scheduleStopActivity(IBinder token, boolean showWindow,
1461 int configChanges) {
1462 queueOrSendMessage(
1463 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
1464 token, 0, configChanges);
1465 }
1466
1467 public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
1468 queueOrSendMessage(
1469 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
1470 token);
1471 }
1472
1473 public final void scheduleResumeActivity(IBinder token, boolean isForward) {
1474 queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
1475 }
1476
1477 public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
1478 ResultData res = new ResultData();
1479 res.token = token;
1480 res.results = results;
1481 queueOrSendMessage(H.SEND_RESULT, res);
1482 }
1483
1484 // we use token to identify this activity without having to send the
1485 // activity itself back to the activity manager. (matters more with ipc)
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001486 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
1488 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
1489 ActivityRecord r = new ActivityRecord();
1490
1491 r.token = token;
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001492 r.ident = ident;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 r.intent = intent;
1494 r.activityInfo = info;
1495 r.state = state;
1496
1497 r.pendingResults = pendingResults;
1498 r.pendingIntents = pendingNewIntents;
1499
1500 r.startsNotResumed = notResumed;
1501 r.isForward = isForward;
1502
1503 queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
1504 }
1505
1506 public final void scheduleRelaunchActivity(IBinder token,
1507 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -08001508 int configChanges, boolean notResumed, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 ActivityRecord r = new ActivityRecord();
1510
1511 r.token = token;
1512 r.pendingResults = pendingResults;
1513 r.pendingIntents = pendingNewIntents;
1514 r.startsNotResumed = notResumed;
Dianne Hackborn871ecdc2009-12-11 15:24:33 -08001515 r.createdConfig = config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001517 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 mRelaunchingActivities.add(r);
1519 }
Bob Leee5408332009-09-04 18:31:17 -07001520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges);
1522 }
1523
1524 public final void scheduleNewIntent(List<Intent> intents, IBinder token) {
1525 NewIntentData data = new NewIntentData();
1526 data.intents = intents;
1527 data.token = token;
1528
1529 queueOrSendMessage(H.NEW_INTENT, data);
1530 }
1531
1532 public final void scheduleDestroyActivity(IBinder token, boolean finishing,
1533 int configChanges) {
1534 queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
1535 configChanges);
1536 }
1537
1538 public final void scheduleReceiver(Intent intent, ActivityInfo info,
1539 int resultCode, String data, Bundle extras, boolean sync) {
1540 ReceiverData r = new ReceiverData();
1541
1542 r.intent = intent;
1543 r.info = info;
1544 r.resultCode = resultCode;
1545 r.resultData = data;
1546 r.resultExtras = extras;
1547 r.sync = sync;
1548
1549 queueOrSendMessage(H.RECEIVER, r);
1550 }
1551
Christopher Tate181fafa2009-05-14 11:12:14 -07001552 public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) {
1553 CreateBackupAgentData d = new CreateBackupAgentData();
1554 d.appInfo = app;
1555 d.backupMode = backupMode;
1556
1557 queueOrSendMessage(H.CREATE_BACKUP_AGENT, d);
1558 }
1559
1560 public final void scheduleDestroyBackupAgent(ApplicationInfo app) {
1561 CreateBackupAgentData d = new CreateBackupAgentData();
1562 d.appInfo = app;
1563
1564 queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d);
1565 }
1566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 public final void scheduleCreateService(IBinder token,
1568 ServiceInfo info) {
1569 CreateServiceData s = new CreateServiceData();
1570 s.token = token;
1571 s.info = info;
1572
1573 queueOrSendMessage(H.CREATE_SERVICE, s);
1574 }
1575
1576 public final void scheduleBindService(IBinder token, Intent intent,
1577 boolean rebind) {
1578 BindServiceData s = new BindServiceData();
1579 s.token = token;
1580 s.intent = intent;
1581 s.rebind = rebind;
1582
1583 queueOrSendMessage(H.BIND_SERVICE, s);
1584 }
1585
1586 public final void scheduleUnbindService(IBinder token, Intent intent) {
1587 BindServiceData s = new BindServiceData();
1588 s.token = token;
1589 s.intent = intent;
1590
1591 queueOrSendMessage(H.UNBIND_SERVICE, s);
1592 }
1593
1594 public final void scheduleServiceArgs(IBinder token, int startId,
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07001595 int flags ,Intent args) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 ServiceArgsData s = new ServiceArgsData();
1597 s.token = token;
1598 s.startId = startId;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07001599 s.flags = flags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 s.args = args;
1601
1602 queueOrSendMessage(H.SERVICE_ARGS, s);
1603 }
1604
1605 public final void scheduleStopService(IBinder token) {
1606 queueOrSendMessage(H.STOP_SERVICE, token);
1607 }
1608
1609 public final void bindApplication(String processName,
1610 ApplicationInfo appInfo, List<ProviderInfo> providers,
1611 ComponentName instrumentationName, String profileFile,
1612 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
Christopher Tate181fafa2009-05-14 11:12:14 -07001613 int debugMode, boolean isRestrictedBackupMode, Configuration config,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 Map<String, IBinder> services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615
1616 if (services != null) {
1617 // Setup the service cache in the ServiceManager
1618 ServiceManager.initServiceCache(services);
1619 }
1620
1621 AppBindData data = new AppBindData();
1622 data.processName = processName;
1623 data.appInfo = appInfo;
1624 data.providers = providers;
1625 data.instrumentationName = instrumentationName;
1626 data.profileFile = profileFile;
1627 data.instrumentationArgs = instrumentationArgs;
1628 data.instrumentationWatcher = instrumentationWatcher;
1629 data.debugMode = debugMode;
Christopher Tate181fafa2009-05-14 11:12:14 -07001630 data.restrictedBackupMode = isRestrictedBackupMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 data.config = config;
1632 queueOrSendMessage(H.BIND_APPLICATION, data);
1633 }
1634
1635 public final void scheduleExit() {
1636 queueOrSendMessage(H.EXIT_APPLICATION, null);
1637 }
1638
Christopher Tate5e1ab332009-09-01 20:32:49 -07001639 public final void scheduleSuicide() {
1640 queueOrSendMessage(H.SUICIDE, null);
1641 }
1642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 public void requestThumbnail(IBinder token) {
1644 queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
1645 }
1646
1647 public void scheduleConfigurationChanged(Configuration config) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001648 synchronized (mPackages) {
1649 if (mPendingConfiguration == null ||
1650 mPendingConfiguration.isOtherSeqNewer(config)) {
1651 mPendingConfiguration = config;
1652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 }
1654 queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
1655 }
1656
1657 public void updateTimeZone() {
1658 TimeZone.setDefault(null);
1659 }
1660
1661 public void processInBackground() {
1662 mH.removeMessages(H.GC_WHEN_IDLE);
1663 mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
1664 }
1665
1666 public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
1667 DumpServiceInfo data = new DumpServiceInfo();
1668 data.fd = fd;
1669 data.service = servicetoken;
1670 data.args = args;
1671 data.dumped = false;
1672 queueOrSendMessage(H.DUMP_SERVICE, data);
1673 synchronized (data) {
1674 while (!data.dumped) {
1675 try {
1676 data.wait();
1677 } catch (InterruptedException e) {
1678 // no need to do anything here, we will keep waiting until
1679 // dumped is set
1680 }
1681 }
1682 }
1683 }
1684
1685 // This function exists to make sure all receiver dispatching is
1686 // correctly ordered, since these are one-way calls and the binder driver
1687 // applies transaction ordering per object for such calls.
1688 public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07001689 int resultCode, String dataStr, Bundle extras, boolean ordered,
1690 boolean sticky) throws RemoteException {
1691 receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 }
Bob Leee5408332009-09-04 18:31:17 -07001693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 public void scheduleLowMemory() {
1695 queueOrSendMessage(H.LOW_MEMORY, null);
1696 }
1697
1698 public void scheduleActivityConfigurationChanged(IBinder token) {
1699 queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
1700 }
1701
1702 public void requestPss() {
1703 try {
1704 ActivityManagerNative.getDefault().reportPss(this,
1705 (int)Process.getPss(Process.myPid()));
1706 } catch (RemoteException e) {
1707 }
1708 }
Bob Leee5408332009-09-04 18:31:17 -07001709
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07001710 public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
1711 ProfilerControlData pcd = new ProfilerControlData();
1712 pcd.path = path;
1713 pcd.fd = fd;
1714 queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001715 }
1716
Dianne Hackborn06de2ea2009-05-21 12:56:43 -07001717 public void setSchedulingGroup(int group) {
1718 // Note: do this immediately, since going into the foreground
1719 // should happen regardless of what pending work we have to do
1720 // and the activity manager will wait for us to report back that
1721 // we are done before sending us to the background.
1722 try {
1723 Process.setProcessGroup(Process.myPid(), group);
1724 } catch (Exception e) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08001725 Slog.w(TAG, "Failed setting process group to " + group, e);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -07001726 }
1727 }
Bob Leee5408332009-09-04 18:31:17 -07001728
Dianne Hackborn3025ef32009-08-31 21:31:47 -07001729 public void getMemoryInfo(Debug.MemoryInfo outInfo) {
1730 Debug.getMemoryInfo(outInfo);
1731 }
Bob Leee5408332009-09-04 18:31:17 -07001732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 @Override
1734 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1735 long nativeMax = Debug.getNativeHeapSize() / 1024;
1736 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
1737 long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
1738
1739 Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
1740 Debug.getMemoryInfo(memInfo);
1741
1742 final int nativeShared = memInfo.nativeSharedDirty;
1743 final int dalvikShared = memInfo.dalvikSharedDirty;
1744 final int otherShared = memInfo.otherSharedDirty;
1745
1746 final int nativePrivate = memInfo.nativePrivateDirty;
1747 final int dalvikPrivate = memInfo.dalvikPrivateDirty;
1748 final int otherPrivate = memInfo.otherPrivateDirty;
1749
1750 Runtime runtime = Runtime.getRuntime();
1751
1752 long dalvikMax = runtime.totalMemory() / 1024;
1753 long dalvikFree = runtime.freeMemory() / 1024;
1754 long dalvikAllocated = dalvikMax - dalvikFree;
1755 long viewInstanceCount = ViewDebug.getViewInstanceCount();
1756 long viewRootInstanceCount = ViewDebug.getViewRootInstanceCount();
Dianne Hackborn21556372010-02-04 16:34:40 -08001757 long appContextInstanceCount = ContextImpl.getInstanceCount();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 long activityInstanceCount = Activity.getInstanceCount();
1759 int globalAssetCount = AssetManager.getGlobalAssetCount();
1760 int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
1761 int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
1762 int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
1763 int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
1764 int openSslSocketCount = OpenSSLSocketImpl.getInstanceCount();
1765 long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024;
Vasu Noric3849202010-03-09 10:47:25 -08001766 SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
Bob Leee5408332009-09-04 18:31:17 -07001767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 // Check to see if we were called by checkin server. If so, print terse format.
1769 boolean doCheckinFormat = false;
1770 if (args != null) {
1771 for (String arg : args) {
1772 if ("-c".equals(arg)) doCheckinFormat = true;
1773 }
1774 }
Bob Leee5408332009-09-04 18:31:17 -07001775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 // For checkin, we print one long comma-separated list of values
1777 if (doCheckinFormat) {
1778 // NOTE: if you change anything significant below, also consider changing
1779 // ACTIVITY_THREAD_CHECKIN_VERSION.
Bob Leee5408332009-09-04 18:31:17 -07001780 String processName = (mBoundApplication != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 ? mBoundApplication.processName : "unknown";
Bob Leee5408332009-09-04 18:31:17 -07001782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 // Header
1784 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
1785 pw.print(Process.myPid()); pw.print(',');
1786 pw.print(processName); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 // Heap info - max
1789 pw.print(nativeMax); pw.print(',');
1790 pw.print(dalvikMax); pw.print(',');
1791 pw.print("N/A,");
1792 pw.print(nativeMax + dalvikMax); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 // Heap info - allocated
1795 pw.print(nativeAllocated); pw.print(',');
1796 pw.print(dalvikAllocated); pw.print(',');
1797 pw.print("N/A,");
1798 pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 // Heap info - free
1801 pw.print(nativeFree); pw.print(',');
1802 pw.print(dalvikFree); pw.print(',');
1803 pw.print("N/A,");
1804 pw.print(nativeFree + dalvikFree); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 // Heap info - proportional set size
1807 pw.print(memInfo.nativePss); pw.print(',');
1808 pw.print(memInfo.dalvikPss); pw.print(',');
1809 pw.print(memInfo.otherPss); pw.print(',');
1810 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 // Heap info - shared
Bob Leee5408332009-09-04 18:31:17 -07001813 pw.print(nativeShared); pw.print(',');
1814 pw.print(dalvikShared); pw.print(',');
1815 pw.print(otherShared); pw.print(',');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816 pw.print(nativeShared + dalvikShared + otherShared); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 // Heap info - private
Bob Leee5408332009-09-04 18:31:17 -07001819 pw.print(nativePrivate); pw.print(',');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 pw.print(dalvikPrivate); pw.print(',');
1821 pw.print(otherPrivate); pw.print(',');
1822 pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001823
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001824 // Object counts
1825 pw.print(viewInstanceCount); pw.print(',');
1826 pw.print(viewRootInstanceCount); pw.print(',');
1827 pw.print(appContextInstanceCount); pw.print(',');
1828 pw.print(activityInstanceCount); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 pw.print(globalAssetCount); pw.print(',');
1831 pw.print(globalAssetManagerCount); pw.print(',');
1832 pw.print(binderLocalObjectCount); pw.print(',');
1833 pw.print(binderProxyObjectCount); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 pw.print(binderDeathObjectCount); pw.print(',');
1836 pw.print(openSslSocketCount); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838 // SQL
1839 pw.print(sqliteAllocated); pw.print(',');
Vasu Noric3849202010-03-09 10:47:25 -08001840 pw.print(stats.memoryUsed / 1024); pw.print(',');
1841 pw.print(stats.pageCacheOverflo / 1024); pw.print(',');
1842 pw.print(stats.largestMemAlloc / 1024); pw.print(',');
1843 for (int i = 0; i < stats.dbStats.size(); i++) {
1844 DbStats dbStats = stats.dbStats.get(i);
1845 printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
1846 dbStats.lookaside, dbStats.dbName);
1847 pw.print(',');
1848 }
Bob Leee5408332009-09-04 18:31:17 -07001849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 return;
1851 }
Bob Leee5408332009-09-04 18:31:17 -07001852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 // otherwise, show human-readable format
1854 printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total");
1855 printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
1856 printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
1857 nativeAllocated + dalvikAllocated);
1858 printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A",
1859 nativeFree + dalvikFree);
1860
1861 printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
1862 memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);
1863
1864 printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared,
1865 nativeShared + dalvikShared + otherShared);
1866 printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
1867 nativePrivate + dalvikPrivate + otherPrivate);
1868
1869 pw.println(" ");
1870 pw.println(" Objects");
1871 printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRoots:",
1872 viewRootInstanceCount);
1873
1874 printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
1875 "Activities:", activityInstanceCount);
1876
1877 printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
1878 "AssetManagers:", globalAssetManagerCount);
1879
1880 printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
1881 "Proxy Binders:", binderProxyObjectCount);
1882 printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount);
1883
1884 printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount);
Bob Leee5408332009-09-04 18:31:17 -07001885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 // SQLite mem info
1887 pw.println(" ");
1888 pw.println(" SQL");
Vasu Noric3849202010-03-09 10:47:25 -08001889 printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "memoryUsed:",
1890 stats.memoryUsed / 1024);
1891 printRow(pw, TWO_COUNT_COLUMNS, "pageCacheOverflo:", stats.pageCacheOverflo / 1024,
1892 "largestMemAlloc:", stats.largestMemAlloc / 1024);
1893 pw.println(" ");
1894 int N = stats.dbStats.size();
1895 if (N > 0) {
1896 pw.println(" DATABASES");
1897 printRow(pw, " %8s %8s %10s %s", "Pagesize", "Dbsize", "Lookaside", "Dbname");
1898 for (int i = 0; i < N; i++) {
1899 DbStats dbStats = stats.dbStats.get(i);
1900 printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
1901 dbStats.lookaside, dbStats.dbName);
1902 }
1903 }
Bob Leee5408332009-09-04 18:31:17 -07001904
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001905 // Asset details.
1906 String assetAlloc = AssetManager.getAssetAllocations();
1907 if (assetAlloc != null) {
1908 pw.println(" ");
1909 pw.println(" Asset Allocations");
1910 pw.print(assetAlloc);
1911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 }
1913
1914 private void printRow(PrintWriter pw, String format, Object...objs) {
1915 pw.println(String.format(format, objs));
1916 }
1917 }
1918
1919 private final class H extends Handler {
Bob Leee5408332009-09-04 18:31:17 -07001920 private H() {
1921 SamplingProfiler.getInstance().setEventThread(mLooper.getThread());
1922 }
1923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 public static final int LAUNCH_ACTIVITY = 100;
1925 public static final int PAUSE_ACTIVITY = 101;
1926 public static final int PAUSE_ACTIVITY_FINISHING= 102;
1927 public static final int STOP_ACTIVITY_SHOW = 103;
1928 public static final int STOP_ACTIVITY_HIDE = 104;
1929 public static final int SHOW_WINDOW = 105;
1930 public static final int HIDE_WINDOW = 106;
1931 public static final int RESUME_ACTIVITY = 107;
1932 public static final int SEND_RESULT = 108;
1933 public static final int DESTROY_ACTIVITY = 109;
1934 public static final int BIND_APPLICATION = 110;
1935 public static final int EXIT_APPLICATION = 111;
1936 public static final int NEW_INTENT = 112;
1937 public static final int RECEIVER = 113;
1938 public static final int CREATE_SERVICE = 114;
1939 public static final int SERVICE_ARGS = 115;
1940 public static final int STOP_SERVICE = 116;
1941 public static final int REQUEST_THUMBNAIL = 117;
1942 public static final int CONFIGURATION_CHANGED = 118;
1943 public static final int CLEAN_UP_CONTEXT = 119;
1944 public static final int GC_WHEN_IDLE = 120;
1945 public static final int BIND_SERVICE = 121;
1946 public static final int UNBIND_SERVICE = 122;
1947 public static final int DUMP_SERVICE = 123;
1948 public static final int LOW_MEMORY = 124;
1949 public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
1950 public static final int RELAUNCH_ACTIVITY = 126;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001951 public static final int PROFILER_CONTROL = 127;
Christopher Tate181fafa2009-05-14 11:12:14 -07001952 public static final int CREATE_BACKUP_AGENT = 128;
Christopher Tate5e1ab332009-09-01 20:32:49 -07001953 public static final int DESTROY_BACKUP_AGENT = 129;
1954 public static final int SUICIDE = 130;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001955 public static final int REMOVE_PROVIDER = 131;
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08001956 public static final int ENABLE_JIT = 132;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 String codeToString(int code) {
1958 if (localLOGV) {
1959 switch (code) {
1960 case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
1961 case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
1962 case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
1963 case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
1964 case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
1965 case SHOW_WINDOW: return "SHOW_WINDOW";
1966 case HIDE_WINDOW: return "HIDE_WINDOW";
1967 case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
1968 case SEND_RESULT: return "SEND_RESULT";
1969 case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
1970 case BIND_APPLICATION: return "BIND_APPLICATION";
1971 case EXIT_APPLICATION: return "EXIT_APPLICATION";
1972 case NEW_INTENT: return "NEW_INTENT";
1973 case RECEIVER: return "RECEIVER";
1974 case CREATE_SERVICE: return "CREATE_SERVICE";
1975 case SERVICE_ARGS: return "SERVICE_ARGS";
1976 case STOP_SERVICE: return "STOP_SERVICE";
1977 case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
1978 case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
1979 case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
1980 case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
1981 case BIND_SERVICE: return "BIND_SERVICE";
1982 case UNBIND_SERVICE: return "UNBIND_SERVICE";
1983 case DUMP_SERVICE: return "DUMP_SERVICE";
1984 case LOW_MEMORY: return "LOW_MEMORY";
1985 case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
1986 case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001987 case PROFILER_CONTROL: return "PROFILER_CONTROL";
Christopher Tate181fafa2009-05-14 11:12:14 -07001988 case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
1989 case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
Christopher Tate5e1ab332009-09-01 20:32:49 -07001990 case SUICIDE: return "SUICIDE";
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001991 case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08001992 case ENABLE_JIT: return "ENABLE_JIT";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 }
1994 }
1995 return "(unknown)";
1996 }
1997 public void handleMessage(Message msg) {
1998 switch (msg.what) {
1999 case LAUNCH_ACTIVITY: {
2000 ActivityRecord r = (ActivityRecord)msg.obj;
2001
2002 r.packageInfo = getPackageInfoNoCheck(
2003 r.activityInfo.applicationInfo);
Christopher Tateb70f3df2009-04-07 16:07:59 -07002004 handleLaunchActivity(r, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002005 } break;
2006 case RELAUNCH_ACTIVITY: {
2007 ActivityRecord r = (ActivityRecord)msg.obj;
2008 handleRelaunchActivity(r, msg.arg1);
2009 } break;
2010 case PAUSE_ACTIVITY:
2011 handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
Bob Leee5408332009-09-04 18:31:17 -07002012 maybeSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 break;
2014 case PAUSE_ACTIVITY_FINISHING:
2015 handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
2016 break;
2017 case STOP_ACTIVITY_SHOW:
2018 handleStopActivity((IBinder)msg.obj, true, msg.arg2);
2019 break;
2020 case STOP_ACTIVITY_HIDE:
2021 handleStopActivity((IBinder)msg.obj, false, msg.arg2);
2022 break;
2023 case SHOW_WINDOW:
2024 handleWindowVisibility((IBinder)msg.obj, true);
2025 break;
2026 case HIDE_WINDOW:
2027 handleWindowVisibility((IBinder)msg.obj, false);
2028 break;
2029 case RESUME_ACTIVITY:
2030 handleResumeActivity((IBinder)msg.obj, true,
2031 msg.arg1 != 0);
2032 break;
2033 case SEND_RESULT:
2034 handleSendResult((ResultData)msg.obj);
2035 break;
2036 case DESTROY_ACTIVITY:
2037 handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
2038 msg.arg2, false);
2039 break;
2040 case BIND_APPLICATION:
2041 AppBindData data = (AppBindData)msg.obj;
2042 handleBindApplication(data);
2043 break;
2044 case EXIT_APPLICATION:
2045 if (mInitialApplication != null) {
2046 mInitialApplication.onTerminate();
2047 }
2048 Looper.myLooper().quit();
2049 break;
2050 case NEW_INTENT:
2051 handleNewIntent((NewIntentData)msg.obj);
2052 break;
2053 case RECEIVER:
2054 handleReceiver((ReceiverData)msg.obj);
Bob Leee5408332009-09-04 18:31:17 -07002055 maybeSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 break;
2057 case CREATE_SERVICE:
2058 handleCreateService((CreateServiceData)msg.obj);
2059 break;
2060 case BIND_SERVICE:
2061 handleBindService((BindServiceData)msg.obj);
2062 break;
2063 case UNBIND_SERVICE:
2064 handleUnbindService((BindServiceData)msg.obj);
2065 break;
2066 case SERVICE_ARGS:
2067 handleServiceArgs((ServiceArgsData)msg.obj);
2068 break;
2069 case STOP_SERVICE:
2070 handleStopService((IBinder)msg.obj);
Bob Leee5408332009-09-04 18:31:17 -07002071 maybeSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 break;
2073 case REQUEST_THUMBNAIL:
2074 handleRequestThumbnail((IBinder)msg.obj);
2075 break;
2076 case CONFIGURATION_CHANGED:
2077 handleConfigurationChanged((Configuration)msg.obj);
2078 break;
2079 case CLEAN_UP_CONTEXT:
2080 ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
2081 cci.context.performFinalCleanup(cci.who, cci.what);
2082 break;
2083 case GC_WHEN_IDLE:
2084 scheduleGcIdler();
2085 break;
2086 case DUMP_SERVICE:
2087 handleDumpService((DumpServiceInfo)msg.obj);
2088 break;
2089 case LOW_MEMORY:
2090 handleLowMemory();
2091 break;
2092 case ACTIVITY_CONFIGURATION_CHANGED:
2093 handleActivityConfigurationChanged((IBinder)msg.obj);
2094 break;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08002095 case PROFILER_CONTROL:
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07002096 handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08002097 break;
Christopher Tate181fafa2009-05-14 11:12:14 -07002098 case CREATE_BACKUP_AGENT:
2099 handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
2100 break;
2101 case DESTROY_BACKUP_AGENT:
2102 handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
2103 break;
Christopher Tate5e1ab332009-09-01 20:32:49 -07002104 case SUICIDE:
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07002105 Process.killProcess(Process.myPid());
2106 break;
2107 case REMOVE_PROVIDER:
2108 completeRemoveProvider((IContentProvider)msg.obj);
Christopher Tate5e1ab332009-09-01 20:32:49 -07002109 break;
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002110 case ENABLE_JIT:
2111 ensureJitEnabled();
2112 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113 }
2114 }
Bob Leee5408332009-09-04 18:31:17 -07002115
2116 void maybeSnapshot() {
2117 if (mBoundApplication != null) {
2118 SamplingProfilerIntegration.writeSnapshot(
2119 mBoundApplication.processName);
2120 }
2121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122 }
2123
2124 private final class Idler implements MessageQueue.IdleHandler {
2125 public final boolean queueIdle() {
2126 ActivityRecord a = mNewActivities;
2127 if (a != null) {
2128 mNewActivities = null;
2129 IActivityManager am = ActivityManagerNative.getDefault();
2130 ActivityRecord prev;
2131 do {
2132 if (localLOGV) Log.v(
2133 TAG, "Reporting idle of " + a +
2134 " finished=" +
2135 (a.activity != null ? a.activity.mFinished : false));
2136 if (a.activity != null && !a.activity.mFinished) {
2137 try {
Dianne Hackborne88846e2009-09-30 21:34:25 -07002138 am.activityIdle(a.token, a.createdConfig);
2139 a.createdConfig = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002140 } catch (RemoteException ex) {
2141 }
2142 }
2143 prev = a;
2144 a = a.nextIdle;
2145 prev.nextIdle = null;
2146 } while (a != null);
2147 }
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002148 ensureJitEnabled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 return false;
2150 }
2151 }
2152
2153 final class GcIdler implements MessageQueue.IdleHandler {
2154 public final boolean queueIdle() {
2155 doGcIfNeeded();
2156 return false;
2157 }
2158 }
2159
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07002160 private final static class ResourcesKey {
2161 final private String mResDir;
2162 final private float mScale;
2163 final private int mHash;
Bob Leee5408332009-09-04 18:31:17 -07002164
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07002165 ResourcesKey(String resDir, float scale) {
2166 mResDir = resDir;
2167 mScale = scale;
2168 mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
2169 }
Bob Leee5408332009-09-04 18:31:17 -07002170
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07002171 @Override
2172 public int hashCode() {
2173 return mHash;
2174 }
2175
2176 @Override
2177 public boolean equals(Object obj) {
2178 if (!(obj instanceof ResourcesKey)) {
2179 return false;
2180 }
2181 ResourcesKey peer = (ResourcesKey) obj;
2182 return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
2183 }
2184 }
2185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 static IPackageManager sPackageManager;
2187
2188 final ApplicationThread mAppThread = new ApplicationThread();
2189 final Looper mLooper = Looper.myLooper();
2190 final H mH = new H();
2191 final HashMap<IBinder, ActivityRecord> mActivities
2192 = new HashMap<IBinder, ActivityRecord>();
2193 // List of new activities (via ActivityRecord.nextIdle) that should
2194 // be reported when next we idle.
2195 ActivityRecord mNewActivities = null;
2196 // Number of activities that are currently visible on-screen.
2197 int mNumVisibleActivities = 0;
2198 final HashMap<IBinder, Service> mServices
2199 = new HashMap<IBinder, Service>();
2200 AppBindData mBoundApplication;
2201 Configuration mConfiguration;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002202 Configuration mResConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 Application mInitialApplication;
2204 final ArrayList<Application> mAllApplications
2205 = new ArrayList<Application>();
Christopher Tate181fafa2009-05-14 11:12:14 -07002206 // set of instantiated backup agents, keyed by package name
2207 final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208 static final ThreadLocal sThreadLocal = new ThreadLocal();
2209 Instrumentation mInstrumentation;
2210 String mInstrumentationAppDir = null;
2211 String mInstrumentationAppPackage = null;
2212 String mInstrumentedAppDir = null;
2213 boolean mSystemThread = false;
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002214 boolean mJitEnabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216 // These can be accessed by multiple threads; mPackages is the lock.
2217 // XXX For now we keep around information about all packages we have
2218 // seen, not removing entries from this map.
2219 final HashMap<String, WeakReference<PackageInfo>> mPackages
2220 = new HashMap<String, WeakReference<PackageInfo>>();
2221 final HashMap<String, WeakReference<PackageInfo>> mResourcePackages
2222 = new HashMap<String, WeakReference<PackageInfo>>();
2223 Display mDisplay = null;
2224 DisplayMetrics mDisplayMetrics = null;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07002225 HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
2226 = new HashMap<ResourcesKey, WeakReference<Resources> >();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002227 final ArrayList<ActivityRecord> mRelaunchingActivities
2228 = new ArrayList<ActivityRecord>();
2229 Configuration mPendingConfiguration = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002230
2231 // The lock of mProviderMap protects the following variables.
2232 final HashMap<String, ProviderRecord> mProviderMap
2233 = new HashMap<String, ProviderRecord>();
2234 final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
2235 = new HashMap<IBinder, ProviderRefCount>();
2236 final HashMap<IBinder, ProviderRecord> mLocalProviders
2237 = new HashMap<IBinder, ProviderRecord>();
2238
2239 final GcIdler mGcIdler = new GcIdler();
2240 boolean mGcIdlerScheduled = false;
2241
2242 public final PackageInfo getPackageInfo(String packageName, int flags) {
2243 synchronized (mPackages) {
2244 WeakReference<PackageInfo> ref;
2245 if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
2246 ref = mPackages.get(packageName);
2247 } else {
2248 ref = mResourcePackages.get(packageName);
2249 }
2250 PackageInfo packageInfo = ref != null ? ref.get() : null;
2251 //Log.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
2252 if (packageInfo != null && (packageInfo.mResources == null
2253 || packageInfo.mResources.getAssets().isUpToDate())) {
2254 if (packageInfo.isSecurityViolation()
2255 && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
2256 throw new SecurityException(
2257 "Requesting code from " + packageName
2258 + " to be run in process "
2259 + mBoundApplication.processName
2260 + "/" + mBoundApplication.appInfo.uid);
2261 }
2262 return packageInfo;
2263 }
2264 }
2265
2266 ApplicationInfo ai = null;
2267 try {
2268 ai = getPackageManager().getApplicationInfo(packageName,
2269 PackageManager.GET_SHARED_LIBRARY_FILES);
2270 } catch (RemoteException e) {
2271 }
2272
2273 if (ai != null) {
2274 return getPackageInfo(ai, flags);
2275 }
2276
2277 return null;
2278 }
2279
2280 public final PackageInfo getPackageInfo(ApplicationInfo ai, int flags) {
2281 boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
2282 boolean securityViolation = includeCode && ai.uid != 0
2283 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
2284 ? ai.uid != mBoundApplication.appInfo.uid : true);
2285 if ((flags&(Context.CONTEXT_INCLUDE_CODE
2286 |Context.CONTEXT_IGNORE_SECURITY))
2287 == Context.CONTEXT_INCLUDE_CODE) {
2288 if (securityViolation) {
2289 String msg = "Requesting code from " + ai.packageName
2290 + " (with uid " + ai.uid + ")";
2291 if (mBoundApplication != null) {
2292 msg = msg + " to be run in process "
2293 + mBoundApplication.processName + " (with uid "
2294 + mBoundApplication.appInfo.uid + ")";
2295 }
2296 throw new SecurityException(msg);
2297 }
2298 }
2299 return getPackageInfo(ai, null, securityViolation, includeCode);
2300 }
2301
2302 public final PackageInfo getPackageInfoNoCheck(ApplicationInfo ai) {
2303 return getPackageInfo(ai, null, false, true);
2304 }
2305
2306 private final PackageInfo getPackageInfo(ApplicationInfo aInfo,
2307 ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
2308 synchronized (mPackages) {
2309 WeakReference<PackageInfo> ref;
2310 if (includeCode) {
2311 ref = mPackages.get(aInfo.packageName);
2312 } else {
2313 ref = mResourcePackages.get(aInfo.packageName);
2314 }
2315 PackageInfo packageInfo = ref != null ? ref.get() : null;
2316 if (packageInfo == null || (packageInfo.mResources != null
2317 && !packageInfo.mResources.getAssets().isUpToDate())) {
2318 if (localLOGV) Log.v(TAG, (includeCode ? "Loading code package "
2319 : "Loading resource-only package ") + aInfo.packageName
2320 + " (in " + (mBoundApplication != null
2321 ? mBoundApplication.processName : null)
2322 + ")");
2323 packageInfo =
2324 new PackageInfo(this, aInfo, this, baseLoader,
2325 securityViolation, includeCode &&
2326 (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
2327 if (includeCode) {
2328 mPackages.put(aInfo.packageName,
2329 new WeakReference<PackageInfo>(packageInfo));
2330 } else {
2331 mResourcePackages.put(aInfo.packageName,
2332 new WeakReference<PackageInfo>(packageInfo));
2333 }
2334 }
2335 return packageInfo;
2336 }
2337 }
2338
2339 public final boolean hasPackageInfo(String packageName) {
2340 synchronized (mPackages) {
2341 WeakReference<PackageInfo> ref;
2342 ref = mPackages.get(packageName);
2343 if (ref != null && ref.get() != null) {
2344 return true;
2345 }
2346 ref = mResourcePackages.get(packageName);
2347 if (ref != null && ref.get() != null) {
2348 return true;
2349 }
2350 return false;
2351 }
2352 }
Bob Leee5408332009-09-04 18:31:17 -07002353
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 ActivityThread() {
2355 }
2356
2357 public ApplicationThread getApplicationThread()
2358 {
2359 return mAppThread;
2360 }
2361
2362 public Instrumentation getInstrumentation()
2363 {
2364 return mInstrumentation;
2365 }
2366
2367 public Configuration getConfiguration() {
2368 return mConfiguration;
2369 }
2370
2371 public boolean isProfiling() {
2372 return mBoundApplication != null && mBoundApplication.profileFile != null;
2373 }
2374
2375 public String getProfileFilePath() {
2376 return mBoundApplication.profileFile;
2377 }
2378
2379 public Looper getLooper() {
2380 return mLooper;
2381 }
2382
2383 public Application getApplication() {
2384 return mInitialApplication;
2385 }
Bob Leee5408332009-09-04 18:31:17 -07002386
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -07002387 public String getProcessName() {
2388 return mBoundApplication.processName;
2389 }
Bob Leee5408332009-09-04 18:31:17 -07002390
Dianne Hackborn21556372010-02-04 16:34:40 -08002391 public ContextImpl getSystemContext() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002392 synchronized (this) {
2393 if (mSystemContext == null) {
Dianne Hackborn21556372010-02-04 16:34:40 -08002394 ContextImpl context =
2395 ContextImpl.createSystemContext(this);
Mike Cleron432b7132009-09-24 15:28:29 -07002396 PackageInfo info = new PackageInfo(this, "android", context, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397 context.init(info, null, this);
2398 context.getResources().updateConfiguration(
2399 getConfiguration(), getDisplayMetricsLocked(false));
2400 mSystemContext = context;
2401 //Log.i(TAG, "Created system resources " + context.getResources()
2402 // + ": " + context.getResources().getConfiguration());
2403 }
2404 }
2405 return mSystemContext;
2406 }
2407
Mike Cleron432b7132009-09-24 15:28:29 -07002408 public void installSystemApplicationInfo(ApplicationInfo info) {
2409 synchronized (this) {
Dianne Hackborn21556372010-02-04 16:34:40 -08002410 ContextImpl context = getSystemContext();
Mike Cleron432b7132009-09-24 15:28:29 -07002411 context.init(new PackageInfo(this, "android", context, info), null, this);
2412 }
2413 }
2414
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002415 void ensureJitEnabled() {
2416 if (!mJitEnabled) {
2417 mJitEnabled = true;
2418 dalvik.system.VMRuntime.getRuntime().startJitCompilation();
2419 }
2420 }
2421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002422 void scheduleGcIdler() {
2423 if (!mGcIdlerScheduled) {
2424 mGcIdlerScheduled = true;
2425 Looper.myQueue().addIdleHandler(mGcIdler);
2426 }
2427 mH.removeMessages(H.GC_WHEN_IDLE);
2428 }
2429
2430 void unscheduleGcIdler() {
2431 if (mGcIdlerScheduled) {
2432 mGcIdlerScheduled = false;
2433 Looper.myQueue().removeIdleHandler(mGcIdler);
2434 }
2435 mH.removeMessages(H.GC_WHEN_IDLE);
2436 }
2437
2438 void doGcIfNeeded() {
2439 mGcIdlerScheduled = false;
2440 final long now = SystemClock.uptimeMillis();
2441 //Log.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
2442 // + "m now=" + now);
2443 if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
2444 //Log.i(TAG, "**** WE DO, WE DO WANT TO GC!");
2445 BinderInternal.forceGc("bg");
2446 }
2447 }
2448
2449 public final ActivityInfo resolveActivityInfo(Intent intent) {
2450 ActivityInfo aInfo = intent.resolveActivityInfo(
2451 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
2452 if (aInfo == null) {
2453 // Throw an exception.
2454 Instrumentation.checkStartActivityResult(
2455 IActivityManager.START_CLASS_NOT_FOUND, intent);
2456 }
2457 return aInfo;
2458 }
Bob Leee5408332009-09-04 18:31:17 -07002459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 public final Activity startActivityNow(Activity parent, String id,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002461 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
2462 Object lastNonConfigurationInstance) {
2463 ActivityRecord r = new ActivityRecord();
2464 r.token = token;
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002465 r.ident = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002466 r.intent = intent;
2467 r.state = state;
2468 r.parent = parent;
2469 r.embeddedID = id;
2470 r.activityInfo = activityInfo;
2471 r.lastNonConfigurationInstance = lastNonConfigurationInstance;
2472 if (localLOGV) {
2473 ComponentName compname = intent.getComponent();
2474 String name;
2475 if (compname != null) {
2476 name = compname.toShortString();
2477 } else {
2478 name = "(Intent " + intent + ").getComponent() returned null";
2479 }
2480 Log.v(TAG, "Performing launch: action=" + intent.getAction()
2481 + ", comp=" + name
2482 + ", token=" + token);
2483 }
Christopher Tateb70f3df2009-04-07 16:07:59 -07002484 return performLaunchActivity(r, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002485 }
2486
2487 public final Activity getActivity(IBinder token) {
2488 return mActivities.get(token).activity;
2489 }
2490
2491 public final void sendActivityResult(
2492 IBinder token, String id, int requestCode,
2493 int resultCode, Intent data) {
Chris Tate8a7dc172009-03-24 20:11:42 -07002494 if (DEBUG_RESULTS) Log.v(TAG, "sendActivityResult: id=" + id
2495 + " req=" + requestCode + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
2497 list.add(new ResultInfo(id, requestCode, resultCode, data));
2498 mAppThread.scheduleSendResult(token, list);
2499 }
2500
2501 // if the thread hasn't started yet, we don't have the handler, so just
2502 // save the messages until we're ready.
2503 private final void queueOrSendMessage(int what, Object obj) {
2504 queueOrSendMessage(what, obj, 0, 0);
2505 }
2506
2507 private final void queueOrSendMessage(int what, Object obj, int arg1) {
2508 queueOrSendMessage(what, obj, arg1, 0);
2509 }
2510
2511 private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
2512 synchronized (this) {
2513 if (localLOGV) Log.v(
2514 TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
2515 + ": " + arg1 + " / " + obj);
2516 Message msg = Message.obtain();
2517 msg.what = what;
2518 msg.obj = obj;
2519 msg.arg1 = arg1;
2520 msg.arg2 = arg2;
2521 mH.sendMessage(msg);
2522 }
2523 }
2524
Dianne Hackborn21556372010-02-04 16:34:40 -08002525 final void scheduleContextCleanup(ContextImpl context, String who,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526 String what) {
2527 ContextCleanupInfo cci = new ContextCleanupInfo();
2528 cci.context = context;
2529 cci.who = who;
2530 cci.what = what;
2531 queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
2532 }
2533
Christopher Tateb70f3df2009-04-07 16:07:59 -07002534 private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535 // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
2536
2537 ActivityInfo aInfo = r.activityInfo;
2538 if (r.packageInfo == null) {
2539 r.packageInfo = getPackageInfo(aInfo.applicationInfo,
2540 Context.CONTEXT_INCLUDE_CODE);
2541 }
Bob Leee5408332009-09-04 18:31:17 -07002542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002543 ComponentName component = r.intent.getComponent();
2544 if (component == null) {
2545 component = r.intent.resolveActivity(
2546 mInitialApplication.getPackageManager());
2547 r.intent.setComponent(component);
2548 }
2549
2550 if (r.activityInfo.targetActivity != null) {
2551 component = new ComponentName(r.activityInfo.packageName,
2552 r.activityInfo.targetActivity);
2553 }
2554
2555 Activity activity = null;
2556 try {
2557 java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
2558 activity = mInstrumentation.newActivity(
2559 cl, component.getClassName(), r.intent);
2560 r.intent.setExtrasClassLoader(cl);
2561 if (r.state != null) {
2562 r.state.setClassLoader(cl);
2563 }
2564 } catch (Exception e) {
2565 if (!mInstrumentation.onException(activity, e)) {
2566 throw new RuntimeException(
2567 "Unable to instantiate activity " + component
2568 + ": " + e.toString(), e);
2569 }
2570 }
2571
2572 try {
Dianne Hackborn0be1f782009-11-09 12:30:12 -08002573 Application app = r.packageInfo.makeApplication(false, mInstrumentation);
Bob Leee5408332009-09-04 18:31:17 -07002574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575 if (localLOGV) Log.v(TAG, "Performing launch of " + r);
2576 if (localLOGV) Log.v(
2577 TAG, r + ": app=" + app
2578 + ", appName=" + app.getPackageName()
2579 + ", pkg=" + r.packageInfo.getPackageName()
2580 + ", comp=" + r.intent.getComponent().toShortString()
2581 + ", dir=" + r.packageInfo.getAppDir());
2582
2583 if (activity != null) {
Dianne Hackborn21556372010-02-04 16:34:40 -08002584 ContextImpl appContext = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 appContext.init(r.packageInfo, r.token, this);
2586 appContext.setOuterContext(activity);
2587 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
2588 Configuration config = new Configuration(mConfiguration);
Dianne Hackborndc6b6352009-09-30 14:20:09 -07002589 if (DEBUG_CONFIGURATION) Log.v(TAG, "Launching activity "
2590 + r.activityInfo.name + " with config " + config);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002591 activity.attach(appContext, this, getInstrumentation(), r.token,
2592 r.ident, app, r.intent, r.activityInfo, title, r.parent,
2593 r.embeddedID, r.lastNonConfigurationInstance,
2594 r.lastNonConfigurationChildInstances, config);
Bob Leee5408332009-09-04 18:31:17 -07002595
Christopher Tateb70f3df2009-04-07 16:07:59 -07002596 if (customIntent != null) {
2597 activity.mIntent = customIntent;
2598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 r.lastNonConfigurationInstance = null;
2600 r.lastNonConfigurationChildInstances = null;
2601 activity.mStartedActivity = false;
2602 int theme = r.activityInfo.getThemeResource();
2603 if (theme != 0) {
2604 activity.setTheme(theme);
2605 }
2606
2607 activity.mCalled = false;
2608 mInstrumentation.callActivityOnCreate(activity, r.state);
2609 if (!activity.mCalled) {
2610 throw new SuperNotCalledException(
2611 "Activity " + r.intent.getComponent().toShortString() +
2612 " did not call through to super.onCreate()");
2613 }
2614 r.activity = activity;
2615 r.stopped = true;
2616 if (!r.activity.mFinished) {
2617 activity.performStart();
2618 r.stopped = false;
2619 }
2620 if (!r.activity.mFinished) {
2621 if (r.state != null) {
2622 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
2623 }
2624 }
2625 if (!r.activity.mFinished) {
2626 activity.mCalled = false;
2627 mInstrumentation.callActivityOnPostCreate(activity, r.state);
2628 if (!activity.mCalled) {
2629 throw new SuperNotCalledException(
2630 "Activity " + r.intent.getComponent().toShortString() +
2631 " did not call through to super.onPostCreate()");
2632 }
2633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 }
2635 r.paused = true;
2636
2637 mActivities.put(r.token, r);
2638
2639 } catch (SuperNotCalledException e) {
2640 throw e;
2641
2642 } catch (Exception e) {
2643 if (!mInstrumentation.onException(activity, e)) {
2644 throw new RuntimeException(
2645 "Unable to start activity " + component
2646 + ": " + e.toString(), e);
2647 }
2648 }
2649
2650 return activity;
2651 }
2652
Christopher Tateb70f3df2009-04-07 16:07:59 -07002653 private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 // If we are getting ready to gc after going to the background, well
2655 // we are back active so skip it.
2656 unscheduleGcIdler();
2657
2658 if (localLOGV) Log.v(
2659 TAG, "Handling launch of " + r);
Christopher Tateb70f3df2009-04-07 16:07:59 -07002660 Activity a = performLaunchActivity(r, customIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661
2662 if (a != null) {
Dianne Hackborn871ecdc2009-12-11 15:24:33 -08002663 r.createdConfig = new Configuration(mConfiguration);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08002664 Bundle oldState = r.state;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 handleResumeActivity(r.token, false, r.isForward);
2666
2667 if (!r.activity.mFinished && r.startsNotResumed) {
2668 // The activity manager actually wants this one to start out
2669 // paused, because it needs to be visible but isn't in the
2670 // foreground. We accomplish this by going through the
2671 // normal startup (because activities expect to go through
2672 // onResume() the first time they run, before their window
2673 // is displayed), and then pausing it. However, in this case
2674 // we do -not- need to do the full pause cycle (of freezing
2675 // and such) because the activity manager assumes it can just
2676 // retain the current state it has.
2677 try {
2678 r.activity.mCalled = false;
2679 mInstrumentation.callActivityOnPause(r.activity);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08002680 // We need to keep around the original state, in case
2681 // we need to be created again.
2682 r.state = oldState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 if (!r.activity.mCalled) {
2684 throw new SuperNotCalledException(
2685 "Activity " + r.intent.getComponent().toShortString() +
2686 " did not call through to super.onPause()");
2687 }
2688
2689 } catch (SuperNotCalledException e) {
2690 throw e;
2691
2692 } catch (Exception e) {
2693 if (!mInstrumentation.onException(r.activity, e)) {
2694 throw new RuntimeException(
2695 "Unable to pause activity "
2696 + r.intent.getComponent().toShortString()
2697 + ": " + e.toString(), e);
2698 }
2699 }
2700 r.paused = true;
2701 }
2702 } else {
2703 // If there was an error, for any reason, tell the activity
2704 // manager to stop us.
2705 try {
2706 ActivityManagerNative.getDefault()
2707 .finishActivity(r.token, Activity.RESULT_CANCELED, null);
2708 } catch (RemoteException ex) {
2709 }
2710 }
2711 }
2712
2713 private final void deliverNewIntents(ActivityRecord r,
2714 List<Intent> intents) {
2715 final int N = intents.size();
2716 for (int i=0; i<N; i++) {
2717 Intent intent = intents.get(i);
2718 intent.setExtrasClassLoader(r.activity.getClassLoader());
2719 mInstrumentation.callActivityOnNewIntent(r.activity, intent);
2720 }
2721 }
2722
2723 public final void performNewIntents(IBinder token,
2724 List<Intent> intents) {
2725 ActivityRecord r = mActivities.get(token);
2726 if (r != null) {
2727 final boolean resumed = !r.paused;
2728 if (resumed) {
2729 mInstrumentation.callActivityOnPause(r.activity);
2730 }
2731 deliverNewIntents(r, intents);
2732 if (resumed) {
2733 mInstrumentation.callActivityOnResume(r.activity);
2734 }
2735 }
2736 }
Bob Leee5408332009-09-04 18:31:17 -07002737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 private final void handleNewIntent(NewIntentData data) {
2739 performNewIntents(data.token, data.intents);
2740 }
2741
2742 private final void handleReceiver(ReceiverData data) {
2743 // If we are getting ready to gc after going to the background, well
2744 // we are back active so skip it.
2745 unscheduleGcIdler();
2746
2747 String component = data.intent.getComponent().getClassName();
2748
2749 PackageInfo packageInfo = getPackageInfoNoCheck(
2750 data.info.applicationInfo);
2751
2752 IActivityManager mgr = ActivityManagerNative.getDefault();
2753
2754 BroadcastReceiver receiver = null;
2755 try {
2756 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2757 data.intent.setExtrasClassLoader(cl);
2758 if (data.resultExtras != null) {
2759 data.resultExtras.setClassLoader(cl);
2760 }
2761 receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
2762 } catch (Exception e) {
2763 try {
2764 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
2765 data.resultData, data.resultExtras, data.resultAbort);
2766 } catch (RemoteException ex) {
2767 }
2768 throw new RuntimeException(
2769 "Unable to instantiate receiver " + component
2770 + ": " + e.toString(), e);
2771 }
2772
2773 try {
Dianne Hackborn0be1f782009-11-09 12:30:12 -08002774 Application app = packageInfo.makeApplication(false, mInstrumentation);
Bob Leee5408332009-09-04 18:31:17 -07002775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002776 if (localLOGV) Log.v(
2777 TAG, "Performing receive of " + data.intent
2778 + ": app=" + app
2779 + ", appName=" + app.getPackageName()
2780 + ", pkg=" + packageInfo.getPackageName()
2781 + ", comp=" + data.intent.getComponent().toShortString()
2782 + ", dir=" + packageInfo.getAppDir());
2783
Dianne Hackborn21556372010-02-04 16:34:40 -08002784 ContextImpl context = (ContextImpl)app.getBaseContext();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002785 receiver.setOrderedHint(true);
2786 receiver.setResult(data.resultCode, data.resultData,
2787 data.resultExtras);
2788 receiver.setOrderedHint(data.sync);
2789 receiver.onReceive(context.getReceiverRestrictedContext(),
2790 data.intent);
2791 } catch (Exception e) {
2792 try {
2793 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
2794 data.resultData, data.resultExtras, data.resultAbort);
2795 } catch (RemoteException ex) {
2796 }
2797 if (!mInstrumentation.onException(receiver, e)) {
2798 throw new RuntimeException(
2799 "Unable to start receiver " + component
2800 + ": " + e.toString(), e);
2801 }
2802 }
2803
2804 try {
2805 if (data.sync) {
2806 mgr.finishReceiver(
2807 mAppThread.asBinder(), receiver.getResultCode(),
2808 receiver.getResultData(), receiver.getResultExtras(false),
2809 receiver.getAbortBroadcast());
2810 } else {
2811 mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false);
2812 }
2813 } catch (RemoteException ex) {
2814 }
2815 }
2816
Christopher Tate181fafa2009-05-14 11:12:14 -07002817 // Instantiate a BackupAgent and tell it that it's alive
2818 private final void handleCreateBackupAgent(CreateBackupAgentData data) {
2819 if (DEBUG_BACKUP) Log.v(TAG, "handleCreateBackupAgent: " + data);
2820
2821 // no longer idle; we have backup work to do
2822 unscheduleGcIdler();
2823
2824 // instantiate the BackupAgent class named in the manifest
2825 PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
2826 String packageName = packageInfo.mPackageName;
2827 if (mBackupAgents.get(packageName) != null) {
2828 Log.d(TAG, "BackupAgent " + " for " + packageName
2829 + " already exists");
2830 return;
2831 }
Bob Leee5408332009-09-04 18:31:17 -07002832
Christopher Tate181fafa2009-05-14 11:12:14 -07002833 BackupAgent agent = null;
2834 String classname = data.appInfo.backupAgentName;
2835 if (classname == null) {
2836 if (data.backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08002837 Slog.e(TAG, "Attempted incremental backup but no defined agent for "
Christopher Tate181fafa2009-05-14 11:12:14 -07002838 + packageName);
2839 return;
2840 }
2841 classname = "android.app.FullBackupAgent";
2842 }
2843 try {
Christopher Tated1475e02009-07-09 15:36:17 -07002844 IBinder binder = null;
2845 try {
2846 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2847 agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance();
2848
2849 // set up the agent's context
2850 if (DEBUG_BACKUP) Log.v(TAG, "Initializing BackupAgent "
2851 + data.appInfo.backupAgentName);
2852
Dianne Hackborn21556372010-02-04 16:34:40 -08002853 ContextImpl context = new ContextImpl();
Christopher Tated1475e02009-07-09 15:36:17 -07002854 context.init(packageInfo, null, this);
2855 context.setOuterContext(agent);
2856 agent.attach(context);
2857
2858 agent.onCreate();
2859 binder = agent.onBind();
2860 mBackupAgents.put(packageName, agent);
2861 } catch (Exception e) {
2862 // If this is during restore, fail silently; otherwise go
2863 // ahead and let the user see the crash.
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08002864 Slog.e(TAG, "Agent threw during creation: " + e);
Christopher Tated1475e02009-07-09 15:36:17 -07002865 if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE) {
2866 throw e;
2867 }
2868 // falling through with 'binder' still null
2869 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002870
2871 // tell the OS that we're live now
Christopher Tate181fafa2009-05-14 11:12:14 -07002872 try {
2873 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
2874 } catch (RemoteException e) {
2875 // nothing to do.
2876 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002877 } catch (Exception e) {
2878 throw new RuntimeException("Unable to create BackupAgent "
2879 + data.appInfo.backupAgentName + ": " + e.toString(), e);
2880 }
2881 }
2882
2883 // Tear down a BackupAgent
2884 private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
2885 if (DEBUG_BACKUP) Log.v(TAG, "handleDestroyBackupAgent: " + data);
Bob Leee5408332009-09-04 18:31:17 -07002886
Christopher Tate181fafa2009-05-14 11:12:14 -07002887 PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
2888 String packageName = packageInfo.mPackageName;
2889 BackupAgent agent = mBackupAgents.get(packageName);
2890 if (agent != null) {
2891 try {
2892 agent.onDestroy();
2893 } catch (Exception e) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08002894 Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
Christopher Tate181fafa2009-05-14 11:12:14 -07002895 e.printStackTrace();
2896 }
2897 mBackupAgents.remove(packageName);
2898 } else {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08002899 Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
Christopher Tate181fafa2009-05-14 11:12:14 -07002900 }
2901 }
2902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 private final void handleCreateService(CreateServiceData data) {
2904 // If we are getting ready to gc after going to the background, well
2905 // we are back active so skip it.
2906 unscheduleGcIdler();
2907
2908 PackageInfo packageInfo = getPackageInfoNoCheck(
2909 data.info.applicationInfo);
2910 Service service = null;
2911 try {
2912 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2913 service = (Service) cl.loadClass(data.info.name).newInstance();
2914 } catch (Exception e) {
2915 if (!mInstrumentation.onException(service, e)) {
2916 throw new RuntimeException(
2917 "Unable to instantiate service " + data.info.name
2918 + ": " + e.toString(), e);
2919 }
2920 }
2921
2922 try {
2923 if (localLOGV) Log.v(TAG, "Creating service " + data.info.name);
2924
Dianne Hackborn21556372010-02-04 16:34:40 -08002925 ContextImpl context = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002926 context.init(packageInfo, null, this);
2927
Dianne Hackborn0be1f782009-11-09 12:30:12 -08002928 Application app = packageInfo.makeApplication(false, mInstrumentation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 context.setOuterContext(service);
2930 service.attach(context, this, data.info.name, data.token, app,
2931 ActivityManagerNative.getDefault());
2932 service.onCreate();
2933 mServices.put(data.token, service);
2934 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07002935 ActivityManagerNative.getDefault().serviceDoneExecuting(
2936 data.token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002937 } catch (RemoteException e) {
2938 // nothing to do.
2939 }
2940 } catch (Exception e) {
2941 if (!mInstrumentation.onException(service, e)) {
2942 throw new RuntimeException(
2943 "Unable to create service " + data.info.name
2944 + ": " + e.toString(), e);
2945 }
2946 }
2947 }
2948
2949 private final void handleBindService(BindServiceData data) {
2950 Service s = mServices.get(data.token);
2951 if (s != null) {
2952 try {
2953 data.intent.setExtrasClassLoader(s.getClassLoader());
2954 try {
2955 if (!data.rebind) {
2956 IBinder binder = s.onBind(data.intent);
2957 ActivityManagerNative.getDefault().publishService(
2958 data.token, data.intent, binder);
2959 } else {
2960 s.onRebind(data.intent);
2961 ActivityManagerNative.getDefault().serviceDoneExecuting(
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07002962 data.token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 }
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08002964 ensureJitEnabled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002965 } catch (RemoteException ex) {
2966 }
2967 } catch (Exception e) {
2968 if (!mInstrumentation.onException(s, e)) {
2969 throw new RuntimeException(
2970 "Unable to bind to service " + s
2971 + " with " + data.intent + ": " + e.toString(), e);
2972 }
2973 }
2974 }
2975 }
2976
2977 private final void handleUnbindService(BindServiceData data) {
2978 Service s = mServices.get(data.token);
2979 if (s != null) {
2980 try {
2981 data.intent.setExtrasClassLoader(s.getClassLoader());
2982 boolean doRebind = s.onUnbind(data.intent);
2983 try {
2984 if (doRebind) {
2985 ActivityManagerNative.getDefault().unbindFinished(
2986 data.token, data.intent, doRebind);
2987 } else {
2988 ActivityManagerNative.getDefault().serviceDoneExecuting(
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07002989 data.token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 }
2991 } catch (RemoteException ex) {
2992 }
2993 } catch (Exception e) {
2994 if (!mInstrumentation.onException(s, e)) {
2995 throw new RuntimeException(
2996 "Unable to unbind to service " + s
2997 + " with " + data.intent + ": " + e.toString(), e);
2998 }
2999 }
3000 }
3001 }
3002
3003 private void handleDumpService(DumpServiceInfo info) {
3004 try {
3005 Service s = mServices.get(info.service);
3006 if (s != null) {
3007 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
3008 s.dump(info.fd, pw, info.args);
3009 pw.close();
3010 }
3011 } finally {
3012 synchronized (info) {
3013 info.dumped = true;
3014 info.notifyAll();
3015 }
3016 }
3017 }
3018
3019 private final void handleServiceArgs(ServiceArgsData data) {
3020 Service s = mServices.get(data.token);
3021 if (s != null) {
3022 try {
3023 if (data.args != null) {
3024 data.args.setExtrasClassLoader(s.getClassLoader());
3025 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07003026 int res = s.onStartCommand(data.args, data.flags, data.startId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003027 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07003028 ActivityManagerNative.getDefault().serviceDoneExecuting(
3029 data.token, 1, data.startId, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003030 } catch (RemoteException e) {
3031 // nothing to do.
3032 }
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08003033 ensureJitEnabled();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 } catch (Exception e) {
3035 if (!mInstrumentation.onException(s, e)) {
3036 throw new RuntimeException(
3037 "Unable to start service " + s
3038 + " with " + data.args + ": " + e.toString(), e);
3039 }
3040 }
3041 }
3042 }
3043
3044 private final void handleStopService(IBinder token) {
3045 Service s = mServices.remove(token);
3046 if (s != null) {
3047 try {
3048 if (localLOGV) Log.v(TAG, "Destroying service " + s);
3049 s.onDestroy();
3050 Context context = s.getBaseContext();
Dianne Hackborn21556372010-02-04 16:34:40 -08003051 if (context instanceof ContextImpl) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 final String who = s.getClassName();
Dianne Hackborn21556372010-02-04 16:34:40 -08003053 ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 }
3055 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07003056 ActivityManagerNative.getDefault().serviceDoneExecuting(
3057 token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003058 } catch (RemoteException e) {
3059 // nothing to do.
3060 }
3061 } catch (Exception e) {
3062 if (!mInstrumentation.onException(s, e)) {
3063 throw new RuntimeException(
3064 "Unable to stop service " + s
3065 + ": " + e.toString(), e);
3066 }
3067 }
3068 }
3069 //Log.i(TAG, "Running services: " + mServices);
3070 }
3071
3072 public final ActivityRecord performResumeActivity(IBinder token,
3073 boolean clearHide) {
3074 ActivityRecord r = mActivities.get(token);
3075 if (localLOGV) Log.v(TAG, "Performing resume of " + r
3076 + " finished=" + r.activity.mFinished);
3077 if (r != null && !r.activity.mFinished) {
3078 if (clearHide) {
3079 r.hideForNow = false;
3080 r.activity.mStartedActivity = false;
3081 }
3082 try {
3083 if (r.pendingIntents != null) {
3084 deliverNewIntents(r, r.pendingIntents);
3085 r.pendingIntents = null;
3086 }
3087 if (r.pendingResults != null) {
3088 deliverResults(r, r.pendingResults);
3089 r.pendingResults = null;
3090 }
3091 r.activity.performResume();
3092
Bob Leee5408332009-09-04 18:31:17 -07003093 EventLog.writeEvent(LOG_ON_RESUME_CALLED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094 r.activity.getComponentName().getClassName());
Bob Leee5408332009-09-04 18:31:17 -07003095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003096 r.paused = false;
3097 r.stopped = false;
3098 if (r.activity.mStartedActivity) {
3099 r.hideForNow = true;
3100 }
3101 r.state = null;
3102 } catch (Exception e) {
3103 if (!mInstrumentation.onException(r.activity, e)) {
3104 throw new RuntimeException(
3105 "Unable to resume activity "
3106 + r.intent.getComponent().toShortString()
3107 + ": " + e.toString(), e);
3108 }
3109 }
3110 }
3111 return r;
3112 }
3113
3114 final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
3115 // If we are getting ready to gc after going to the background, well
3116 // we are back active so skip it.
3117 unscheduleGcIdler();
3118
3119 ActivityRecord r = performResumeActivity(token, clearHide);
3120
3121 if (r != null) {
3122 final Activity a = r.activity;
3123
3124 if (localLOGV) Log.v(
3125 TAG, "Resume " + r + " started activity: " +
3126 a.mStartedActivity + ", hideForNow: " + r.hideForNow
3127 + ", finished: " + a.mFinished);
3128
3129 final int forwardBit = isForward ?
3130 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
Bob Leee5408332009-09-04 18:31:17 -07003131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003132 // If the window hasn't yet been added to the window manager,
3133 // and this guy didn't finish itself or start another activity,
3134 // then go ahead and add the window.
3135 if (r.window == null && !a.mFinished && !a.mStartedActivity) {
3136 r.window = r.activity.getWindow();
3137 View decor = r.window.getDecorView();
3138 decor.setVisibility(View.INVISIBLE);
3139 ViewManager wm = a.getWindowManager();
3140 WindowManager.LayoutParams l = r.window.getAttributes();
3141 a.mDecor = decor;
3142 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
3143 l.softInputMode |= forwardBit;
3144 if (a.mVisibleFromClient) {
3145 a.mWindowAdded = true;
3146 wm.addView(decor, l);
3147 }
3148
3149 // If the window has already been added, but during resume
3150 // we started another activity, then don't yet make the
3151 // window visisble.
3152 } else if (a.mStartedActivity) {
3153 if (localLOGV) Log.v(
3154 TAG, "Launch " + r + " mStartedActivity set");
3155 r.hideForNow = true;
3156 }
3157
3158 // The window is now visible if it has been added, we are not
3159 // simply finishing, and we are not starting another activity.
Dianne Hackbornc1e605e2009-09-25 17:18:15 -07003160 if (!r.activity.mFinished && !a.mStartedActivity
3161 && r.activity.mDecor != null && !r.hideForNow) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 if (r.newConfig != null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003163 if (DEBUG_CONFIGURATION) Log.v(TAG, "Resuming activity "
3164 + r.activityInfo.name + " with newConfig " + r.newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 performConfigurationChanged(r.activity, r.newConfig);
3166 r.newConfig = null;
3167 }
3168 if (localLOGV) Log.v(TAG, "Resuming " + r + " with isForward="
3169 + isForward);
3170 WindowManager.LayoutParams l = r.window.getAttributes();
3171 if ((l.softInputMode
3172 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
3173 != forwardBit) {
3174 l.softInputMode = (l.softInputMode
3175 & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
3176 | forwardBit;
Dianne Hackbornc1e605e2009-09-25 17:18:15 -07003177 if (r.activity.mVisibleFromClient) {
3178 ViewManager wm = a.getWindowManager();
3179 View decor = r.window.getDecorView();
3180 wm.updateViewLayout(decor, l);
3181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003182 }
3183 r.activity.mVisibleFromServer = true;
3184 mNumVisibleActivities++;
3185 if (r.activity.mVisibleFromClient) {
3186 r.activity.makeVisible();
3187 }
3188 }
3189
3190 r.nextIdle = mNewActivities;
3191 mNewActivities = r;
3192 if (localLOGV) Log.v(
3193 TAG, "Scheduling idle handler for " + r);
3194 Looper.myQueue().addIdleHandler(new Idler());
3195
3196 } else {
3197 // If an exception was thrown when trying to resume, then
3198 // just end this activity.
3199 try {
3200 ActivityManagerNative.getDefault()
3201 .finishActivity(token, Activity.RESULT_CANCELED, null);
3202 } catch (RemoteException ex) {
3203 }
3204 }
3205 }
3206
3207 private int mThumbnailWidth = -1;
3208 private int mThumbnailHeight = -1;
3209
3210 private final Bitmap createThumbnailBitmap(ActivityRecord r) {
3211 Bitmap thumbnail = null;
3212 try {
3213 int w = mThumbnailWidth;
3214 int h;
3215 if (w < 0) {
3216 Resources res = r.activity.getResources();
3217 mThumbnailHeight = h =
3218 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
3219
3220 mThumbnailWidth = w =
3221 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
3222 } else {
3223 h = mThumbnailHeight;
3224 }
3225
3226 // XXX Only set hasAlpha if needed?
3227 thumbnail = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
3228 thumbnail.eraseColor(0);
3229 Canvas cv = new Canvas(thumbnail);
3230 if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
3231 thumbnail = null;
3232 }
3233 } catch (Exception e) {
3234 if (!mInstrumentation.onException(r.activity, e)) {
3235 throw new RuntimeException(
3236 "Unable to create thumbnail of "
3237 + r.intent.getComponent().toShortString()
3238 + ": " + e.toString(), e);
3239 }
3240 thumbnail = null;
3241 }
3242
3243 return thumbnail;
3244 }
3245
3246 private final void handlePauseActivity(IBinder token, boolean finished,
3247 boolean userLeaving, int configChanges) {
3248 ActivityRecord r = mActivities.get(token);
3249 if (r != null) {
3250 //Log.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
3251 if (userLeaving) {
3252 performUserLeavingActivity(r);
3253 }
Bob Leee5408332009-09-04 18:31:17 -07003254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 r.activity.mConfigChangeFlags |= configChanges;
3256 Bundle state = performPauseActivity(token, finished, true);
3257
3258 // Tell the activity manager we have paused.
3259 try {
3260 ActivityManagerNative.getDefault().activityPaused(token, state);
3261 } catch (RemoteException ex) {
3262 }
3263 }
3264 }
3265
3266 final void performUserLeavingActivity(ActivityRecord r) {
3267 mInstrumentation.callActivityOnUserLeaving(r.activity);
3268 }
3269
3270 final Bundle performPauseActivity(IBinder token, boolean finished,
3271 boolean saveState) {
3272 ActivityRecord r = mActivities.get(token);
3273 return r != null ? performPauseActivity(r, finished, saveState) : null;
3274 }
3275
3276 final Bundle performPauseActivity(ActivityRecord r, boolean finished,
3277 boolean saveState) {
3278 if (r.paused) {
3279 if (r.activity.mFinished) {
3280 // If we are finishing, we won't call onResume() in certain cases.
3281 // So here we likewise don't want to call onPause() if the activity
3282 // isn't resumed.
3283 return null;
3284 }
3285 RuntimeException e = new RuntimeException(
3286 "Performing pause of activity that is not resumed: "
3287 + r.intent.getComponent().toShortString());
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08003288 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 }
3290 Bundle state = null;
3291 if (finished) {
3292 r.activity.mFinished = true;
3293 }
3294 try {
3295 // Next have the activity save its current state and managed dialogs...
3296 if (!r.activity.mFinished && saveState) {
3297 state = new Bundle();
3298 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
3299 r.state = state;
3300 }
3301 // Now we are idle.
3302 r.activity.mCalled = false;
3303 mInstrumentation.callActivityOnPause(r.activity);
3304 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
3305 if (!r.activity.mCalled) {
3306 throw new SuperNotCalledException(
3307 "Activity " + r.intent.getComponent().toShortString() +
3308 " did not call through to super.onPause()");
3309 }
3310
3311 } catch (SuperNotCalledException e) {
3312 throw e;
3313
3314 } catch (Exception e) {
3315 if (!mInstrumentation.onException(r.activity, e)) {
3316 throw new RuntimeException(
3317 "Unable to pause activity "
3318 + r.intent.getComponent().toShortString()
3319 + ": " + e.toString(), e);
3320 }
3321 }
3322 r.paused = true;
3323 return state;
3324 }
3325
3326 final void performStopActivity(IBinder token) {
3327 ActivityRecord r = mActivities.get(token);
3328 performStopActivityInner(r, null, false);
3329 }
3330
3331 private static class StopInfo {
3332 Bitmap thumbnail;
3333 CharSequence description;
3334 }
3335
3336 private final class ProviderRefCount {
3337 public int count;
3338 ProviderRefCount(int pCount) {
3339 count = pCount;
3340 }
3341 }
3342
3343 private final void performStopActivityInner(ActivityRecord r,
3344 StopInfo info, boolean keepShown) {
3345 if (localLOGV) Log.v(TAG, "Performing stop of " + r);
3346 if (r != null) {
3347 if (!keepShown && r.stopped) {
3348 if (r.activity.mFinished) {
3349 // If we are finishing, we won't call onResume() in certain
3350 // cases. So here we likewise don't want to call onStop()
3351 // if the activity isn't resumed.
3352 return;
3353 }
3354 RuntimeException e = new RuntimeException(
3355 "Performing stop of activity that is not resumed: "
3356 + r.intent.getComponent().toShortString());
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08003357 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358 }
3359
3360 if (info != null) {
3361 try {
3362 // First create a thumbnail for the activity...
3363 //info.thumbnail = createThumbnailBitmap(r);
3364 info.description = r.activity.onCreateDescription();
3365 } catch (Exception e) {
3366 if (!mInstrumentation.onException(r.activity, e)) {
3367 throw new RuntimeException(
3368 "Unable to save state of activity "
3369 + r.intent.getComponent().toShortString()
3370 + ": " + e.toString(), e);
3371 }
3372 }
3373 }
3374
3375 if (!keepShown) {
3376 try {
3377 // Now we are idle.
3378 r.activity.performStop();
3379 } catch (Exception e) {
3380 if (!mInstrumentation.onException(r.activity, e)) {
3381 throw new RuntimeException(
3382 "Unable to stop activity "
3383 + r.intent.getComponent().toShortString()
3384 + ": " + e.toString(), e);
3385 }
3386 }
3387 r.stopped = true;
3388 }
3389
3390 r.paused = true;
3391 }
3392 }
3393
3394 private final void updateVisibility(ActivityRecord r, boolean show) {
3395 View v = r.activity.mDecor;
3396 if (v != null) {
3397 if (show) {
3398 if (!r.activity.mVisibleFromServer) {
3399 r.activity.mVisibleFromServer = true;
3400 mNumVisibleActivities++;
3401 if (r.activity.mVisibleFromClient) {
3402 r.activity.makeVisible();
3403 }
3404 }
3405 if (r.newConfig != null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003406 if (DEBUG_CONFIGURATION) Log.v(TAG, "Updating activity vis "
3407 + r.activityInfo.name + " with new config " + r.newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003408 performConfigurationChanged(r.activity, r.newConfig);
3409 r.newConfig = null;
3410 }
3411 } else {
3412 if (r.activity.mVisibleFromServer) {
3413 r.activity.mVisibleFromServer = false;
3414 mNumVisibleActivities--;
3415 v.setVisibility(View.INVISIBLE);
3416 }
3417 }
3418 }
3419 }
3420
3421 private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
3422 ActivityRecord r = mActivities.get(token);
3423 r.activity.mConfigChangeFlags |= configChanges;
3424
3425 StopInfo info = new StopInfo();
3426 performStopActivityInner(r, info, show);
3427
3428 if (localLOGV) Log.v(
3429 TAG, "Finishing stop of " + r + ": show=" + show
3430 + " win=" + r.window);
3431
3432 updateVisibility(r, show);
Bob Leee5408332009-09-04 18:31:17 -07003433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 // Tell activity manager we have been stopped.
3435 try {
3436 ActivityManagerNative.getDefault().activityStopped(
3437 r.token, info.thumbnail, info.description);
3438 } catch (RemoteException ex) {
3439 }
3440 }
3441
3442 final void performRestartActivity(IBinder token) {
3443 ActivityRecord r = mActivities.get(token);
3444 if (r.stopped) {
3445 r.activity.performRestart();
3446 r.stopped = false;
3447 }
3448 }
3449
3450 private final void handleWindowVisibility(IBinder token, boolean show) {
3451 ActivityRecord r = mActivities.get(token);
3452 if (!show && !r.stopped) {
3453 performStopActivityInner(r, null, show);
3454 } else if (show && r.stopped) {
3455 // If we are getting ready to gc after going to the background, well
3456 // we are back active so skip it.
3457 unscheduleGcIdler();
3458
3459 r.activity.performRestart();
3460 r.stopped = false;
3461 }
3462 if (r.activity.mDecor != null) {
3463 if (Config.LOGV) Log.v(
3464 TAG, "Handle window " + r + " visibility: " + show);
3465 updateVisibility(r, show);
3466 }
3467 }
3468
3469 private final void deliverResults(ActivityRecord r, List<ResultInfo> results) {
3470 final int N = results.size();
3471 for (int i=0; i<N; i++) {
3472 ResultInfo ri = results.get(i);
3473 try {
3474 if (ri.mData != null) {
3475 ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
3476 }
Chris Tate8a7dc172009-03-24 20:11:42 -07003477 if (DEBUG_RESULTS) Log.v(TAG,
3478 "Delivering result to activity " + r + " : " + ri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 r.activity.dispatchActivityResult(ri.mResultWho,
3480 ri.mRequestCode, ri.mResultCode, ri.mData);
3481 } catch (Exception e) {
3482 if (!mInstrumentation.onException(r.activity, e)) {
3483 throw new RuntimeException(
3484 "Failure delivering result " + ri + " to activity "
3485 + r.intent.getComponent().toShortString()
3486 + ": " + e.toString(), e);
3487 }
3488 }
3489 }
3490 }
3491
3492 private final void handleSendResult(ResultData res) {
3493 ActivityRecord r = mActivities.get(res.token);
Chris Tate8a7dc172009-03-24 20:11:42 -07003494 if (DEBUG_RESULTS) Log.v(TAG, "Handling send result to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 if (r != null) {
3496 final boolean resumed = !r.paused;
3497 if (!r.activity.mFinished && r.activity.mDecor != null
3498 && r.hideForNow && resumed) {
3499 // We had hidden the activity because it started another
3500 // one... we have gotten a result back and we are not
3501 // paused, so make sure our window is visible.
3502 updateVisibility(r, true);
3503 }
3504 if (resumed) {
3505 try {
3506 // Now we are idle.
3507 r.activity.mCalled = false;
3508 mInstrumentation.callActivityOnPause(r.activity);
3509 if (!r.activity.mCalled) {
3510 throw new SuperNotCalledException(
3511 "Activity " + r.intent.getComponent().toShortString()
3512 + " did not call through to super.onPause()");
3513 }
3514 } catch (SuperNotCalledException e) {
3515 throw e;
3516 } catch (Exception e) {
3517 if (!mInstrumentation.onException(r.activity, e)) {
3518 throw new RuntimeException(
3519 "Unable to pause activity "
3520 + r.intent.getComponent().toShortString()
3521 + ": " + e.toString(), e);
3522 }
3523 }
3524 }
3525 deliverResults(r, res.results);
3526 if (resumed) {
3527 mInstrumentation.callActivityOnResume(r.activity);
3528 }
3529 }
3530 }
3531
3532 public final ActivityRecord performDestroyActivity(IBinder token, boolean finishing) {
3533 return performDestroyActivity(token, finishing, 0, false);
3534 }
3535
3536 private final ActivityRecord performDestroyActivity(IBinder token, boolean finishing,
3537 int configChanges, boolean getNonConfigInstance) {
3538 ActivityRecord r = mActivities.get(token);
3539 if (localLOGV) Log.v(TAG, "Performing finish of " + r);
3540 if (r != null) {
3541 r.activity.mConfigChangeFlags |= configChanges;
3542 if (finishing) {
3543 r.activity.mFinished = true;
3544 }
3545 if (!r.paused) {
3546 try {
3547 r.activity.mCalled = false;
3548 mInstrumentation.callActivityOnPause(r.activity);
Bob Leee5408332009-09-04 18:31:17 -07003549 EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003550 r.activity.getComponentName().getClassName());
3551 if (!r.activity.mCalled) {
3552 throw new SuperNotCalledException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003553 "Activity " + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003554 + " did not call through to super.onPause()");
3555 }
3556 } catch (SuperNotCalledException e) {
3557 throw e;
3558 } catch (Exception e) {
3559 if (!mInstrumentation.onException(r.activity, e)) {
3560 throw new RuntimeException(
3561 "Unable to pause activity "
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003562 + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003563 + ": " + e.toString(), e);
3564 }
3565 }
3566 r.paused = true;
3567 }
3568 if (!r.stopped) {
3569 try {
3570 r.activity.performStop();
3571 } catch (SuperNotCalledException e) {
3572 throw e;
3573 } catch (Exception e) {
3574 if (!mInstrumentation.onException(r.activity, e)) {
3575 throw new RuntimeException(
3576 "Unable to stop activity "
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003577 + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 + ": " + e.toString(), e);
3579 }
3580 }
3581 r.stopped = true;
3582 }
3583 if (getNonConfigInstance) {
3584 try {
3585 r.lastNonConfigurationInstance
3586 = r.activity.onRetainNonConfigurationInstance();
3587 } catch (Exception e) {
3588 if (!mInstrumentation.onException(r.activity, e)) {
3589 throw new RuntimeException(
3590 "Unable to retain activity "
3591 + r.intent.getComponent().toShortString()
3592 + ": " + e.toString(), e);
3593 }
3594 }
3595 try {
3596 r.lastNonConfigurationChildInstances
3597 = r.activity.onRetainNonConfigurationChildInstances();
3598 } catch (Exception e) {
3599 if (!mInstrumentation.onException(r.activity, e)) {
3600 throw new RuntimeException(
3601 "Unable to retain child activities "
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003602 + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 + ": " + e.toString(), e);
3604 }
3605 }
Bob Leee5408332009-09-04 18:31:17 -07003606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 }
3608 try {
3609 r.activity.mCalled = false;
3610 r.activity.onDestroy();
3611 if (!r.activity.mCalled) {
3612 throw new SuperNotCalledException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003613 "Activity " + safeToComponentShortString(r.intent) +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 " did not call through to super.onDestroy()");
3615 }
3616 if (r.window != null) {
3617 r.window.closeAllPanels();
3618 }
3619 } catch (SuperNotCalledException e) {
3620 throw e;
3621 } catch (Exception e) {
3622 if (!mInstrumentation.onException(r.activity, e)) {
3623 throw new RuntimeException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003624 "Unable to destroy activity " + safeToComponentShortString(r.intent)
3625 + ": " + e.toString(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 }
3627 }
3628 }
3629 mActivities.remove(token);
3630
3631 return r;
3632 }
3633
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003634 private static String safeToComponentShortString(Intent intent) {
3635 ComponentName component = intent.getComponent();
3636 return component == null ? "[Unknown]" : component.toShortString();
3637 }
3638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003639 private final void handleDestroyActivity(IBinder token, boolean finishing,
3640 int configChanges, boolean getNonConfigInstance) {
3641 ActivityRecord r = performDestroyActivity(token, finishing,
3642 configChanges, getNonConfigInstance);
3643 if (r != null) {
3644 WindowManager wm = r.activity.getWindowManager();
3645 View v = r.activity.mDecor;
3646 if (v != null) {
3647 if (r.activity.mVisibleFromServer) {
3648 mNumVisibleActivities--;
3649 }
3650 IBinder wtoken = v.getWindowToken();
3651 if (r.activity.mWindowAdded) {
3652 wm.removeViewImmediate(v);
3653 }
3654 if (wtoken != null) {
3655 WindowManagerImpl.getDefault().closeAll(wtoken,
3656 r.activity.getClass().getName(), "Activity");
3657 }
3658 r.activity.mDecor = null;
3659 }
3660 WindowManagerImpl.getDefault().closeAll(token,
3661 r.activity.getClass().getName(), "Activity");
3662
3663 // Mocked out contexts won't be participating in the normal
3664 // process lifecycle, but if we're running with a proper
3665 // ApplicationContext we need to have it tear down things
3666 // cleanly.
3667 Context c = r.activity.getBaseContext();
Dianne Hackborn21556372010-02-04 16:34:40 -08003668 if (c instanceof ContextImpl) {
3669 ((ContextImpl) c).scheduleFinalCleanup(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003670 r.activity.getClass().getName(), "Activity");
3671 }
3672 }
3673 if (finishing) {
3674 try {
3675 ActivityManagerNative.getDefault().activityDestroyed(token);
3676 } catch (RemoteException ex) {
3677 // If the system process has died, it's game over for everyone.
3678 }
3679 }
3680 }
3681
3682 private final void handleRelaunchActivity(ActivityRecord tmp, int configChanges) {
3683 // If we are getting ready to gc after going to the background, well
3684 // we are back active so skip it.
3685 unscheduleGcIdler();
3686
3687 Configuration changedConfig = null;
Bob Leee5408332009-09-04 18:31:17 -07003688
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003689 if (DEBUG_CONFIGURATION) Log.v(TAG, "Relaunching activity "
3690 + tmp.token + " with configChanges=0x"
3691 + Integer.toHexString(configChanges));
3692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 // First: make sure we have the most recent configuration and most
3694 // recent version of the activity, or skip it if some previous call
3695 // had taken a more recent version.
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003696 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 int N = mRelaunchingActivities.size();
3698 IBinder token = tmp.token;
3699 tmp = null;
3700 for (int i=0; i<N; i++) {
3701 ActivityRecord r = mRelaunchingActivities.get(i);
3702 if (r.token == token) {
3703 tmp = r;
3704 mRelaunchingActivities.remove(i);
3705 i--;
3706 N--;
3707 }
3708 }
Bob Leee5408332009-09-04 18:31:17 -07003709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 if (tmp == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003711 if (DEBUG_CONFIGURATION) Log.v(TAG, "Abort, activity not relaunching!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712 return;
3713 }
Bob Leee5408332009-09-04 18:31:17 -07003714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003715 if (mPendingConfiguration != null) {
3716 changedConfig = mPendingConfiguration;
3717 mPendingConfiguration = null;
3718 }
3719 }
Bob Leee5408332009-09-04 18:31:17 -07003720
Dianne Hackborn871ecdc2009-12-11 15:24:33 -08003721 if (tmp.createdConfig != null) {
3722 // If the activity manager is passing us its current config,
3723 // assume that is really what we want regardless of what we
3724 // may have pending.
3725 if (mConfiguration == null
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003726 || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
3727 && mConfiguration.diff(tmp.createdConfig) != 0)) {
3728 if (changedConfig == null
3729 || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
3730 changedConfig = tmp.createdConfig;
3731 }
Dianne Hackborn871ecdc2009-12-11 15:24:33 -08003732 }
3733 }
3734
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003735 if (DEBUG_CONFIGURATION) Log.v(TAG, "Relaunching activity "
3736 + tmp.token + ": changedConfig=" + changedConfig);
3737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003738 // If there was a pending configuration change, execute it first.
3739 if (changedConfig != null) {
3740 handleConfigurationChanged(changedConfig);
3741 }
Bob Leee5408332009-09-04 18:31:17 -07003742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003743 ActivityRecord r = mActivities.get(tmp.token);
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003744 if (DEBUG_CONFIGURATION) Log.v(TAG, "Handling relaunch of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 if (r == null) {
3746 return;
3747 }
Bob Leee5408332009-09-04 18:31:17 -07003748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003749 r.activity.mConfigChangeFlags |= configChanges;
Christopher Tateb70f3df2009-04-07 16:07:59 -07003750 Intent currentIntent = r.activity.mIntent;
Bob Leee5408332009-09-04 18:31:17 -07003751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 Bundle savedState = null;
3753 if (!r.paused) {
3754 savedState = performPauseActivity(r.token, false, true);
3755 }
Bob Leee5408332009-09-04 18:31:17 -07003756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757 handleDestroyActivity(r.token, false, configChanges, true);
Bob Leee5408332009-09-04 18:31:17 -07003758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003759 r.activity = null;
3760 r.window = null;
3761 r.hideForNow = false;
3762 r.nextIdle = null;
The Android Open Source Project10592532009-03-18 17:39:46 -07003763 // Merge any pending results and pending intents; don't just replace them
3764 if (tmp.pendingResults != null) {
3765 if (r.pendingResults == null) {
3766 r.pendingResults = tmp.pendingResults;
3767 } else {
3768 r.pendingResults.addAll(tmp.pendingResults);
3769 }
3770 }
3771 if (tmp.pendingIntents != null) {
3772 if (r.pendingIntents == null) {
3773 r.pendingIntents = tmp.pendingIntents;
3774 } else {
3775 r.pendingIntents.addAll(tmp.pendingIntents);
3776 }
3777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 r.startsNotResumed = tmp.startsNotResumed;
3779 if (savedState != null) {
3780 r.state = savedState;
3781 }
Bob Leee5408332009-09-04 18:31:17 -07003782
Christopher Tateb70f3df2009-04-07 16:07:59 -07003783 handleLaunchActivity(r, currentIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784 }
3785
3786 private final void handleRequestThumbnail(IBinder token) {
3787 ActivityRecord r = mActivities.get(token);
3788 Bitmap thumbnail = createThumbnailBitmap(r);
3789 CharSequence description = null;
3790 try {
3791 description = r.activity.onCreateDescription();
3792 } catch (Exception e) {
3793 if (!mInstrumentation.onException(r.activity, e)) {
3794 throw new RuntimeException(
3795 "Unable to create description of activity "
3796 + r.intent.getComponent().toShortString()
3797 + ": " + e.toString(), e);
3798 }
3799 }
3800 //System.out.println("Reporting top thumbnail " + thumbnail);
3801 try {
3802 ActivityManagerNative.getDefault().reportThumbnail(
3803 token, thumbnail, description);
3804 } catch (RemoteException ex) {
3805 }
3806 }
3807
3808 ArrayList<ComponentCallbacks> collectComponentCallbacksLocked(
3809 boolean allActivities, Configuration newConfig) {
3810 ArrayList<ComponentCallbacks> callbacks
3811 = new ArrayList<ComponentCallbacks>();
Bob Leee5408332009-09-04 18:31:17 -07003812
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813 if (mActivities.size() > 0) {
3814 Iterator<ActivityRecord> it = mActivities.values().iterator();
3815 while (it.hasNext()) {
3816 ActivityRecord ar = it.next();
3817 Activity a = ar.activity;
3818 if (a != null) {
3819 if (!ar.activity.mFinished && (allActivities ||
3820 (a != null && !ar.paused))) {
3821 // If the activity is currently resumed, its configuration
3822 // needs to change right now.
3823 callbacks.add(a);
3824 } else if (newConfig != null) {
3825 // Otherwise, we will tell it about the change
3826 // the next time it is resumed or shown. Note that
3827 // the activity manager may, before then, decide the
3828 // activity needs to be destroyed to handle its new
3829 // configuration.
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003830 if (DEBUG_CONFIGURATION) Log.v(TAG, "Setting activity "
3831 + ar.activityInfo.name + " newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 ar.newConfig = newConfig;
3833 }
3834 }
3835 }
3836 }
3837 if (mServices.size() > 0) {
3838 Iterator<Service> it = mServices.values().iterator();
3839 while (it.hasNext()) {
3840 callbacks.add(it.next());
3841 }
3842 }
3843 synchronized (mProviderMap) {
3844 if (mLocalProviders.size() > 0) {
3845 Iterator<ProviderRecord> it = mLocalProviders.values().iterator();
3846 while (it.hasNext()) {
3847 callbacks.add(it.next().mLocalProvider);
3848 }
3849 }
3850 }
3851 final int N = mAllApplications.size();
3852 for (int i=0; i<N; i++) {
3853 callbacks.add(mAllApplications.get(i));
3854 }
Bob Leee5408332009-09-04 18:31:17 -07003855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003856 return callbacks;
3857 }
Bob Leee5408332009-09-04 18:31:17 -07003858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 private final void performConfigurationChanged(
3860 ComponentCallbacks cb, Configuration config) {
3861 // Only for Activity objects, check that they actually call up to their
3862 // superclass implementation. ComponentCallbacks is an interface, so
3863 // we check the runtime type and act accordingly.
3864 Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
3865 if (activity != null) {
3866 activity.mCalled = false;
3867 }
Bob Leee5408332009-09-04 18:31:17 -07003868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003869 boolean shouldChangeConfig = false;
3870 if ((activity == null) || (activity.mCurrentConfig == null)) {
3871 shouldChangeConfig = true;
3872 } else {
Bob Leee5408332009-09-04 18:31:17 -07003873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003874 // If the new config is the same as the config this Activity
3875 // is already running with then don't bother calling
3876 // onConfigurationChanged
3877 int diff = activity.mCurrentConfig.diff(config);
3878 if (diff != 0) {
Bob Leee5408332009-09-04 18:31:17 -07003879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003880 // If this activity doesn't handle any of the config changes
3881 // then don't bother calling onConfigurationChanged as we're
3882 // going to destroy it.
3883 if ((~activity.mActivityInfo.configChanges & diff) == 0) {
3884 shouldChangeConfig = true;
3885 }
3886 }
3887 }
Bob Leee5408332009-09-04 18:31:17 -07003888
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003889 if (DEBUG_CONFIGURATION) Log.v(TAG, "Config callback " + cb
3890 + ": shouldChangeConfig=" + shouldChangeConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003891 if (shouldChangeConfig) {
3892 cb.onConfigurationChanged(config);
Bob Leee5408332009-09-04 18:31:17 -07003893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 if (activity != null) {
3895 if (!activity.mCalled) {
3896 throw new SuperNotCalledException(
3897 "Activity " + activity.getLocalClassName() +
3898 " did not call through to super.onConfigurationChanged()");
3899 }
3900 activity.mConfigChangeFlags = 0;
3901 activity.mCurrentConfig = new Configuration(config);
3902 }
3903 }
3904 }
3905
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003906 final void applyConfigurationToResourcesLocked(Configuration config) {
3907 if (mResConfiguration == null) {
3908 mResConfiguration = new Configuration();
3909 }
3910 if (!mResConfiguration.isOtherSeqNewer(config)) {
3911 return;
3912 }
3913 mResConfiguration.updateFrom(config);
3914 DisplayMetrics dm = getDisplayMetricsLocked(true);
Bob Leee5408332009-09-04 18:31:17 -07003915
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003916 // set it for java, this also affects newly created Resources
3917 if (config.locale != null) {
3918 Locale.setDefault(config.locale);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003919 }
Bob Leee5408332009-09-04 18:31:17 -07003920
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003921 Resources.updateSystemConfiguration(config, dm);
Bob Leee5408332009-09-04 18:31:17 -07003922
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003923 ContextImpl.ApplicationPackageManager.configurationChanged();
3924 //Log.i(TAG, "Configuration changed in " + currentPackageName());
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003925
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003926 Iterator<WeakReference<Resources>> it =
3927 mActiveResources.values().iterator();
3928 //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
3929 // mActiveResources.entrySet().iterator();
3930 while (it.hasNext()) {
3931 WeakReference<Resources> v = it.next();
3932 Resources r = v.get();
3933 if (r != null) {
3934 r.updateConfiguration(config, dm);
3935 //Log.i(TAG, "Updated app resources " + v.getKey()
3936 // + " " + r + ": " + r.getConfiguration());
3937 } else {
3938 //Log.i(TAG, "Removing old resources " + v.getKey());
3939 it.remove();
3940 }
3941 }
3942 }
3943
3944 final void handleConfigurationChanged(Configuration config) {
3945
3946 ArrayList<ComponentCallbacks> callbacks = null;
3947
3948 synchronized (mPackages) {
3949 if (mPendingConfiguration != null) {
3950 if (!mPendingConfiguration.isOtherSeqNewer(config)) {
3951 config = mPendingConfiguration;
3952 }
3953 mPendingConfiguration = null;
3954 }
3955
3956 if (config == null) {
3957 return;
3958 }
3959
3960 if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle configuration changed: "
3961 + config);
3962
3963 applyConfigurationToResourcesLocked(config);
3964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003965 if (mConfiguration == null) {
3966 mConfiguration = new Configuration();
3967 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003968 if (!mConfiguration.isOtherSeqNewer(config)) {
3969 return;
3970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003971 mConfiguration.updateFrom(config);
Bob Leee5408332009-09-04 18:31:17 -07003972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003973 callbacks = collectComponentCallbacksLocked(false, config);
3974 }
Bob Leee5408332009-09-04 18:31:17 -07003975
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003976 if (callbacks != null) {
3977 final int N = callbacks.size();
3978 for (int i=0; i<N; i++) {
3979 performConfigurationChanged(callbacks.get(i), config);
3980 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003981 }
3982 }
3983
3984 final void handleActivityConfigurationChanged(IBinder token) {
3985 ActivityRecord r = mActivities.get(token);
3986 if (r == null || r.activity == null) {
3987 return;
3988 }
Bob Leee5408332009-09-04 18:31:17 -07003989
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003990 if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle activity config changed: "
3991 + r.activityInfo.name);
3992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 performConfigurationChanged(r.activity, mConfiguration);
3994 }
3995
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07003996 final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08003997 if (start) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08003998 try {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07003999 Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
4000 8 * 1024 * 1024, 0);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08004001 } catch (RuntimeException e) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08004002 Slog.w(TAG, "Profiling failed on path " + pcd.path
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08004003 + " -- can the process access this path?");
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07004004 } finally {
4005 try {
4006 pcd.fd.close();
4007 } catch (IOException e) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08004008 Slog.w(TAG, "Failure closing profile fd", e);
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07004009 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08004010 }
4011 } else {
4012 Debug.stopMethodTracing();
4013 }
4014 }
Bob Leee5408332009-09-04 18:31:17 -07004015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004016 final void handleLowMemory() {
4017 ArrayList<ComponentCallbacks> callbacks
4018 = new ArrayList<ComponentCallbacks>();
4019
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004020 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004021 callbacks = collectComponentCallbacksLocked(true, null);
4022 }
Bob Leee5408332009-09-04 18:31:17 -07004023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004024 final int N = callbacks.size();
4025 for (int i=0; i<N; i++) {
4026 callbacks.get(i).onLowMemory();
4027 }
4028
Chris Tatece229052009-03-25 16:44:52 -07004029 // Ask SQLite to free up as much memory as it can, mostly from its page caches.
4030 if (Process.myUid() != Process.SYSTEM_UID) {
4031 int sqliteReleased = SQLiteDatabase.releaseMemory();
4032 EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
4033 }
Bob Leee5408332009-09-04 18:31:17 -07004034
Mike Reedcaf0df12009-04-27 14:32:05 -04004035 // Ask graphics to free up as much as possible (font/image caches)
4036 Canvas.freeCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004037
4038 BinderInternal.forceGc("mem");
4039 }
4040
4041 private final void handleBindApplication(AppBindData data) {
4042 mBoundApplication = data;
4043 mConfiguration = new Configuration(data.config);
4044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004045 // send up app name; do this *before* waiting for debugger
Christopher Tate8ee038d2009-11-06 11:30:20 -08004046 Process.setArgV0(data.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004047 android.ddm.DdmHandleAppName.setAppName(data.processName);
4048
4049 /*
4050 * Before spawning a new process, reset the time zone to be the system time zone.
4051 * This needs to be done because the system time zone could have changed after the
4052 * the spawning of this process. Without doing this this process would have the incorrect
4053 * system time zone.
4054 */
4055 TimeZone.setDefault(null);
4056
4057 /*
4058 * Initialize the default locale in this process for the reasons we set the time zone.
4059 */
4060 Locale.setDefault(data.config.locale);
4061
Suchi Amalapurapuc9843292009-06-24 17:02:25 -07004062 /*
4063 * Update the system configuration since its preloaded and might not
4064 * reflect configuration changes. The configuration object passed
4065 * in AppBindData can be safely assumed to be up to date
4066 */
4067 Resources.getSystem().updateConfiguration(mConfiguration, null);
4068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004069 data.info = getPackageInfoNoCheck(data.appInfo);
4070
Dianne Hackborn96e240f2009-07-26 17:42:30 -07004071 /**
4072 * Switch this process to density compatibility mode if needed.
4073 */
4074 if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
4075 == 0) {
4076 Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
4077 }
Bob Leee5408332009-09-04 18:31:17 -07004078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004079 if (data.debugMode != IApplicationThread.DEBUG_OFF) {
4080 // XXX should have option to change the port.
4081 Debug.changeDebugPort(8100);
4082 if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
4083 Log.w(TAG, "Application " + data.info.getPackageName()
4084 + " is waiting for the debugger on port 8100...");
4085
4086 IActivityManager mgr = ActivityManagerNative.getDefault();
4087 try {
4088 mgr.showWaitingForDebugger(mAppThread, true);
4089 } catch (RemoteException ex) {
4090 }
4091
4092 Debug.waitForDebugger();
4093
4094 try {
4095 mgr.showWaitingForDebugger(mAppThread, false);
4096 } catch (RemoteException ex) {
4097 }
4098
4099 } else {
4100 Log.w(TAG, "Application " + data.info.getPackageName()
4101 + " can be debugged on port 8100...");
4102 }
4103 }
4104
4105 if (data.instrumentationName != null) {
Dianne Hackborn21556372010-02-04 16:34:40 -08004106 ContextImpl appContext = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 appContext.init(data.info, null, this);
4108 InstrumentationInfo ii = null;
4109 try {
4110 ii = appContext.getPackageManager().
4111 getInstrumentationInfo(data.instrumentationName, 0);
4112 } catch (PackageManager.NameNotFoundException e) {
4113 }
4114 if (ii == null) {
4115 throw new RuntimeException(
4116 "Unable to find instrumentation info for: "
4117 + data.instrumentationName);
4118 }
4119
4120 mInstrumentationAppDir = ii.sourceDir;
4121 mInstrumentationAppPackage = ii.packageName;
4122 mInstrumentedAppDir = data.info.getAppDir();
4123
4124 ApplicationInfo instrApp = new ApplicationInfo();
4125 instrApp.packageName = ii.packageName;
4126 instrApp.sourceDir = ii.sourceDir;
4127 instrApp.publicSourceDir = ii.publicSourceDir;
4128 instrApp.dataDir = ii.dataDir;
4129 PackageInfo pi = getPackageInfo(instrApp,
4130 appContext.getClassLoader(), false, true);
Dianne Hackborn21556372010-02-04 16:34:40 -08004131 ContextImpl instrContext = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 instrContext.init(pi, null, this);
4133
4134 try {
4135 java.lang.ClassLoader cl = instrContext.getClassLoader();
4136 mInstrumentation = (Instrumentation)
4137 cl.loadClass(data.instrumentationName.getClassName()).newInstance();
4138 } catch (Exception e) {
4139 throw new RuntimeException(
4140 "Unable to instantiate instrumentation "
4141 + data.instrumentationName + ": " + e.toString(), e);
4142 }
4143
4144 mInstrumentation.init(this, instrContext, appContext,
4145 new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
4146
4147 if (data.profileFile != null && !ii.handleProfiling) {
4148 data.handlingProfiling = true;
4149 File file = new File(data.profileFile);
4150 file.getParentFile().mkdirs();
4151 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
4152 }
4153
4154 try {
4155 mInstrumentation.onCreate(data.instrumentationArgs);
4156 }
4157 catch (Exception e) {
4158 throw new RuntimeException(
4159 "Exception thrown in onCreate() of "
4160 + data.instrumentationName + ": " + e.toString(), e);
4161 }
4162
4163 } else {
4164 mInstrumentation = new Instrumentation();
4165 }
4166
Christopher Tate181fafa2009-05-14 11:12:14 -07004167 // If the app is being launched for full backup or restore, bring it up in
4168 // a restricted environment with the base application class.
Dianne Hackborn0be1f782009-11-09 12:30:12 -08004169 Application app = data.info.makeApplication(data.restrictedBackupMode, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 mInitialApplication = app;
4171
4172 List<ProviderInfo> providers = data.providers;
4173 if (providers != null) {
4174 installContentProviders(app, providers);
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08004175 // For process that contain content providers, we want to
4176 // ensure that the JIT is enabled "at some point".
4177 mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004178 }
4179
4180 try {
4181 mInstrumentation.callApplicationOnCreate(app);
4182 } catch (Exception e) {
4183 if (!mInstrumentation.onException(app, e)) {
4184 throw new RuntimeException(
4185 "Unable to create application " + app.getClass().getName()
4186 + ": " + e.toString(), e);
4187 }
4188 }
4189 }
4190
4191 /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
4192 IActivityManager am = ActivityManagerNative.getDefault();
4193 if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) {
4194 Debug.stopMethodTracing();
4195 }
4196 //Log.i(TAG, "am: " + ActivityManagerNative.getDefault()
4197 // + ", app thr: " + mAppThread);
4198 try {
4199 am.finishInstrumentation(mAppThread, resultCode, results);
4200 } catch (RemoteException ex) {
4201 }
4202 }
4203
4204 private final void installContentProviders(
4205 Context context, List<ProviderInfo> providers) {
4206 final ArrayList<IActivityManager.ContentProviderHolder> results =
4207 new ArrayList<IActivityManager.ContentProviderHolder>();
4208
4209 Iterator<ProviderInfo> i = providers.iterator();
4210 while (i.hasNext()) {
4211 ProviderInfo cpi = i.next();
4212 StringBuilder buf = new StringBuilder(128);
4213 buf.append("Publishing provider ");
4214 buf.append(cpi.authority);
4215 buf.append(": ");
4216 buf.append(cpi.name);
4217 Log.i(TAG, buf.toString());
4218 IContentProvider cp = installProvider(context, null, cpi, false);
4219 if (cp != null) {
4220 IActivityManager.ContentProviderHolder cph =
4221 new IActivityManager.ContentProviderHolder(cpi);
4222 cph.provider = cp;
4223 results.add(cph);
4224 // Don't ever unload this provider from the process.
4225 synchronized(mProviderMap) {
4226 mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
4227 }
4228 }
4229 }
4230
4231 try {
4232 ActivityManagerNative.getDefault().publishContentProviders(
4233 getApplicationThread(), results);
4234 } catch (RemoteException ex) {
4235 }
4236 }
4237
4238 private final IContentProvider getProvider(Context context, String name) {
4239 synchronized(mProviderMap) {
4240 final ProviderRecord pr = mProviderMap.get(name);
4241 if (pr != null) {
4242 return pr.mProvider;
4243 }
4244 }
4245
4246 IActivityManager.ContentProviderHolder holder = null;
4247 try {
4248 holder = ActivityManagerNative.getDefault().getContentProvider(
4249 getApplicationThread(), name);
4250 } catch (RemoteException ex) {
4251 }
4252 if (holder == null) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08004253 Slog.e(TAG, "Failed to find provider info for " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 return null;
4255 }
4256 if (holder.permissionFailure != null) {
4257 throw new SecurityException("Permission " + holder.permissionFailure
4258 + " required for provider " + name);
4259 }
4260
4261 IContentProvider prov = installProvider(context, holder.provider,
4262 holder.info, true);
4263 //Log.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
4264 if (holder.noReleaseNeeded || holder.provider == null) {
4265 // We are not going to release the provider if it is an external
4266 // provider that doesn't care about being released, or if it is
4267 // a local provider running in this process.
4268 //Log.i(TAG, "*** NO RELEASE NEEDED");
4269 synchronized(mProviderMap) {
4270 mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
4271 }
4272 }
4273 return prov;
4274 }
4275
4276 public final IContentProvider acquireProvider(Context c, String name) {
4277 IContentProvider provider = getProvider(c, name);
4278 if(provider == null)
4279 return null;
4280 IBinder jBinder = provider.asBinder();
4281 synchronized(mProviderMap) {
4282 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4283 if(prc == null) {
4284 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
4285 } else {
4286 prc.count++;
4287 } //end else
4288 } //end synchronized
4289 return provider;
4290 }
4291
4292 public final boolean releaseProvider(IContentProvider provider) {
4293 if(provider == null) {
4294 return false;
4295 }
4296 IBinder jBinder = provider.asBinder();
4297 synchronized(mProviderMap) {
4298 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4299 if(prc == null) {
4300 if(localLOGV) Log.v(TAG, "releaseProvider::Weird shouldnt be here");
4301 return false;
4302 } else {
4303 prc.count--;
4304 if(prc.count == 0) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004305 // Schedule the actual remove asynchronously, since we
4306 // don't know the context this will be called in.
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004307 // TODO: it would be nice to post a delayed message, so
4308 // if we come back and need the same provider quickly
4309 // we will still have it available.
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004310 Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
4311 mH.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004312 } //end if
4313 } //end else
4314 } //end synchronized
4315 return true;
4316 }
4317
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004318 final void completeRemoveProvider(IContentProvider provider) {
4319 IBinder jBinder = provider.asBinder();
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004320 String name = null;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004321 synchronized(mProviderMap) {
4322 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4323 if(prc != null && prc.count == 0) {
4324 mProviderRefCountMap.remove(jBinder);
4325 //invoke removeProvider to dereference provider
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004326 name = removeProviderLocked(provider);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004327 }
4328 }
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004329
4330 if (name != null) {
4331 try {
4332 if(localLOGV) Log.v(TAG, "removeProvider::Invoking " +
4333 "ActivityManagerNative.removeContentProvider(" + name);
4334 ActivityManagerNative.getDefault().removeContentProvider(
4335 getApplicationThread(), name);
4336 } catch (RemoteException e) {
4337 //do nothing content provider object is dead any way
4338 } //end catch
4339 }
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004340 }
4341
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004342 public final String removeProviderLocked(IContentProvider provider) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004343 if (provider == null) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004344 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004345 }
4346 IBinder providerBinder = provider.asBinder();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004348 String name = null;
4349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 // remove the provider from mProviderMap
4351 Iterator<ProviderRecord> iter = mProviderMap.values().iterator();
4352 while (iter.hasNext()) {
4353 ProviderRecord pr = iter.next();
4354 IBinder myBinder = pr.mProvider.asBinder();
4355 if (myBinder == providerBinder) {
4356 //find if its published by this process itself
4357 if(pr.mLocalProvider != null) {
4358 if(localLOGV) Log.i(TAG, "removeProvider::found local provider returning");
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004359 return name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 }
4361 if(localLOGV) Log.v(TAG, "removeProvider::Not local provider Unlinking " +
4362 "death recipient");
4363 //content provider is in another process
4364 myBinder.unlinkToDeath(pr, 0);
4365 iter.remove();
4366 //invoke remove only once for the very first name seen
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004367 if(name == null) {
4368 name = pr.mName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 }
4370 } //end if myBinder
4371 } //end while iter
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004372
4373 return name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 }
4375
4376 final void removeDeadProvider(String name, IContentProvider provider) {
4377 synchronized(mProviderMap) {
4378 ProviderRecord pr = mProviderMap.get(name);
4379 if (pr.mProvider.asBinder() == provider.asBinder()) {
4380 Log.i(TAG, "Removing dead content provider: " + name);
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004381 ProviderRecord removed = mProviderMap.remove(name);
4382 if (removed != null) {
4383 removed.mProvider.asBinder().unlinkToDeath(removed, 0);
4384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 }
4386 }
4387 }
4388
4389 final void removeDeadProviderLocked(String name, IContentProvider provider) {
4390 ProviderRecord pr = mProviderMap.get(name);
4391 if (pr.mProvider.asBinder() == provider.asBinder()) {
4392 Log.i(TAG, "Removing dead content provider: " + name);
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004393 ProviderRecord removed = mProviderMap.remove(name);
4394 if (removed != null) {
4395 removed.mProvider.asBinder().unlinkToDeath(removed, 0);
4396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 }
4398 }
4399
4400 private final IContentProvider installProvider(Context context,
4401 IContentProvider provider, ProviderInfo info, boolean noisy) {
4402 ContentProvider localProvider = null;
4403 if (provider == null) {
4404 if (noisy) {
4405 Log.d(TAG, "Loading provider " + info.authority + ": "
4406 + info.name);
4407 }
4408 Context c = null;
4409 ApplicationInfo ai = info.applicationInfo;
4410 if (context.getPackageName().equals(ai.packageName)) {
4411 c = context;
4412 } else if (mInitialApplication != null &&
4413 mInitialApplication.getPackageName().equals(ai.packageName)) {
4414 c = mInitialApplication;
4415 } else {
4416 try {
4417 c = context.createPackageContext(ai.packageName,
4418 Context.CONTEXT_INCLUDE_CODE);
4419 } catch (PackageManager.NameNotFoundException e) {
4420 }
4421 }
4422 if (c == null) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08004423 Slog.w(TAG, "Unable to get context for package " +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 ai.packageName +
4425 " while loading content provider " +
4426 info.name);
4427 return null;
4428 }
4429 try {
4430 final java.lang.ClassLoader cl = c.getClassLoader();
4431 localProvider = (ContentProvider)cl.
4432 loadClass(info.name).newInstance();
4433 provider = localProvider.getIContentProvider();
4434 if (provider == null) {
Dianne Hackbornc9421ba2010-03-11 22:23:46 -08004435 Slog.e(TAG, "Failed to instantiate class " +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 info.name + " from sourceDir " +
4437 info.applicationInfo.sourceDir);
4438 return null;
4439 }
4440 if (Config.LOGV) Log.v(
4441 TAG, "Instantiating local provider " + info.name);
4442 // XXX Need to create the correct context for this provider.
4443 localProvider.attachInfo(c, info);
4444 } catch (java.lang.Exception e) {
4445 if (!mInstrumentation.onException(null, e)) {
4446 throw new RuntimeException(
4447 "Unable to get provider " + info.name
4448 + ": " + e.toString(), e);
4449 }
4450 return null;
4451 }
4452 } else if (localLOGV) {
4453 Log.v(TAG, "Installing external provider " + info.authority + ": "
4454 + info.name);
4455 }
4456
4457 synchronized (mProviderMap) {
4458 // Cache the pointer for the remote provider.
4459 String names[] = PATTERN_SEMICOLON.split(info.authority);
4460 for (int i=0; i<names.length; i++) {
4461 ProviderRecord pr = new ProviderRecord(names[i], provider,
4462 localProvider);
4463 try {
4464 provider.asBinder().linkToDeath(pr, 0);
4465 mProviderMap.put(names[i], pr);
4466 } catch (RemoteException e) {
4467 return null;
4468 }
4469 }
4470 if (localProvider != null) {
4471 mLocalProviders.put(provider.asBinder(),
4472 new ProviderRecord(null, provider, localProvider));
4473 }
4474 }
4475
4476 return provider;
4477 }
4478
4479 private final void attach(boolean system) {
4480 sThreadLocal.set(this);
4481 mSystemThread = system;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 if (!system) {
Dianne Hackborn2a9094d2010-02-03 19:20:09 -08004483 ViewRoot.addFirstDrawHandler(new Runnable() {
4484 public void run() {
4485 ensureJitEnabled();
4486 }
4487 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
4489 RuntimeInit.setApplicationObject(mAppThread.asBinder());
4490 IActivityManager mgr = ActivityManagerNative.getDefault();
4491 try {
4492 mgr.attachApplication(mAppThread);
4493 } catch (RemoteException ex) {
4494 }
4495 } else {
4496 // Don't set application object here -- if the system crashes,
4497 // we can't display an alert, we just want to die die die.
4498 android.ddm.DdmHandleAppName.setAppName("system_process");
4499 try {
4500 mInstrumentation = new Instrumentation();
Dianne Hackborn21556372010-02-04 16:34:40 -08004501 ContextImpl context = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502 context.init(getSystemContext().mPackageInfo, null, this);
4503 Application app = Instrumentation.newApplication(Application.class, context);
4504 mAllApplications.add(app);
4505 mInitialApplication = app;
4506 app.onCreate();
4507 } catch (Exception e) {
4508 throw new RuntimeException(
4509 "Unable to instantiate Application():" + e.toString(), e);
4510 }
4511 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004512
4513 ViewRoot.addConfigCallback(new ComponentCallbacks() {
4514 public void onConfigurationChanged(Configuration newConfig) {
4515 synchronized (mPackages) {
4516 if (mPendingConfiguration == null ||
4517 mPendingConfiguration.isOtherSeqNewer(newConfig)) {
4518 mPendingConfiguration = newConfig;
4519
4520 // We need to apply this change to the resources
4521 // immediately, because upon returning the view
4522 // hierarchy will be informed about it.
4523 applyConfigurationToResourcesLocked(newConfig);
4524 }
4525 }
4526 queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
4527 }
4528 public void onLowMemory() {
4529 }
4530 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004531 }
4532
4533 private final void detach()
4534 {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004535 sThreadLocal.set(null);
4536 }
4537
4538 public static final ActivityThread systemMain() {
4539 ActivityThread thread = new ActivityThread();
4540 thread.attach(true);
4541 return thread;
4542 }
4543
4544 public final void installSystemProviders(List providers) {
4545 if (providers != null) {
4546 installContentProviders(mInitialApplication,
4547 (List<ProviderInfo>)providers);
4548 }
4549 }
4550
4551 public static final void main(String[] args) {
Bob Leee5408332009-09-04 18:31:17 -07004552 SamplingProfilerIntegration.start();
4553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 Process.setArgV0("<pre-initialized>");
4555
4556 Looper.prepareMainLooper();
4557
4558 ActivityThread thread = new ActivityThread();
4559 thread.attach(false);
4560
4561 Looper.loop();
4562
4563 if (Process.supportsProcesses()) {
4564 throw new RuntimeException("Main thread loop unexpectedly exited");
4565 }
4566
4567 thread.detach();
Bob Leeeec2f412009-09-10 11:01:24 +02004568 String name = (thread.mInitialApplication != null)
4569 ? thread.mInitialApplication.getPackageName()
4570 : "<unknown>";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004571 Log.i(TAG, "Main thread of " + name + " is now exiting");
4572 }
4573}