blob: b4ac159ea4ceb8b9de20840c1e208ed27f21d2ce [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
19import android.content.BroadcastReceiver;
20import android.content.ComponentCallbacks;
21import android.content.ComponentName;
22import android.content.ContentProvider;
23import android.content.Context;
24import android.content.IContentProvider;
25import android.content.Intent;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070026import android.content.IIntentReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.content.ServiceConnection;
28import android.content.pm.ActivityInfo;
29import android.content.pm.ApplicationInfo;
30import android.content.pm.IPackageManager;
31import android.content.pm.InstrumentationInfo;
32import android.content.pm.PackageManager;
33import android.content.pm.ProviderInfo;
34import android.content.pm.ServiceInfo;
35import android.content.res.AssetManager;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -070036import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.content.res.Configuration;
38import android.content.res.Resources;
39import android.database.sqlite.SQLiteDatabase;
40import android.database.sqlite.SQLiteDebug;
41import android.graphics.Bitmap;
42import android.graphics.Canvas;
43import android.net.http.AndroidHttpClient;
44import android.os.Bundle;
45import android.os.Debug;
46import android.os.Handler;
47import android.os.IBinder;
48import android.os.Looper;
49import android.os.Message;
50import android.os.MessageQueue;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070051import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.os.Process;
53import android.os.RemoteException;
54import android.os.ServiceManager;
55import android.os.SystemClock;
56import android.util.AndroidRuntimeException;
57import android.util.Config;
58import android.util.DisplayMetrics;
59import android.util.EventLog;
60import android.util.Log;
61import android.view.Display;
62import android.view.View;
63import android.view.ViewDebug;
64import android.view.ViewManager;
65import android.view.Window;
66import android.view.WindowManager;
67import android.view.WindowManagerImpl;
68
69import com.android.internal.os.BinderInternal;
70import com.android.internal.os.RuntimeInit;
Bob Leee5408332009-09-04 18:31:17 -070071import com.android.internal.os.SamplingProfilerIntegration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import com.android.internal.util.ArrayUtils;
73
74import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
75
76import java.io.File;
77import java.io.FileDescriptor;
78import java.io.FileOutputStream;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070079import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import java.io.PrintWriter;
81import java.lang.ref.WeakReference;
82import java.util.ArrayList;
83import java.util.HashMap;
84import java.util.Iterator;
85import java.util.List;
86import java.util.Locale;
87import java.util.Map;
88import java.util.TimeZone;
89import java.util.regex.Pattern;
90
Bob Leee5408332009-09-04 18:31:17 -070091import dalvik.system.SamplingProfiler;
92
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093final class IntentReceiverLeaked extends AndroidRuntimeException {
94 public IntentReceiverLeaked(String msg) {
95 super(msg);
96 }
97}
98
99final class ServiceConnectionLeaked extends AndroidRuntimeException {
100 public ServiceConnectionLeaked(String msg) {
101 super(msg);
102 }
103}
104
105final class SuperNotCalledException extends AndroidRuntimeException {
106 public SuperNotCalledException(String msg) {
107 super(msg);
108 }
109}
110
111/**
112 * This manages the execution of the main thread in an
113 * application process, scheduling and executing activities,
114 * broadcasts, and other operations on it as the activity
115 * manager requests.
116 *
117 * {@hide}
118 */
119public final class ActivityThread {
120 private static final String TAG = "ActivityThread";
121 private static final boolean DEBUG = false;
122 private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
123 private static final boolean DEBUG_BROADCAST = false;
Chris Tate8a7dc172009-03-24 20:11:42 -0700124 private static final boolean DEBUG_RESULTS = false;
Christopher Tate436344a2009-09-30 16:17:37 -0700125 private static final boolean DEBUG_BACKUP = false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700126 private static final boolean DEBUG_CONFIGURATION = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
128 private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
129 private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
130 private static final int LOG_ON_PAUSE_CALLED = 30021;
131 private static final int LOG_ON_RESUME_CALLED = 30022;
132
Bob Leee5408332009-09-04 18:31:17 -0700133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 public static final ActivityThread currentActivityThread() {
135 return (ActivityThread)sThreadLocal.get();
136 }
137
138 public static final String currentPackageName()
139 {
140 ActivityThread am = currentActivityThread();
141 return (am != null && am.mBoundApplication != null)
142 ? am.mBoundApplication.processName : null;
143 }
144
145 public static IPackageManager getPackageManager() {
146 if (sPackageManager != null) {
147 //Log.v("PackageManager", "returning cur default = " + sPackageManager);
148 return sPackageManager;
149 }
150 IBinder b = ServiceManager.getService("package");
151 //Log.v("PackageManager", "default service binder = " + b);
152 sPackageManager = IPackageManager.Stub.asInterface(b);
153 //Log.v("PackageManager", "default service = " + sPackageManager);
154 return sPackageManager;
155 }
156
157 DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
158 if (mDisplayMetrics != null && !forceUpdate) {
159 return mDisplayMetrics;
160 }
161 if (mDisplay == null) {
162 WindowManager wm = WindowManagerImpl.getDefault();
163 mDisplay = wm.getDefaultDisplay();
164 }
165 DisplayMetrics metrics = mDisplayMetrics = new DisplayMetrics();
166 mDisplay.getMetrics(metrics);
167 //Log.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
168 // + metrics.heightPixels + " den=" + metrics.density
169 // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
170 return metrics;
171 }
172
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700173 /**
174 * Creates the top level Resources for applications with the given compatibility info.
175 *
176 * @param resDir the resource directory.
177 * @param compInfo the compability info. It will use the default compatibility info when it's
178 * null.
179 */
180 Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 synchronized (mPackages) {
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700182 // Resources is app scale dependent.
183 ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700184 if (false) {
185 Log.w(TAG, "getTopLevelResources: " + resDir + " / "
186 + compInfo.applicationScale);
187 }
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700188 WeakReference<Resources> wr = mActiveResources.get(key);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 Resources r = wr != null ? wr.get() : null;
190 if (r != null && r.getAssets().isUpToDate()) {
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700191 if (false) {
192 Log.w(TAG, "Returning cached resources " + r + " " + resDir
193 + ": appScale=" + r.getCompatibilityInfo().applicationScale);
194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 return r;
196 }
197
198 //if (r != null) {
199 // Log.w(TAG, "Throwing away out-of-date resources!!!! "
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700200 // + r + " " + resDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 //}
202
203 AssetManager assets = new AssetManager();
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700204 if (assets.addAssetPath(resDir) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 return null;
206 }
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700207
208 //Log.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700209 DisplayMetrics metrics = getDisplayMetricsLocked(false);
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700210 r = new Resources(assets, metrics, getConfiguration(), compInfo);
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700211 if (false) {
212 Log.i(TAG, "Created app resources " + resDir + " " + r + ": "
213 + r.getConfiguration() + " appScale="
214 + r.getCompatibilityInfo().applicationScale);
215 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 // XXX need to remove entries when weak references go away
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700217 mActiveResources.put(key, new WeakReference<Resources>(r));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 return r;
219 }
220 }
221
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700222 /**
223 * Creates the top level resources for the given package.
224 */
225 Resources getTopLevelResources(String resDir, PackageInfo pkgInfo) {
226 return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo);
227 }
228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 final Handler getHandler() {
230 return mH;
231 }
232
233 public final static class PackageInfo {
234
235 private final ActivityThread mActivityThread;
236 private final ApplicationInfo mApplicationInfo;
237 private final String mPackageName;
238 private final String mAppDir;
239 private final String mResDir;
240 private final String[] mSharedLibraries;
241 private final String mDataDir;
242 private final File mDataDirFile;
243 private final ClassLoader mBaseClassLoader;
244 private final boolean mSecurityViolation;
245 private final boolean mIncludeCode;
246 private Resources mResources;
247 private ClassLoader mClassLoader;
248 private Application mApplication;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700249 private CompatibilityInfo mCompatibilityInfo;
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
252 = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
253 private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mUnregisteredReceivers
254 = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
255 private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mServices
256 = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
257 private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mUnboundServices
258 = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
259
260 int mClientCount = 0;
261
262 public PackageInfo(ActivityThread activityThread, ApplicationInfo aInfo,
263 ActivityThread mainThread, ClassLoader baseLoader,
264 boolean securityViolation, boolean includeCode) {
265 mActivityThread = activityThread;
266 mApplicationInfo = aInfo;
267 mPackageName = aInfo.packageName;
268 mAppDir = aInfo.sourceDir;
269 mResDir = aInfo.uid == Process.myUid() ? aInfo.sourceDir
270 : aInfo.publicSourceDir;
271 mSharedLibraries = aInfo.sharedLibraryFiles;
272 mDataDir = aInfo.dataDir;
273 mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
274 mBaseClassLoader = baseLoader;
275 mSecurityViolation = securityViolation;
276 mIncludeCode = includeCode;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700277 mCompatibilityInfo = new CompatibilityInfo(aInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278
279 if (mAppDir == null) {
280 if (mSystemContext == null) {
281 mSystemContext =
282 ApplicationContext.createSystemContext(mainThread);
283 mSystemContext.getResources().updateConfiguration(
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700284 mainThread.getConfiguration(),
285 mainThread.getDisplayMetricsLocked(false));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 //Log.i(TAG, "Created system resources "
287 // + mSystemContext.getResources() + ": "
288 // + mSystemContext.getResources().getConfiguration());
289 }
290 mClassLoader = mSystemContext.getClassLoader();
291 mResources = mSystemContext.getResources();
292 }
293 }
294
295 public PackageInfo(ActivityThread activityThread, String name,
Mike Cleron432b7132009-09-24 15:28:29 -0700296 Context systemContext, ApplicationInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 mActivityThread = activityThread;
Mike Cleron432b7132009-09-24 15:28:29 -0700298 mApplicationInfo = info != null ? info : new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 mApplicationInfo.packageName = name;
300 mPackageName = name;
301 mAppDir = null;
302 mResDir = null;
303 mSharedLibraries = null;
304 mDataDir = null;
305 mDataDirFile = null;
306 mBaseClassLoader = null;
307 mSecurityViolation = false;
308 mIncludeCode = true;
309 mClassLoader = systemContext.getClassLoader();
310 mResources = systemContext.getResources();
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -0700311 mCompatibilityInfo = new CompatibilityInfo(mApplicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 }
313
314 public String getPackageName() {
315 return mPackageName;
316 }
317
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700318 public ApplicationInfo getApplicationInfo() {
319 return mApplicationInfo;
320 }
Bob Leee5408332009-09-04 18:31:17 -0700321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 public boolean isSecurityViolation() {
323 return mSecurityViolation;
324 }
325
326 /**
327 * Gets the array of shared libraries that are listed as
328 * used by the given package.
Bob Leee5408332009-09-04 18:31:17 -0700329 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 * @param packageName the name of the package (note: not its
331 * file name)
332 * @return null-ok; the array of shared libraries, each one
333 * a fully-qualified path
334 */
335 private static String[] getLibrariesFor(String packageName) {
336 ApplicationInfo ai = null;
337 try {
338 ai = getPackageManager().getApplicationInfo(packageName,
339 PackageManager.GET_SHARED_LIBRARY_FILES);
340 } catch (RemoteException e) {
341 throw new AssertionError(e);
342 }
343
344 if (ai == null) {
345 return null;
346 }
347
348 return ai.sharedLibraryFiles;
349 }
350
351 /**
352 * Combines two arrays (of library names) such that they are
353 * concatenated in order but are devoid of duplicates. The
354 * result is a single string with the names of the libraries
355 * separated by colons, or <code>null</code> if both lists
356 * were <code>null</code> or empty.
Bob Leee5408332009-09-04 18:31:17 -0700357 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 * @param list1 null-ok; the first list
359 * @param list2 null-ok; the second list
360 * @return null-ok; the combination
361 */
362 private static String combineLibs(String[] list1, String[] list2) {
363 StringBuilder result = new StringBuilder(300);
364 boolean first = true;
365
366 if (list1 != null) {
367 for (String s : list1) {
368 if (first) {
369 first = false;
370 } else {
371 result.append(':');
372 }
373 result.append(s);
374 }
375 }
376
377 // Only need to check for duplicates if list1 was non-empty.
378 boolean dupCheck = !first;
379
380 if (list2 != null) {
381 for (String s : list2) {
382 if (dupCheck && ArrayUtils.contains(list1, s)) {
383 continue;
384 }
Bob Leee5408332009-09-04 18:31:17 -0700385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 if (first) {
387 first = false;
388 } else {
389 result.append(':');
390 }
391 result.append(s);
392 }
393 }
394
395 return result.toString();
396 }
Bob Leee5408332009-09-04 18:31:17 -0700397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 public ClassLoader getClassLoader() {
399 synchronized (this) {
400 if (mClassLoader != null) {
401 return mClassLoader;
402 }
403
404 if (mIncludeCode && !mPackageName.equals("android")) {
405 String zip = mAppDir;
406
407 /*
408 * The following is a bit of a hack to inject
409 * instrumentation into the system: If the app
410 * being started matches one of the instrumentation names,
411 * then we combine both the "instrumentation" and
412 * "instrumented" app into the path, along with the
413 * concatenation of both apps' shared library lists.
414 */
415
416 String instrumentationAppDir =
417 mActivityThread.mInstrumentationAppDir;
418 String instrumentationAppPackage =
419 mActivityThread.mInstrumentationAppPackage;
420 String instrumentedAppDir =
421 mActivityThread.mInstrumentedAppDir;
422 String[] instrumentationLibs = null;
423
424 if (mAppDir.equals(instrumentationAppDir)
425 || mAppDir.equals(instrumentedAppDir)) {
426 zip = instrumentationAppDir + ":" + instrumentedAppDir;
427 if (! instrumentedAppDir.equals(instrumentationAppDir)) {
428 instrumentationLibs =
429 getLibrariesFor(instrumentationAppPackage);
430 }
431 }
432
433 if ((mSharedLibraries != null) ||
434 (instrumentationLibs != null)) {
Bob Leee5408332009-09-04 18:31:17 -0700435 zip =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 combineLibs(mSharedLibraries, instrumentationLibs)
437 + ':' + zip;
438 }
439
440 /*
441 * With all the combination done (if necessary, actually
442 * create the class loader.
443 */
444
445 if (localLOGV) Log.v(TAG, "Class path: " + zip);
446
447 mClassLoader =
448 ApplicationLoaders.getDefault().getClassLoader(
449 zip, mDataDir, mBaseClassLoader);
450 } else {
451 if (mBaseClassLoader == null) {
452 mClassLoader = ClassLoader.getSystemClassLoader();
453 } else {
454 mClassLoader = mBaseClassLoader;
455 }
456 }
457 return mClassLoader;
458 }
459 }
460
461 public String getAppDir() {
462 return mAppDir;
463 }
464
465 public String getResDir() {
466 return mResDir;
467 }
468
469 public String getDataDir() {
470 return mDataDir;
471 }
472
473 public File getDataDirFile() {
474 return mDataDirFile;
475 }
476
477 public AssetManager getAssets(ActivityThread mainThread) {
478 return getResources(mainThread).getAssets();
479 }
480
481 public Resources getResources(ActivityThread mainThread) {
482 if (mResources == null) {
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700483 mResources = mainThread.getTopLevelResources(mResDir, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 }
485 return mResources;
486 }
487
Christopher Tate181fafa2009-05-14 11:12:14 -0700488 public Application makeApplication(boolean forceDefaultAppClass) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 if (mApplication != null) {
490 return mApplication;
491 }
Bob Leee5408332009-09-04 18:31:17 -0700492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493 Application app = null;
Bob Leee5408332009-09-04 18:31:17 -0700494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 String appClass = mApplicationInfo.className;
Christopher Tate181fafa2009-05-14 11:12:14 -0700496 if (forceDefaultAppClass || (appClass == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 appClass = "android.app.Application";
498 }
499
500 try {
501 java.lang.ClassLoader cl = getClassLoader();
502 ApplicationContext appContext = new ApplicationContext();
503 appContext.init(this, null, mActivityThread);
504 app = mActivityThread.mInstrumentation.newApplication(
505 cl, appClass, appContext);
506 appContext.setOuterContext(app);
507 } catch (Exception e) {
508 if (!mActivityThread.mInstrumentation.onException(app, e)) {
509 throw new RuntimeException(
510 "Unable to instantiate application " + appClass
511 + ": " + e.toString(), e);
512 }
513 }
514 mActivityThread.mAllApplications.add(app);
515 return mApplication = app;
516 }
Bob Leee5408332009-09-04 18:31:17 -0700517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 public void removeContextRegistrations(Context context,
519 String who, String what) {
520 HashMap<BroadcastReceiver, ReceiverDispatcher> rmap =
521 mReceivers.remove(context);
522 if (rmap != null) {
523 Iterator<ReceiverDispatcher> it = rmap.values().iterator();
524 while (it.hasNext()) {
525 ReceiverDispatcher rd = it.next();
526 IntentReceiverLeaked leak = new IntentReceiverLeaked(
527 what + " " + who + " has leaked IntentReceiver "
528 + rd.getIntentReceiver() + " that was " +
529 "originally registered here. Are you missing a " +
530 "call to unregisterReceiver()?");
531 leak.setStackTrace(rd.getLocation().getStackTrace());
532 Log.e(TAG, leak.getMessage(), leak);
533 try {
534 ActivityManagerNative.getDefault().unregisterReceiver(
535 rd.getIIntentReceiver());
536 } catch (RemoteException e) {
537 // system crashed, nothing we can do
538 }
539 }
540 }
541 mUnregisteredReceivers.remove(context);
542 //Log.i(TAG, "Receiver registrations: " + mReceivers);
543 HashMap<ServiceConnection, ServiceDispatcher> smap =
544 mServices.remove(context);
545 if (smap != null) {
546 Iterator<ServiceDispatcher> it = smap.values().iterator();
547 while (it.hasNext()) {
548 ServiceDispatcher sd = it.next();
549 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
550 what + " " + who + " has leaked ServiceConnection "
551 + sd.getServiceConnection() + " that was originally bound here");
552 leak.setStackTrace(sd.getLocation().getStackTrace());
553 Log.e(TAG, leak.getMessage(), leak);
554 try {
555 ActivityManagerNative.getDefault().unbindService(
556 sd.getIServiceConnection());
557 } catch (RemoteException e) {
558 // system crashed, nothing we can do
559 }
560 sd.doForget();
561 }
562 }
563 mUnboundServices.remove(context);
564 //Log.i(TAG, "Service registrations: " + mServices);
565 }
566
567 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
568 Context context, Handler handler,
569 Instrumentation instrumentation, boolean registered) {
570 synchronized (mReceivers) {
571 ReceiverDispatcher rd = null;
572 HashMap<BroadcastReceiver, ReceiverDispatcher> map = null;
573 if (registered) {
574 map = mReceivers.get(context);
575 if (map != null) {
576 rd = map.get(r);
577 }
578 }
579 if (rd == null) {
580 rd = new ReceiverDispatcher(r, context, handler,
581 instrumentation, registered);
582 if (registered) {
583 if (map == null) {
584 map = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
585 mReceivers.put(context, map);
586 }
587 map.put(r, rd);
588 }
589 } else {
590 rd.validate(context, handler);
591 }
592 return rd.getIIntentReceiver();
593 }
594 }
595
596 public IIntentReceiver forgetReceiverDispatcher(Context context,
597 BroadcastReceiver r) {
598 synchronized (mReceivers) {
599 HashMap<BroadcastReceiver, ReceiverDispatcher> map = mReceivers.get(context);
600 ReceiverDispatcher rd = null;
601 if (map != null) {
602 rd = map.get(r);
603 if (rd != null) {
604 map.remove(r);
605 if (map.size() == 0) {
606 mReceivers.remove(context);
607 }
608 if (r.getDebugUnregister()) {
609 HashMap<BroadcastReceiver, ReceiverDispatcher> holder
610 = mUnregisteredReceivers.get(context);
611 if (holder == null) {
612 holder = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
613 mUnregisteredReceivers.put(context, holder);
614 }
615 RuntimeException ex = new IllegalArgumentException(
616 "Originally unregistered here:");
617 ex.fillInStackTrace();
618 rd.setUnregisterLocation(ex);
619 holder.put(r, rd);
620 }
621 return rd.getIIntentReceiver();
622 }
623 }
624 HashMap<BroadcastReceiver, ReceiverDispatcher> holder
625 = mUnregisteredReceivers.get(context);
626 if (holder != null) {
627 rd = holder.get(r);
628 if (rd != null) {
629 RuntimeException ex = rd.getUnregisterLocation();
630 throw new IllegalArgumentException(
631 "Unregistering Receiver " + r
632 + " that was already unregistered", ex);
633 }
634 }
635 if (context == null) {
636 throw new IllegalStateException("Unbinding Receiver " + r
637 + " from Context that is no longer in use: " + context);
638 } else {
639 throw new IllegalArgumentException("Receiver not registered: " + r);
640 }
641
642 }
643 }
644
645 static final class ReceiverDispatcher {
646
647 final static class InnerReceiver extends IIntentReceiver.Stub {
648 final WeakReference<ReceiverDispatcher> mDispatcher;
649 final ReceiverDispatcher mStrongRef;
Bob Leee5408332009-09-04 18:31:17 -0700650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 InnerReceiver(ReceiverDispatcher rd, boolean strong) {
652 mDispatcher = new WeakReference<ReceiverDispatcher>(rd);
653 mStrongRef = strong ? rd : null;
654 }
655 public void performReceive(Intent intent, int resultCode,
656 String data, Bundle extras, boolean ordered) {
657 ReceiverDispatcher rd = mDispatcher.get();
658 if (DEBUG_BROADCAST) {
659 int seq = intent.getIntExtra("seq", -1);
660 Log.i(TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
661 + " to " + rd);
662 }
663 if (rd != null) {
664 rd.performReceive(intent, resultCode, data, extras, ordered);
665 }
666 }
667 }
Bob Leee5408332009-09-04 18:31:17 -0700668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 final IIntentReceiver.Stub mIIntentReceiver;
670 final BroadcastReceiver mReceiver;
671 final Context mContext;
672 final Handler mActivityThread;
673 final Instrumentation mInstrumentation;
674 final boolean mRegistered;
675 final IntentReceiverLeaked mLocation;
676 RuntimeException mUnregisterLocation;
677
678 final class Args implements Runnable {
679 private Intent mCurIntent;
680 private int mCurCode;
681 private String mCurData;
682 private Bundle mCurMap;
683 private boolean mCurOrdered;
684
685 public void run() {
686 BroadcastReceiver receiver = mReceiver;
687 if (DEBUG_BROADCAST) {
688 int seq = mCurIntent.getIntExtra("seq", -1);
689 Log.i(TAG, "Dispathing broadcast " + mCurIntent.getAction() + " seq=" + seq
690 + " to " + mReceiver);
691 }
692 if (receiver == null) {
693 return;
694 }
695
696 IActivityManager mgr = ActivityManagerNative.getDefault();
697 Intent intent = mCurIntent;
698 mCurIntent = null;
699 try {
700 ClassLoader cl = mReceiver.getClass().getClassLoader();
701 intent.setExtrasClassLoader(cl);
702 if (mCurMap != null) {
703 mCurMap.setClassLoader(cl);
704 }
705 receiver.setOrderedHint(true);
706 receiver.setResult(mCurCode, mCurData, mCurMap);
707 receiver.clearAbortBroadcast();
708 receiver.setOrderedHint(mCurOrdered);
709 receiver.onReceive(mContext, intent);
710 } catch (Exception e) {
711 if (mRegistered && mCurOrdered) {
712 try {
713 mgr.finishReceiver(mIIntentReceiver,
714 mCurCode, mCurData, mCurMap, false);
715 } catch (RemoteException ex) {
716 }
717 }
718 if (mInstrumentation == null ||
719 !mInstrumentation.onException(mReceiver, e)) {
720 throw new RuntimeException(
721 "Error receiving broadcast " + intent
722 + " in " + mReceiver, e);
723 }
724 }
725 if (mRegistered && mCurOrdered) {
726 try {
727 mgr.finishReceiver(mIIntentReceiver,
728 receiver.getResultCode(),
729 receiver.getResultData(),
730 receiver.getResultExtras(false),
731 receiver.getAbortBroadcast());
732 } catch (RemoteException ex) {
733 }
734 }
735 }
736 }
737
738 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
739 Handler activityThread, Instrumentation instrumentation,
740 boolean registered) {
741 if (activityThread == null) {
742 throw new NullPointerException("Handler must not be null");
743 }
744
745 mIIntentReceiver = new InnerReceiver(this, !registered);
746 mReceiver = receiver;
747 mContext = context;
748 mActivityThread = activityThread;
749 mInstrumentation = instrumentation;
750 mRegistered = registered;
751 mLocation = new IntentReceiverLeaked(null);
752 mLocation.fillInStackTrace();
753 }
754
755 void validate(Context context, Handler activityThread) {
756 if (mContext != context) {
757 throw new IllegalStateException(
758 "Receiver " + mReceiver +
759 " registered with differing Context (was " +
760 mContext + " now " + context + ")");
761 }
762 if (mActivityThread != activityThread) {
763 throw new IllegalStateException(
764 "Receiver " + mReceiver +
765 " registered with differing handler (was " +
766 mActivityThread + " now " + activityThread + ")");
767 }
768 }
769
770 IntentReceiverLeaked getLocation() {
771 return mLocation;
772 }
773
774 BroadcastReceiver getIntentReceiver() {
775 return mReceiver;
776 }
Bob Leee5408332009-09-04 18:31:17 -0700777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 IIntentReceiver getIIntentReceiver() {
779 return mIIntentReceiver;
780 }
781
782 void setUnregisterLocation(RuntimeException ex) {
783 mUnregisterLocation = ex;
784 }
785
786 RuntimeException getUnregisterLocation() {
787 return mUnregisterLocation;
788 }
789
790 public void performReceive(Intent intent, int resultCode,
791 String data, Bundle extras, boolean ordered) {
792 if (DEBUG_BROADCAST) {
793 int seq = intent.getIntExtra("seq", -1);
794 Log.i(TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
795 + " to " + mReceiver);
796 }
797 Args args = new Args();
798 args.mCurIntent = intent;
799 args.mCurCode = resultCode;
800 args.mCurData = data;
801 args.mCurMap = extras;
802 args.mCurOrdered = ordered;
803 if (!mActivityThread.post(args)) {
804 if (mRegistered) {
805 IActivityManager mgr = ActivityManagerNative.getDefault();
806 try {
807 mgr.finishReceiver(mIIntentReceiver, args.mCurCode,
808 args.mCurData, args.mCurMap, false);
809 } catch (RemoteException ex) {
810 }
811 }
812 }
813 }
814
815 }
816
817 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
818 Context context, Handler handler, int flags) {
819 synchronized (mServices) {
820 ServiceDispatcher sd = null;
821 HashMap<ServiceConnection, ServiceDispatcher> map = mServices.get(context);
822 if (map != null) {
823 sd = map.get(c);
824 }
825 if (sd == null) {
826 sd = new ServiceDispatcher(c, context, handler, flags);
827 if (map == null) {
828 map = new HashMap<ServiceConnection, ServiceDispatcher>();
829 mServices.put(context, map);
830 }
831 map.put(c, sd);
832 } else {
833 sd.validate(context, handler);
834 }
835 return sd.getIServiceConnection();
836 }
837 }
838
839 public final IServiceConnection forgetServiceDispatcher(Context context,
840 ServiceConnection c) {
841 synchronized (mServices) {
842 HashMap<ServiceConnection, ServiceDispatcher> map
843 = mServices.get(context);
844 ServiceDispatcher sd = null;
845 if (map != null) {
846 sd = map.get(c);
847 if (sd != null) {
848 map.remove(c);
849 sd.doForget();
850 if (map.size() == 0) {
851 mServices.remove(context);
852 }
853 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
854 HashMap<ServiceConnection, ServiceDispatcher> holder
855 = mUnboundServices.get(context);
856 if (holder == null) {
857 holder = new HashMap<ServiceConnection, ServiceDispatcher>();
858 mUnboundServices.put(context, holder);
859 }
860 RuntimeException ex = new IllegalArgumentException(
861 "Originally unbound here:");
862 ex.fillInStackTrace();
863 sd.setUnbindLocation(ex);
864 holder.put(c, sd);
865 }
866 return sd.getIServiceConnection();
867 }
868 }
869 HashMap<ServiceConnection, ServiceDispatcher> holder
870 = mUnboundServices.get(context);
871 if (holder != null) {
872 sd = holder.get(c);
873 if (sd != null) {
874 RuntimeException ex = sd.getUnbindLocation();
875 throw new IllegalArgumentException(
876 "Unbinding Service " + c
877 + " that was already unbound", ex);
878 }
879 }
880 if (context == null) {
881 throw new IllegalStateException("Unbinding Service " + c
882 + " from Context that is no longer in use: " + context);
883 } else {
884 throw new IllegalArgumentException("Service not registered: " + c);
885 }
886 }
887 }
888
889 static final class ServiceDispatcher {
890 private final InnerConnection mIServiceConnection;
891 private final ServiceConnection mConnection;
892 private final Context mContext;
893 private final Handler mActivityThread;
894 private final ServiceConnectionLeaked mLocation;
895 private final int mFlags;
896
897 private RuntimeException mUnbindLocation;
898
899 private boolean mDied;
900
901 private static class ConnectionInfo {
902 IBinder binder;
903 IBinder.DeathRecipient deathMonitor;
904 }
905
906 private static class InnerConnection extends IServiceConnection.Stub {
907 final WeakReference<ServiceDispatcher> mDispatcher;
Bob Leee5408332009-09-04 18:31:17 -0700908
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 InnerConnection(ServiceDispatcher sd) {
910 mDispatcher = new WeakReference<ServiceDispatcher>(sd);
911 }
912
913 public void connected(ComponentName name, IBinder service) throws RemoteException {
914 ServiceDispatcher sd = mDispatcher.get();
915 if (sd != null) {
916 sd.connected(name, service);
917 }
918 }
919 }
Bob Leee5408332009-09-04 18:31:17 -0700920
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 private final HashMap<ComponentName, ConnectionInfo> mActiveConnections
922 = new HashMap<ComponentName, ConnectionInfo>();
923
924 ServiceDispatcher(ServiceConnection conn,
925 Context context, Handler activityThread, int flags) {
926 mIServiceConnection = new InnerConnection(this);
927 mConnection = conn;
928 mContext = context;
929 mActivityThread = activityThread;
930 mLocation = new ServiceConnectionLeaked(null);
931 mLocation.fillInStackTrace();
932 mFlags = flags;
933 }
934
935 void validate(Context context, Handler activityThread) {
936 if (mContext != context) {
937 throw new RuntimeException(
938 "ServiceConnection " + mConnection +
939 " registered with differing Context (was " +
940 mContext + " now " + context + ")");
941 }
942 if (mActivityThread != activityThread) {
943 throw new RuntimeException(
944 "ServiceConnection " + mConnection +
945 " registered with differing handler (was " +
946 mActivityThread + " now " + activityThread + ")");
947 }
948 }
949
950 void doForget() {
951 synchronized(this) {
952 Iterator<ConnectionInfo> it = mActiveConnections.values().iterator();
953 while (it.hasNext()) {
954 ConnectionInfo ci = it.next();
955 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
956 }
957 mActiveConnections.clear();
958 }
959 }
960
961 ServiceConnectionLeaked getLocation() {
962 return mLocation;
963 }
964
965 ServiceConnection getServiceConnection() {
966 return mConnection;
967 }
968
969 IServiceConnection getIServiceConnection() {
970 return mIServiceConnection;
971 }
Bob Leee5408332009-09-04 18:31:17 -0700972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 int getFlags() {
974 return mFlags;
975 }
976
977 void setUnbindLocation(RuntimeException ex) {
978 mUnbindLocation = ex;
979 }
980
981 RuntimeException getUnbindLocation() {
982 return mUnbindLocation;
983 }
984
985 public void connected(ComponentName name, IBinder service) {
986 if (mActivityThread != null) {
987 mActivityThread.post(new RunConnection(name, service, 0));
988 } else {
989 doConnected(name, service);
990 }
991 }
992
993 public void death(ComponentName name, IBinder service) {
994 ConnectionInfo old;
995
996 synchronized (this) {
997 mDied = true;
998 old = mActiveConnections.remove(name);
999 if (old == null || old.binder != service) {
1000 // Death for someone different than who we last
1001 // reported... just ignore it.
1002 return;
1003 }
1004 old.binder.unlinkToDeath(old.deathMonitor, 0);
1005 }
1006
1007 if (mActivityThread != null) {
1008 mActivityThread.post(new RunConnection(name, service, 1));
1009 } else {
1010 doDeath(name, service);
1011 }
1012 }
1013
1014 public void doConnected(ComponentName name, IBinder service) {
1015 ConnectionInfo old;
1016 ConnectionInfo info;
1017
1018 synchronized (this) {
1019 old = mActiveConnections.get(name);
1020 if (old != null && old.binder == service) {
1021 // Huh, already have this one. Oh well!
1022 return;
1023 }
1024
1025 if (service != null) {
1026 // A new service is being connected... set it all up.
1027 mDied = false;
1028 info = new ConnectionInfo();
1029 info.binder = service;
1030 info.deathMonitor = new DeathMonitor(name, service);
1031 try {
1032 service.linkToDeath(info.deathMonitor, 0);
1033 mActiveConnections.put(name, info);
1034 } catch (RemoteException e) {
1035 // This service was dead before we got it... just
1036 // don't do anything with it.
1037 mActiveConnections.remove(name);
1038 return;
1039 }
1040
1041 } else {
1042 // The named service is being disconnected... clean up.
1043 mActiveConnections.remove(name);
1044 }
1045
1046 if (old != null) {
1047 old.binder.unlinkToDeath(old.deathMonitor, 0);
1048 }
1049 }
1050
1051 // If there was an old service, it is not disconnected.
1052 if (old != null) {
1053 mConnection.onServiceDisconnected(name);
1054 }
1055 // If there is a new service, it is now connected.
1056 if (service != null) {
1057 mConnection.onServiceConnected(name, service);
1058 }
1059 }
1060
1061 public void doDeath(ComponentName name, IBinder service) {
1062 mConnection.onServiceDisconnected(name);
1063 }
1064
1065 private final class RunConnection implements Runnable {
1066 RunConnection(ComponentName name, IBinder service, int command) {
1067 mName = name;
1068 mService = service;
1069 mCommand = command;
1070 }
1071
1072 public void run() {
1073 if (mCommand == 0) {
1074 doConnected(mName, mService);
1075 } else if (mCommand == 1) {
1076 doDeath(mName, mService);
1077 }
1078 }
1079
1080 final ComponentName mName;
1081 final IBinder mService;
1082 final int mCommand;
1083 }
1084
1085 private final class DeathMonitor implements IBinder.DeathRecipient
1086 {
1087 DeathMonitor(ComponentName name, IBinder service) {
1088 mName = name;
1089 mService = service;
1090 }
1091
1092 public void binderDied() {
1093 death(mName, mService);
1094 }
1095
1096 final ComponentName mName;
1097 final IBinder mService;
1098 }
1099 }
1100 }
1101
1102 private static ApplicationContext mSystemContext = null;
1103
1104 private static final class ActivityRecord {
1105 IBinder token;
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001106 int ident;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 Intent intent;
1108 Bundle state;
1109 Activity activity;
1110 Window window;
1111 Activity parent;
1112 String embeddedID;
1113 Object lastNonConfigurationInstance;
1114 HashMap<String,Object> lastNonConfigurationChildInstances;
1115 boolean paused;
1116 boolean stopped;
1117 boolean hideForNow;
1118 Configuration newConfig;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001119 Configuration createdConfig;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 ActivityRecord nextIdle;
1121
1122 ActivityInfo activityInfo;
1123 PackageInfo packageInfo;
1124
1125 List<ResultInfo> pendingResults;
1126 List<Intent> pendingIntents;
1127
1128 boolean startsNotResumed;
1129 boolean isForward;
1130
1131 ActivityRecord() {
1132 parent = null;
1133 embeddedID = null;
1134 paused = false;
1135 stopped = false;
1136 hideForNow = false;
1137 nextIdle = null;
1138 }
1139
1140 public String toString() {
1141 ComponentName componentName = intent.getComponent();
1142 return "ActivityRecord{"
1143 + Integer.toHexString(System.identityHashCode(this))
1144 + " token=" + token + " " + (componentName == null
1145 ? "no component name" : componentName.toShortString())
1146 + "}";
1147 }
1148 }
1149
1150 private final class ProviderRecord implements IBinder.DeathRecipient {
1151 final String mName;
1152 final IContentProvider mProvider;
1153 final ContentProvider mLocalProvider;
1154
1155 ProviderRecord(String name, IContentProvider provider,
1156 ContentProvider localProvider) {
1157 mName = name;
1158 mProvider = provider;
1159 mLocalProvider = localProvider;
1160 }
1161
1162 public void binderDied() {
1163 removeDeadProvider(mName, mProvider);
1164 }
1165 }
1166
1167 private static final class NewIntentData {
1168 List<Intent> intents;
1169 IBinder token;
1170 public String toString() {
1171 return "NewIntentData{intents=" + intents + " token=" + token + "}";
1172 }
1173 }
1174
1175 private static final class ReceiverData {
1176 Intent intent;
1177 ActivityInfo info;
1178 int resultCode;
1179 String resultData;
1180 Bundle resultExtras;
1181 boolean sync;
1182 boolean resultAbort;
1183 public String toString() {
1184 return "ReceiverData{intent=" + intent + " packageName=" +
1185 info.packageName + " resultCode=" + resultCode
1186 + " resultData=" + resultData + " resultExtras=" + resultExtras + "}";
1187 }
1188 }
1189
Christopher Tate181fafa2009-05-14 11:12:14 -07001190 private static final class CreateBackupAgentData {
1191 ApplicationInfo appInfo;
1192 int backupMode;
1193 public String toString() {
1194 return "CreateBackupAgentData{appInfo=" + appInfo
1195 + " backupAgent=" + appInfo.backupAgentName
1196 + " mode=" + backupMode + "}";
1197 }
1198 }
Bob Leee5408332009-09-04 18:31:17 -07001199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 private static final class CreateServiceData {
1201 IBinder token;
1202 ServiceInfo info;
1203 Intent intent;
1204 public String toString() {
1205 return "CreateServiceData{token=" + token + " className="
1206 + info.name + " packageName=" + info.packageName
1207 + " intent=" + intent + "}";
1208 }
1209 }
1210
1211 private static final class BindServiceData {
1212 IBinder token;
1213 Intent intent;
1214 boolean rebind;
1215 public String toString() {
1216 return "BindServiceData{token=" + token + " intent=" + intent + "}";
1217 }
1218 }
1219
1220 private static final class ServiceArgsData {
1221 IBinder token;
1222 int startId;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07001223 int flags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 Intent args;
1225 public String toString() {
1226 return "ServiceArgsData{token=" + token + " startId=" + startId
1227 + " args=" + args + "}";
1228 }
1229 }
1230
1231 private static final class AppBindData {
1232 PackageInfo info;
1233 String processName;
1234 ApplicationInfo appInfo;
1235 List<ProviderInfo> providers;
1236 ComponentName instrumentationName;
1237 String profileFile;
1238 Bundle instrumentationArgs;
1239 IInstrumentationWatcher instrumentationWatcher;
1240 int debugMode;
Christopher Tate181fafa2009-05-14 11:12:14 -07001241 boolean restrictedBackupMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242 Configuration config;
1243 boolean handlingProfiling;
1244 public String toString() {
1245 return "AppBindData{appInfo=" + appInfo + "}";
1246 }
1247 }
1248
1249 private static final class DumpServiceInfo {
1250 FileDescriptor fd;
1251 IBinder service;
1252 String[] args;
1253 boolean dumped;
1254 }
1255
1256 private static final class ResultData {
1257 IBinder token;
1258 List<ResultInfo> results;
1259 public String toString() {
1260 return "ResultData{token=" + token + " results" + results + "}";
1261 }
1262 }
1263
1264 private static final class ContextCleanupInfo {
1265 ApplicationContext context;
1266 String what;
1267 String who;
1268 }
1269
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07001270 private static final class ProfilerControlData {
1271 String path;
1272 ParcelFileDescriptor fd;
1273 }
1274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 private final class ApplicationThread extends ApplicationThreadNative {
1276 private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
1277 private static final String ONE_COUNT_COLUMN = "%17s %8d";
1278 private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
Bob Leee5408332009-09-04 18:31:17 -07001279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001280 // Formatting for checkin service - update version if row format changes
1281 private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
Bob Leee5408332009-09-04 18:31:17 -07001282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283 public final void schedulePauseActivity(IBinder token, boolean finished,
1284 boolean userLeaving, int configChanges) {
1285 queueOrSendMessage(
1286 finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
1287 token,
1288 (userLeaving ? 1 : 0),
1289 configChanges);
1290 }
1291
1292 public final void scheduleStopActivity(IBinder token, boolean showWindow,
1293 int configChanges) {
1294 queueOrSendMessage(
1295 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
1296 token, 0, configChanges);
1297 }
1298
1299 public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
1300 queueOrSendMessage(
1301 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
1302 token);
1303 }
1304
1305 public final void scheduleResumeActivity(IBinder token, boolean isForward) {
1306 queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
1307 }
1308
1309 public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
1310 ResultData res = new ResultData();
1311 res.token = token;
1312 res.results = results;
1313 queueOrSendMessage(H.SEND_RESULT, res);
1314 }
1315
1316 // we use token to identify this activity without having to send the
1317 // activity itself back to the activity manager. (matters more with ipc)
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001318 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
1320 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
1321 ActivityRecord r = new ActivityRecord();
1322
1323 r.token = token;
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001324 r.ident = ident;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325 r.intent = intent;
1326 r.activityInfo = info;
1327 r.state = state;
1328
1329 r.pendingResults = pendingResults;
1330 r.pendingIntents = pendingNewIntents;
1331
1332 r.startsNotResumed = notResumed;
1333 r.isForward = isForward;
1334
1335 queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
1336 }
1337
1338 public final void scheduleRelaunchActivity(IBinder token,
1339 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
1340 int configChanges, boolean notResumed) {
1341 ActivityRecord r = new ActivityRecord();
1342
1343 r.token = token;
1344 r.pendingResults = pendingResults;
1345 r.pendingIntents = pendingNewIntents;
1346 r.startsNotResumed = notResumed;
1347
1348 synchronized (mRelaunchingActivities) {
1349 mRelaunchingActivities.add(r);
1350 }
Bob Leee5408332009-09-04 18:31:17 -07001351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges);
1353 }
1354
1355 public final void scheduleNewIntent(List<Intent> intents, IBinder token) {
1356 NewIntentData data = new NewIntentData();
1357 data.intents = intents;
1358 data.token = token;
1359
1360 queueOrSendMessage(H.NEW_INTENT, data);
1361 }
1362
1363 public final void scheduleDestroyActivity(IBinder token, boolean finishing,
1364 int configChanges) {
1365 queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
1366 configChanges);
1367 }
1368
1369 public final void scheduleReceiver(Intent intent, ActivityInfo info,
1370 int resultCode, String data, Bundle extras, boolean sync) {
1371 ReceiverData r = new ReceiverData();
1372
1373 r.intent = intent;
1374 r.info = info;
1375 r.resultCode = resultCode;
1376 r.resultData = data;
1377 r.resultExtras = extras;
1378 r.sync = sync;
1379
1380 queueOrSendMessage(H.RECEIVER, r);
1381 }
1382
Christopher Tate181fafa2009-05-14 11:12:14 -07001383 public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) {
1384 CreateBackupAgentData d = new CreateBackupAgentData();
1385 d.appInfo = app;
1386 d.backupMode = backupMode;
1387
1388 queueOrSendMessage(H.CREATE_BACKUP_AGENT, d);
1389 }
1390
1391 public final void scheduleDestroyBackupAgent(ApplicationInfo app) {
1392 CreateBackupAgentData d = new CreateBackupAgentData();
1393 d.appInfo = app;
1394
1395 queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d);
1396 }
1397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 public final void scheduleCreateService(IBinder token,
1399 ServiceInfo info) {
1400 CreateServiceData s = new CreateServiceData();
1401 s.token = token;
1402 s.info = info;
1403
1404 queueOrSendMessage(H.CREATE_SERVICE, s);
1405 }
1406
1407 public final void scheduleBindService(IBinder token, Intent intent,
1408 boolean rebind) {
1409 BindServiceData s = new BindServiceData();
1410 s.token = token;
1411 s.intent = intent;
1412 s.rebind = rebind;
1413
1414 queueOrSendMessage(H.BIND_SERVICE, s);
1415 }
1416
1417 public final void scheduleUnbindService(IBinder token, Intent intent) {
1418 BindServiceData s = new BindServiceData();
1419 s.token = token;
1420 s.intent = intent;
1421
1422 queueOrSendMessage(H.UNBIND_SERVICE, s);
1423 }
1424
1425 public final void scheduleServiceArgs(IBinder token, int startId,
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07001426 int flags ,Intent args) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 ServiceArgsData s = new ServiceArgsData();
1428 s.token = token;
1429 s.startId = startId;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07001430 s.flags = flags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431 s.args = args;
1432
1433 queueOrSendMessage(H.SERVICE_ARGS, s);
1434 }
1435
1436 public final void scheduleStopService(IBinder token) {
1437 queueOrSendMessage(H.STOP_SERVICE, token);
1438 }
1439
1440 public final void bindApplication(String processName,
1441 ApplicationInfo appInfo, List<ProviderInfo> providers,
1442 ComponentName instrumentationName, String profileFile,
1443 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
Christopher Tate181fafa2009-05-14 11:12:14 -07001444 int debugMode, boolean isRestrictedBackupMode, Configuration config,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 Map<String, IBinder> services) {
1446 Process.setArgV0(processName);
1447
1448 if (services != null) {
1449 // Setup the service cache in the ServiceManager
1450 ServiceManager.initServiceCache(services);
1451 }
1452
1453 AppBindData data = new AppBindData();
1454 data.processName = processName;
1455 data.appInfo = appInfo;
1456 data.providers = providers;
1457 data.instrumentationName = instrumentationName;
1458 data.profileFile = profileFile;
1459 data.instrumentationArgs = instrumentationArgs;
1460 data.instrumentationWatcher = instrumentationWatcher;
1461 data.debugMode = debugMode;
Christopher Tate181fafa2009-05-14 11:12:14 -07001462 data.restrictedBackupMode = isRestrictedBackupMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 data.config = config;
1464 queueOrSendMessage(H.BIND_APPLICATION, data);
1465 }
1466
1467 public final void scheduleExit() {
1468 queueOrSendMessage(H.EXIT_APPLICATION, null);
1469 }
1470
Christopher Tate5e1ab332009-09-01 20:32:49 -07001471 public final void scheduleSuicide() {
1472 queueOrSendMessage(H.SUICIDE, null);
1473 }
1474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 public void requestThumbnail(IBinder token) {
1476 queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
1477 }
1478
1479 public void scheduleConfigurationChanged(Configuration config) {
1480 synchronized (mRelaunchingActivities) {
1481 mPendingConfiguration = config;
1482 }
1483 queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
1484 }
1485
1486 public void updateTimeZone() {
1487 TimeZone.setDefault(null);
1488 }
1489
1490 public void processInBackground() {
1491 mH.removeMessages(H.GC_WHEN_IDLE);
1492 mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
1493 }
1494
1495 public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
1496 DumpServiceInfo data = new DumpServiceInfo();
1497 data.fd = fd;
1498 data.service = servicetoken;
1499 data.args = args;
1500 data.dumped = false;
1501 queueOrSendMessage(H.DUMP_SERVICE, data);
1502 synchronized (data) {
1503 while (!data.dumped) {
1504 try {
1505 data.wait();
1506 } catch (InterruptedException e) {
1507 // no need to do anything here, we will keep waiting until
1508 // dumped is set
1509 }
1510 }
1511 }
1512 }
1513
1514 // This function exists to make sure all receiver dispatching is
1515 // correctly ordered, since these are one-way calls and the binder driver
1516 // applies transaction ordering per object for such calls.
1517 public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
1518 int resultCode, String dataStr, Bundle extras, boolean ordered)
1519 throws RemoteException {
1520 receiver.performReceive(intent, resultCode, dataStr, extras, ordered);
1521 }
Bob Leee5408332009-09-04 18:31:17 -07001522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 public void scheduleLowMemory() {
1524 queueOrSendMessage(H.LOW_MEMORY, null);
1525 }
1526
1527 public void scheduleActivityConfigurationChanged(IBinder token) {
1528 queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
1529 }
1530
1531 public void requestPss() {
1532 try {
1533 ActivityManagerNative.getDefault().reportPss(this,
1534 (int)Process.getPss(Process.myPid()));
1535 } catch (RemoteException e) {
1536 }
1537 }
Bob Leee5408332009-09-04 18:31:17 -07001538
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07001539 public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
1540 ProfilerControlData pcd = new ProfilerControlData();
1541 pcd.path = path;
1542 pcd.fd = fd;
1543 queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001544 }
1545
Dianne Hackborn06de2ea2009-05-21 12:56:43 -07001546 public void setSchedulingGroup(int group) {
1547 // Note: do this immediately, since going into the foreground
1548 // should happen regardless of what pending work we have to do
1549 // and the activity manager will wait for us to report back that
1550 // we are done before sending us to the background.
1551 try {
1552 Process.setProcessGroup(Process.myPid(), group);
1553 } catch (Exception e) {
1554 Log.w(TAG, "Failed setting process group to " + group, e);
1555 }
1556 }
Bob Leee5408332009-09-04 18:31:17 -07001557
Dianne Hackborn3025ef32009-08-31 21:31:47 -07001558 public void getMemoryInfo(Debug.MemoryInfo outInfo) {
1559 Debug.getMemoryInfo(outInfo);
1560 }
Bob Leee5408332009-09-04 18:31:17 -07001561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 @Override
1563 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1564 long nativeMax = Debug.getNativeHeapSize() / 1024;
1565 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
1566 long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
1567
1568 Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
1569 Debug.getMemoryInfo(memInfo);
1570
1571 final int nativeShared = memInfo.nativeSharedDirty;
1572 final int dalvikShared = memInfo.dalvikSharedDirty;
1573 final int otherShared = memInfo.otherSharedDirty;
1574
1575 final int nativePrivate = memInfo.nativePrivateDirty;
1576 final int dalvikPrivate = memInfo.dalvikPrivateDirty;
1577 final int otherPrivate = memInfo.otherPrivateDirty;
1578
1579 Runtime runtime = Runtime.getRuntime();
1580
1581 long dalvikMax = runtime.totalMemory() / 1024;
1582 long dalvikFree = runtime.freeMemory() / 1024;
1583 long dalvikAllocated = dalvikMax - dalvikFree;
1584 long viewInstanceCount = ViewDebug.getViewInstanceCount();
1585 long viewRootInstanceCount = ViewDebug.getViewRootInstanceCount();
1586 long appContextInstanceCount = ApplicationContext.getInstanceCount();
1587 long activityInstanceCount = Activity.getInstanceCount();
1588 int globalAssetCount = AssetManager.getGlobalAssetCount();
1589 int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
1590 int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
1591 int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
1592 int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
1593 int openSslSocketCount = OpenSSLSocketImpl.getInstanceCount();
1594 long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024;
1595 SQLiteDebug.PagerStats stats = new SQLiteDebug.PagerStats();
1596 SQLiteDebug.getPagerStats(stats);
Bob Leee5408332009-09-04 18:31:17 -07001597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 // Check to see if we were called by checkin server. If so, print terse format.
1599 boolean doCheckinFormat = false;
1600 if (args != null) {
1601 for (String arg : args) {
1602 if ("-c".equals(arg)) doCheckinFormat = true;
1603 }
1604 }
Bob Leee5408332009-09-04 18:31:17 -07001605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 // For checkin, we print one long comma-separated list of values
1607 if (doCheckinFormat) {
1608 // NOTE: if you change anything significant below, also consider changing
1609 // ACTIVITY_THREAD_CHECKIN_VERSION.
Bob Leee5408332009-09-04 18:31:17 -07001610 String processName = (mBoundApplication != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 ? mBoundApplication.processName : "unknown";
Bob Leee5408332009-09-04 18:31:17 -07001612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 // Header
1614 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
1615 pw.print(Process.myPid()); pw.print(',');
1616 pw.print(processName); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 // Heap info - max
1619 pw.print(nativeMax); pw.print(',');
1620 pw.print(dalvikMax); pw.print(',');
1621 pw.print("N/A,");
1622 pw.print(nativeMax + dalvikMax); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 // Heap info - allocated
1625 pw.print(nativeAllocated); pw.print(',');
1626 pw.print(dalvikAllocated); pw.print(',');
1627 pw.print("N/A,");
1628 pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 // Heap info - free
1631 pw.print(nativeFree); pw.print(',');
1632 pw.print(dalvikFree); pw.print(',');
1633 pw.print("N/A,");
1634 pw.print(nativeFree + dalvikFree); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 // Heap info - proportional set size
1637 pw.print(memInfo.nativePss); pw.print(',');
1638 pw.print(memInfo.dalvikPss); pw.print(',');
1639 pw.print(memInfo.otherPss); pw.print(',');
1640 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 // Heap info - shared
Bob Leee5408332009-09-04 18:31:17 -07001643 pw.print(nativeShared); pw.print(',');
1644 pw.print(dalvikShared); pw.print(',');
1645 pw.print(otherShared); pw.print(',');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 pw.print(nativeShared + dalvikShared + otherShared); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 // Heap info - private
Bob Leee5408332009-09-04 18:31:17 -07001649 pw.print(nativePrivate); pw.print(',');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 pw.print(dalvikPrivate); pw.print(',');
1651 pw.print(otherPrivate); pw.print(',');
1652 pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 // Object counts
1655 pw.print(viewInstanceCount); pw.print(',');
1656 pw.print(viewRootInstanceCount); pw.print(',');
1657 pw.print(appContextInstanceCount); pw.print(',');
1658 pw.print(activityInstanceCount); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 pw.print(globalAssetCount); pw.print(',');
1661 pw.print(globalAssetManagerCount); pw.print(',');
1662 pw.print(binderLocalObjectCount); pw.print(',');
1663 pw.print(binderProxyObjectCount); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 pw.print(binderDeathObjectCount); pw.print(',');
1666 pw.print(openSslSocketCount); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 // SQL
1669 pw.print(sqliteAllocated); pw.print(',');
Bob Leee5408332009-09-04 18:31:17 -07001670 pw.print(stats.databaseBytes / 1024); pw.print(',');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 pw.print(stats.numPagers); pw.print(',');
1672 pw.print((stats.totalBytes - stats.referencedBytes) / 1024); pw.print(',');
1673 pw.print(stats.referencedBytes / 1024); pw.print('\n');
Bob Leee5408332009-09-04 18:31:17 -07001674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 return;
1676 }
Bob Leee5408332009-09-04 18:31:17 -07001677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 // otherwise, show human-readable format
1679 printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total");
1680 printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
1681 printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
1682 nativeAllocated + dalvikAllocated);
1683 printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A",
1684 nativeFree + dalvikFree);
1685
1686 printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
1687 memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);
1688
1689 printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared,
1690 nativeShared + dalvikShared + otherShared);
1691 printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
1692 nativePrivate + dalvikPrivate + otherPrivate);
1693
1694 pw.println(" ");
1695 pw.println(" Objects");
1696 printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRoots:",
1697 viewRootInstanceCount);
1698
1699 printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
1700 "Activities:", activityInstanceCount);
1701
1702 printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
1703 "AssetManagers:", globalAssetManagerCount);
1704
1705 printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
1706 "Proxy Binders:", binderProxyObjectCount);
1707 printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount);
1708
1709 printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount);
Bob Leee5408332009-09-04 18:31:17 -07001710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 // SQLite mem info
1712 pw.println(" ");
1713 pw.println(" SQL");
1714 printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "dbFiles:",
1715 stats.databaseBytes / 1024);
1716 printRow(pw, TWO_COUNT_COLUMNS, "numPagers:", stats.numPagers, "inactivePageKB:",
1717 (stats.totalBytes - stats.referencedBytes) / 1024);
1718 printRow(pw, ONE_COUNT_COLUMN, "activePageKB:", stats.referencedBytes / 1024);
Bob Leee5408332009-09-04 18:31:17 -07001719
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001720 // Asset details.
1721 String assetAlloc = AssetManager.getAssetAllocations();
1722 if (assetAlloc != null) {
1723 pw.println(" ");
1724 pw.println(" Asset Allocations");
1725 pw.print(assetAlloc);
1726 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 }
1728
1729 private void printRow(PrintWriter pw, String format, Object...objs) {
1730 pw.println(String.format(format, objs));
1731 }
1732 }
1733
1734 private final class H extends Handler {
Bob Leee5408332009-09-04 18:31:17 -07001735 private H() {
1736 SamplingProfiler.getInstance().setEventThread(mLooper.getThread());
1737 }
1738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 public static final int LAUNCH_ACTIVITY = 100;
1740 public static final int PAUSE_ACTIVITY = 101;
1741 public static final int PAUSE_ACTIVITY_FINISHING= 102;
1742 public static final int STOP_ACTIVITY_SHOW = 103;
1743 public static final int STOP_ACTIVITY_HIDE = 104;
1744 public static final int SHOW_WINDOW = 105;
1745 public static final int HIDE_WINDOW = 106;
1746 public static final int RESUME_ACTIVITY = 107;
1747 public static final int SEND_RESULT = 108;
1748 public static final int DESTROY_ACTIVITY = 109;
1749 public static final int BIND_APPLICATION = 110;
1750 public static final int EXIT_APPLICATION = 111;
1751 public static final int NEW_INTENT = 112;
1752 public static final int RECEIVER = 113;
1753 public static final int CREATE_SERVICE = 114;
1754 public static final int SERVICE_ARGS = 115;
1755 public static final int STOP_SERVICE = 116;
1756 public static final int REQUEST_THUMBNAIL = 117;
1757 public static final int CONFIGURATION_CHANGED = 118;
1758 public static final int CLEAN_UP_CONTEXT = 119;
1759 public static final int GC_WHEN_IDLE = 120;
1760 public static final int BIND_SERVICE = 121;
1761 public static final int UNBIND_SERVICE = 122;
1762 public static final int DUMP_SERVICE = 123;
1763 public static final int LOW_MEMORY = 124;
1764 public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
1765 public static final int RELAUNCH_ACTIVITY = 126;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001766 public static final int PROFILER_CONTROL = 127;
Christopher Tate181fafa2009-05-14 11:12:14 -07001767 public static final int CREATE_BACKUP_AGENT = 128;
Christopher Tate5e1ab332009-09-01 20:32:49 -07001768 public static final int DESTROY_BACKUP_AGENT = 129;
1769 public static final int SUICIDE = 130;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001770 public static final int REMOVE_PROVIDER = 131;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 String codeToString(int code) {
1772 if (localLOGV) {
1773 switch (code) {
1774 case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
1775 case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
1776 case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
1777 case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
1778 case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
1779 case SHOW_WINDOW: return "SHOW_WINDOW";
1780 case HIDE_WINDOW: return "HIDE_WINDOW";
1781 case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
1782 case SEND_RESULT: return "SEND_RESULT";
1783 case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
1784 case BIND_APPLICATION: return "BIND_APPLICATION";
1785 case EXIT_APPLICATION: return "EXIT_APPLICATION";
1786 case NEW_INTENT: return "NEW_INTENT";
1787 case RECEIVER: return "RECEIVER";
1788 case CREATE_SERVICE: return "CREATE_SERVICE";
1789 case SERVICE_ARGS: return "SERVICE_ARGS";
1790 case STOP_SERVICE: return "STOP_SERVICE";
1791 case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
1792 case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
1793 case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
1794 case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
1795 case BIND_SERVICE: return "BIND_SERVICE";
1796 case UNBIND_SERVICE: return "UNBIND_SERVICE";
1797 case DUMP_SERVICE: return "DUMP_SERVICE";
1798 case LOW_MEMORY: return "LOW_MEMORY";
1799 case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
1800 case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001801 case PROFILER_CONTROL: return "PROFILER_CONTROL";
Christopher Tate181fafa2009-05-14 11:12:14 -07001802 case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
1803 case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
Christopher Tate5e1ab332009-09-01 20:32:49 -07001804 case SUICIDE: return "SUICIDE";
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001805 case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 }
1807 }
1808 return "(unknown)";
1809 }
1810 public void handleMessage(Message msg) {
1811 switch (msg.what) {
1812 case LAUNCH_ACTIVITY: {
1813 ActivityRecord r = (ActivityRecord)msg.obj;
1814
1815 r.packageInfo = getPackageInfoNoCheck(
1816 r.activityInfo.applicationInfo);
Christopher Tateb70f3df2009-04-07 16:07:59 -07001817 handleLaunchActivity(r, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 } break;
1819 case RELAUNCH_ACTIVITY: {
1820 ActivityRecord r = (ActivityRecord)msg.obj;
1821 handleRelaunchActivity(r, msg.arg1);
1822 } break;
1823 case PAUSE_ACTIVITY:
1824 handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
Bob Leee5408332009-09-04 18:31:17 -07001825 maybeSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001826 break;
1827 case PAUSE_ACTIVITY_FINISHING:
1828 handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
1829 break;
1830 case STOP_ACTIVITY_SHOW:
1831 handleStopActivity((IBinder)msg.obj, true, msg.arg2);
1832 break;
1833 case STOP_ACTIVITY_HIDE:
1834 handleStopActivity((IBinder)msg.obj, false, msg.arg2);
1835 break;
1836 case SHOW_WINDOW:
1837 handleWindowVisibility((IBinder)msg.obj, true);
1838 break;
1839 case HIDE_WINDOW:
1840 handleWindowVisibility((IBinder)msg.obj, false);
1841 break;
1842 case RESUME_ACTIVITY:
1843 handleResumeActivity((IBinder)msg.obj, true,
1844 msg.arg1 != 0);
1845 break;
1846 case SEND_RESULT:
1847 handleSendResult((ResultData)msg.obj);
1848 break;
1849 case DESTROY_ACTIVITY:
1850 handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
1851 msg.arg2, false);
1852 break;
1853 case BIND_APPLICATION:
1854 AppBindData data = (AppBindData)msg.obj;
1855 handleBindApplication(data);
1856 break;
1857 case EXIT_APPLICATION:
1858 if (mInitialApplication != null) {
1859 mInitialApplication.onTerminate();
1860 }
1861 Looper.myLooper().quit();
1862 break;
1863 case NEW_INTENT:
1864 handleNewIntent((NewIntentData)msg.obj);
1865 break;
1866 case RECEIVER:
1867 handleReceiver((ReceiverData)msg.obj);
Bob Leee5408332009-09-04 18:31:17 -07001868 maybeSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 break;
1870 case CREATE_SERVICE:
1871 handleCreateService((CreateServiceData)msg.obj);
1872 break;
1873 case BIND_SERVICE:
1874 handleBindService((BindServiceData)msg.obj);
1875 break;
1876 case UNBIND_SERVICE:
1877 handleUnbindService((BindServiceData)msg.obj);
1878 break;
1879 case SERVICE_ARGS:
1880 handleServiceArgs((ServiceArgsData)msg.obj);
1881 break;
1882 case STOP_SERVICE:
1883 handleStopService((IBinder)msg.obj);
Bob Leee5408332009-09-04 18:31:17 -07001884 maybeSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 break;
1886 case REQUEST_THUMBNAIL:
1887 handleRequestThumbnail((IBinder)msg.obj);
1888 break;
1889 case CONFIGURATION_CHANGED:
1890 handleConfigurationChanged((Configuration)msg.obj);
1891 break;
1892 case CLEAN_UP_CONTEXT:
1893 ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
1894 cci.context.performFinalCleanup(cci.who, cci.what);
1895 break;
1896 case GC_WHEN_IDLE:
1897 scheduleGcIdler();
1898 break;
1899 case DUMP_SERVICE:
1900 handleDumpService((DumpServiceInfo)msg.obj);
1901 break;
1902 case LOW_MEMORY:
1903 handleLowMemory();
1904 break;
1905 case ACTIVITY_CONFIGURATION_CHANGED:
1906 handleActivityConfigurationChanged((IBinder)msg.obj);
1907 break;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001908 case PROFILER_CONTROL:
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07001909 handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001910 break;
Christopher Tate181fafa2009-05-14 11:12:14 -07001911 case CREATE_BACKUP_AGENT:
1912 handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
1913 break;
1914 case DESTROY_BACKUP_AGENT:
1915 handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
1916 break;
Christopher Tate5e1ab332009-09-01 20:32:49 -07001917 case SUICIDE:
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001918 Process.killProcess(Process.myPid());
1919 break;
1920 case REMOVE_PROVIDER:
1921 completeRemoveProvider((IContentProvider)msg.obj);
Christopher Tate5e1ab332009-09-01 20:32:49 -07001922 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001923 }
1924 }
Bob Leee5408332009-09-04 18:31:17 -07001925
1926 void maybeSnapshot() {
1927 if (mBoundApplication != null) {
1928 SamplingProfilerIntegration.writeSnapshot(
1929 mBoundApplication.processName);
1930 }
1931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001932 }
1933
1934 private final class Idler implements MessageQueue.IdleHandler {
1935 public final boolean queueIdle() {
1936 ActivityRecord a = mNewActivities;
1937 if (a != null) {
1938 mNewActivities = null;
1939 IActivityManager am = ActivityManagerNative.getDefault();
1940 ActivityRecord prev;
1941 do {
1942 if (localLOGV) Log.v(
1943 TAG, "Reporting idle of " + a +
1944 " finished=" +
1945 (a.activity != null ? a.activity.mFinished : false));
1946 if (a.activity != null && !a.activity.mFinished) {
1947 try {
Dianne Hackborne88846e2009-09-30 21:34:25 -07001948 am.activityIdle(a.token, a.createdConfig);
1949 a.createdConfig = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001950 } catch (RemoteException ex) {
1951 }
1952 }
1953 prev = a;
1954 a = a.nextIdle;
1955 prev.nextIdle = null;
1956 } while (a != null);
1957 }
1958 return false;
1959 }
1960 }
1961
1962 final class GcIdler implements MessageQueue.IdleHandler {
1963 public final boolean queueIdle() {
1964 doGcIfNeeded();
1965 return false;
1966 }
1967 }
1968
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001969 private final static class ResourcesKey {
1970 final private String mResDir;
1971 final private float mScale;
1972 final private int mHash;
Bob Leee5408332009-09-04 18:31:17 -07001973
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001974 ResourcesKey(String resDir, float scale) {
1975 mResDir = resDir;
1976 mScale = scale;
1977 mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
1978 }
Bob Leee5408332009-09-04 18:31:17 -07001979
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001980 @Override
1981 public int hashCode() {
1982 return mHash;
1983 }
1984
1985 @Override
1986 public boolean equals(Object obj) {
1987 if (!(obj instanceof ResourcesKey)) {
1988 return false;
1989 }
1990 ResourcesKey peer = (ResourcesKey) obj;
1991 return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
1992 }
1993 }
1994
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001995 static IPackageManager sPackageManager;
1996
1997 final ApplicationThread mAppThread = new ApplicationThread();
1998 final Looper mLooper = Looper.myLooper();
1999 final H mH = new H();
2000 final HashMap<IBinder, ActivityRecord> mActivities
2001 = new HashMap<IBinder, ActivityRecord>();
2002 // List of new activities (via ActivityRecord.nextIdle) that should
2003 // be reported when next we idle.
2004 ActivityRecord mNewActivities = null;
2005 // Number of activities that are currently visible on-screen.
2006 int mNumVisibleActivities = 0;
2007 final HashMap<IBinder, Service> mServices
2008 = new HashMap<IBinder, Service>();
2009 AppBindData mBoundApplication;
2010 Configuration mConfiguration;
2011 Application mInitialApplication;
2012 final ArrayList<Application> mAllApplications
2013 = new ArrayList<Application>();
Christopher Tate181fafa2009-05-14 11:12:14 -07002014 // set of instantiated backup agents, keyed by package name
2015 final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002016 static final ThreadLocal sThreadLocal = new ThreadLocal();
2017 Instrumentation mInstrumentation;
2018 String mInstrumentationAppDir = null;
2019 String mInstrumentationAppPackage = null;
2020 String mInstrumentedAppDir = null;
2021 boolean mSystemThread = false;
2022
2023 /**
2024 * Activities that are enqueued to be relaunched. This list is accessed
2025 * by multiple threads, so you must synchronize on it when accessing it.
2026 */
2027 final ArrayList<ActivityRecord> mRelaunchingActivities
2028 = new ArrayList<ActivityRecord>();
2029 Configuration mPendingConfiguration = null;
Bob Leee5408332009-09-04 18:31:17 -07002030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 // These can be accessed by multiple threads; mPackages is the lock.
2032 // XXX For now we keep around information about all packages we have
2033 // seen, not removing entries from this map.
2034 final HashMap<String, WeakReference<PackageInfo>> mPackages
2035 = new HashMap<String, WeakReference<PackageInfo>>();
2036 final HashMap<String, WeakReference<PackageInfo>> mResourcePackages
2037 = new HashMap<String, WeakReference<PackageInfo>>();
2038 Display mDisplay = null;
2039 DisplayMetrics mDisplayMetrics = null;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07002040 HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
2041 = new HashMap<ResourcesKey, WeakReference<Resources> >();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002042
2043 // The lock of mProviderMap protects the following variables.
2044 final HashMap<String, ProviderRecord> mProviderMap
2045 = new HashMap<String, ProviderRecord>();
2046 final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
2047 = new HashMap<IBinder, ProviderRefCount>();
2048 final HashMap<IBinder, ProviderRecord> mLocalProviders
2049 = new HashMap<IBinder, ProviderRecord>();
2050
2051 final GcIdler mGcIdler = new GcIdler();
2052 boolean mGcIdlerScheduled = false;
2053
2054 public final PackageInfo getPackageInfo(String packageName, int flags) {
2055 synchronized (mPackages) {
2056 WeakReference<PackageInfo> ref;
2057 if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
2058 ref = mPackages.get(packageName);
2059 } else {
2060 ref = mResourcePackages.get(packageName);
2061 }
2062 PackageInfo packageInfo = ref != null ? ref.get() : null;
2063 //Log.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
2064 if (packageInfo != null && (packageInfo.mResources == null
2065 || packageInfo.mResources.getAssets().isUpToDate())) {
2066 if (packageInfo.isSecurityViolation()
2067 && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
2068 throw new SecurityException(
2069 "Requesting code from " + packageName
2070 + " to be run in process "
2071 + mBoundApplication.processName
2072 + "/" + mBoundApplication.appInfo.uid);
2073 }
2074 return packageInfo;
2075 }
2076 }
2077
2078 ApplicationInfo ai = null;
2079 try {
2080 ai = getPackageManager().getApplicationInfo(packageName,
2081 PackageManager.GET_SHARED_LIBRARY_FILES);
2082 } catch (RemoteException e) {
2083 }
2084
2085 if (ai != null) {
2086 return getPackageInfo(ai, flags);
2087 }
2088
2089 return null;
2090 }
2091
2092 public final PackageInfo getPackageInfo(ApplicationInfo ai, int flags) {
2093 boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
2094 boolean securityViolation = includeCode && ai.uid != 0
2095 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
2096 ? ai.uid != mBoundApplication.appInfo.uid : true);
2097 if ((flags&(Context.CONTEXT_INCLUDE_CODE
2098 |Context.CONTEXT_IGNORE_SECURITY))
2099 == Context.CONTEXT_INCLUDE_CODE) {
2100 if (securityViolation) {
2101 String msg = "Requesting code from " + ai.packageName
2102 + " (with uid " + ai.uid + ")";
2103 if (mBoundApplication != null) {
2104 msg = msg + " to be run in process "
2105 + mBoundApplication.processName + " (with uid "
2106 + mBoundApplication.appInfo.uid + ")";
2107 }
2108 throw new SecurityException(msg);
2109 }
2110 }
2111 return getPackageInfo(ai, null, securityViolation, includeCode);
2112 }
2113
2114 public final PackageInfo getPackageInfoNoCheck(ApplicationInfo ai) {
2115 return getPackageInfo(ai, null, false, true);
2116 }
2117
2118 private final PackageInfo getPackageInfo(ApplicationInfo aInfo,
2119 ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
2120 synchronized (mPackages) {
2121 WeakReference<PackageInfo> ref;
2122 if (includeCode) {
2123 ref = mPackages.get(aInfo.packageName);
2124 } else {
2125 ref = mResourcePackages.get(aInfo.packageName);
2126 }
2127 PackageInfo packageInfo = ref != null ? ref.get() : null;
2128 if (packageInfo == null || (packageInfo.mResources != null
2129 && !packageInfo.mResources.getAssets().isUpToDate())) {
2130 if (localLOGV) Log.v(TAG, (includeCode ? "Loading code package "
2131 : "Loading resource-only package ") + aInfo.packageName
2132 + " (in " + (mBoundApplication != null
2133 ? mBoundApplication.processName : null)
2134 + ")");
2135 packageInfo =
2136 new PackageInfo(this, aInfo, this, baseLoader,
2137 securityViolation, includeCode &&
2138 (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
2139 if (includeCode) {
2140 mPackages.put(aInfo.packageName,
2141 new WeakReference<PackageInfo>(packageInfo));
2142 } else {
2143 mResourcePackages.put(aInfo.packageName,
2144 new WeakReference<PackageInfo>(packageInfo));
2145 }
2146 }
2147 return packageInfo;
2148 }
2149 }
2150
2151 public final boolean hasPackageInfo(String packageName) {
2152 synchronized (mPackages) {
2153 WeakReference<PackageInfo> ref;
2154 ref = mPackages.get(packageName);
2155 if (ref != null && ref.get() != null) {
2156 return true;
2157 }
2158 ref = mResourcePackages.get(packageName);
2159 if (ref != null && ref.get() != null) {
2160 return true;
2161 }
2162 return false;
2163 }
2164 }
Bob Leee5408332009-09-04 18:31:17 -07002165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 ActivityThread() {
2167 }
2168
2169 public ApplicationThread getApplicationThread()
2170 {
2171 return mAppThread;
2172 }
2173
2174 public Instrumentation getInstrumentation()
2175 {
2176 return mInstrumentation;
2177 }
2178
2179 public Configuration getConfiguration() {
2180 return mConfiguration;
2181 }
2182
2183 public boolean isProfiling() {
2184 return mBoundApplication != null && mBoundApplication.profileFile != null;
2185 }
2186
2187 public String getProfileFilePath() {
2188 return mBoundApplication.profileFile;
2189 }
2190
2191 public Looper getLooper() {
2192 return mLooper;
2193 }
2194
2195 public Application getApplication() {
2196 return mInitialApplication;
2197 }
Bob Leee5408332009-09-04 18:31:17 -07002198
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -07002199 public String getProcessName() {
2200 return mBoundApplication.processName;
2201 }
Bob Leee5408332009-09-04 18:31:17 -07002202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 public ApplicationContext getSystemContext() {
2204 synchronized (this) {
2205 if (mSystemContext == null) {
2206 ApplicationContext context =
2207 ApplicationContext.createSystemContext(this);
Mike Cleron432b7132009-09-24 15:28:29 -07002208 PackageInfo info = new PackageInfo(this, "android", context, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002209 context.init(info, null, this);
2210 context.getResources().updateConfiguration(
2211 getConfiguration(), getDisplayMetricsLocked(false));
2212 mSystemContext = context;
2213 //Log.i(TAG, "Created system resources " + context.getResources()
2214 // + ": " + context.getResources().getConfiguration());
2215 }
2216 }
2217 return mSystemContext;
2218 }
2219
Mike Cleron432b7132009-09-24 15:28:29 -07002220 public void installSystemApplicationInfo(ApplicationInfo info) {
2221 synchronized (this) {
2222 ApplicationContext context = getSystemContext();
2223 context.init(new PackageInfo(this, "android", context, info), null, this);
2224 }
2225 }
2226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 void scheduleGcIdler() {
2228 if (!mGcIdlerScheduled) {
2229 mGcIdlerScheduled = true;
2230 Looper.myQueue().addIdleHandler(mGcIdler);
2231 }
2232 mH.removeMessages(H.GC_WHEN_IDLE);
2233 }
2234
2235 void unscheduleGcIdler() {
2236 if (mGcIdlerScheduled) {
2237 mGcIdlerScheduled = false;
2238 Looper.myQueue().removeIdleHandler(mGcIdler);
2239 }
2240 mH.removeMessages(H.GC_WHEN_IDLE);
2241 }
2242
2243 void doGcIfNeeded() {
2244 mGcIdlerScheduled = false;
2245 final long now = SystemClock.uptimeMillis();
2246 //Log.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
2247 // + "m now=" + now);
2248 if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
2249 //Log.i(TAG, "**** WE DO, WE DO WANT TO GC!");
2250 BinderInternal.forceGc("bg");
2251 }
2252 }
2253
2254 public final ActivityInfo resolveActivityInfo(Intent intent) {
2255 ActivityInfo aInfo = intent.resolveActivityInfo(
2256 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
2257 if (aInfo == null) {
2258 // Throw an exception.
2259 Instrumentation.checkStartActivityResult(
2260 IActivityManager.START_CLASS_NOT_FOUND, intent);
2261 }
2262 return aInfo;
2263 }
Bob Leee5408332009-09-04 18:31:17 -07002264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002265 public final Activity startActivityNow(Activity parent, String id,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
2267 Object lastNonConfigurationInstance) {
2268 ActivityRecord r = new ActivityRecord();
2269 r.token = token;
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002270 r.ident = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 r.intent = intent;
2272 r.state = state;
2273 r.parent = parent;
2274 r.embeddedID = id;
2275 r.activityInfo = activityInfo;
2276 r.lastNonConfigurationInstance = lastNonConfigurationInstance;
2277 if (localLOGV) {
2278 ComponentName compname = intent.getComponent();
2279 String name;
2280 if (compname != null) {
2281 name = compname.toShortString();
2282 } else {
2283 name = "(Intent " + intent + ").getComponent() returned null";
2284 }
2285 Log.v(TAG, "Performing launch: action=" + intent.getAction()
2286 + ", comp=" + name
2287 + ", token=" + token);
2288 }
Christopher Tateb70f3df2009-04-07 16:07:59 -07002289 return performLaunchActivity(r, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290 }
2291
2292 public final Activity getActivity(IBinder token) {
2293 return mActivities.get(token).activity;
2294 }
2295
2296 public final void sendActivityResult(
2297 IBinder token, String id, int requestCode,
2298 int resultCode, Intent data) {
Chris Tate8a7dc172009-03-24 20:11:42 -07002299 if (DEBUG_RESULTS) Log.v(TAG, "sendActivityResult: id=" + id
2300 + " req=" + requestCode + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002301 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
2302 list.add(new ResultInfo(id, requestCode, resultCode, data));
2303 mAppThread.scheduleSendResult(token, list);
2304 }
2305
2306 // if the thread hasn't started yet, we don't have the handler, so just
2307 // save the messages until we're ready.
2308 private final void queueOrSendMessage(int what, Object obj) {
2309 queueOrSendMessage(what, obj, 0, 0);
2310 }
2311
2312 private final void queueOrSendMessage(int what, Object obj, int arg1) {
2313 queueOrSendMessage(what, obj, arg1, 0);
2314 }
2315
2316 private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
2317 synchronized (this) {
2318 if (localLOGV) Log.v(
2319 TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
2320 + ": " + arg1 + " / " + obj);
2321 Message msg = Message.obtain();
2322 msg.what = what;
2323 msg.obj = obj;
2324 msg.arg1 = arg1;
2325 msg.arg2 = arg2;
2326 mH.sendMessage(msg);
2327 }
2328 }
2329
2330 final void scheduleContextCleanup(ApplicationContext context, String who,
2331 String what) {
2332 ContextCleanupInfo cci = new ContextCleanupInfo();
2333 cci.context = context;
2334 cci.who = who;
2335 cci.what = what;
2336 queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
2337 }
2338
Christopher Tateb70f3df2009-04-07 16:07:59 -07002339 private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002340 // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
2341
2342 ActivityInfo aInfo = r.activityInfo;
2343 if (r.packageInfo == null) {
2344 r.packageInfo = getPackageInfo(aInfo.applicationInfo,
2345 Context.CONTEXT_INCLUDE_CODE);
2346 }
Bob Leee5408332009-09-04 18:31:17 -07002347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002348 ComponentName component = r.intent.getComponent();
2349 if (component == null) {
2350 component = r.intent.resolveActivity(
2351 mInitialApplication.getPackageManager());
2352 r.intent.setComponent(component);
2353 }
2354
2355 if (r.activityInfo.targetActivity != null) {
2356 component = new ComponentName(r.activityInfo.packageName,
2357 r.activityInfo.targetActivity);
2358 }
2359
2360 Activity activity = null;
2361 try {
2362 java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
2363 activity = mInstrumentation.newActivity(
2364 cl, component.getClassName(), r.intent);
2365 r.intent.setExtrasClassLoader(cl);
2366 if (r.state != null) {
2367 r.state.setClassLoader(cl);
2368 }
2369 } catch (Exception e) {
2370 if (!mInstrumentation.onException(activity, e)) {
2371 throw new RuntimeException(
2372 "Unable to instantiate activity " + component
2373 + ": " + e.toString(), e);
2374 }
2375 }
2376
2377 try {
Christopher Tate181fafa2009-05-14 11:12:14 -07002378 Application app = r.packageInfo.makeApplication(false);
Bob Leee5408332009-09-04 18:31:17 -07002379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 if (localLOGV) Log.v(TAG, "Performing launch of " + r);
2381 if (localLOGV) Log.v(
2382 TAG, r + ": app=" + app
2383 + ", appName=" + app.getPackageName()
2384 + ", pkg=" + r.packageInfo.getPackageName()
2385 + ", comp=" + r.intent.getComponent().toShortString()
2386 + ", dir=" + r.packageInfo.getAppDir());
2387
2388 if (activity != null) {
2389 ApplicationContext appContext = new ApplicationContext();
2390 appContext.init(r.packageInfo, r.token, this);
2391 appContext.setOuterContext(activity);
2392 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
2393 Configuration config = new Configuration(mConfiguration);
Dianne Hackborndc6b6352009-09-30 14:20:09 -07002394 if (DEBUG_CONFIGURATION) Log.v(TAG, "Launching activity "
2395 + r.activityInfo.name + " with config " + config);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002396 activity.attach(appContext, this, getInstrumentation(), r.token,
2397 r.ident, app, r.intent, r.activityInfo, title, r.parent,
2398 r.embeddedID, r.lastNonConfigurationInstance,
2399 r.lastNonConfigurationChildInstances, config);
Bob Leee5408332009-09-04 18:31:17 -07002400
Christopher Tateb70f3df2009-04-07 16:07:59 -07002401 if (customIntent != null) {
2402 activity.mIntent = customIntent;
2403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002404 r.lastNonConfigurationInstance = null;
2405 r.lastNonConfigurationChildInstances = null;
2406 activity.mStartedActivity = false;
2407 int theme = r.activityInfo.getThemeResource();
2408 if (theme != 0) {
2409 activity.setTheme(theme);
2410 }
2411
2412 activity.mCalled = false;
2413 mInstrumentation.callActivityOnCreate(activity, r.state);
2414 if (!activity.mCalled) {
2415 throw new SuperNotCalledException(
2416 "Activity " + r.intent.getComponent().toShortString() +
2417 " did not call through to super.onCreate()");
2418 }
2419 r.activity = activity;
2420 r.stopped = true;
2421 if (!r.activity.mFinished) {
2422 activity.performStart();
2423 r.stopped = false;
2424 }
2425 if (!r.activity.mFinished) {
2426 if (r.state != null) {
2427 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
2428 }
2429 }
2430 if (!r.activity.mFinished) {
2431 activity.mCalled = false;
2432 mInstrumentation.callActivityOnPostCreate(activity, r.state);
2433 if (!activity.mCalled) {
2434 throw new SuperNotCalledException(
2435 "Activity " + r.intent.getComponent().toShortString() +
2436 " did not call through to super.onPostCreate()");
2437 }
2438 }
2439 r.state = null;
2440 }
2441 r.paused = true;
2442
2443 mActivities.put(r.token, r);
2444
2445 } catch (SuperNotCalledException e) {
2446 throw e;
2447
2448 } catch (Exception e) {
2449 if (!mInstrumentation.onException(activity, e)) {
2450 throw new RuntimeException(
2451 "Unable to start activity " + component
2452 + ": " + e.toString(), e);
2453 }
2454 }
2455
2456 return activity;
2457 }
2458
Christopher Tateb70f3df2009-04-07 16:07:59 -07002459 private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 // If we are getting ready to gc after going to the background, well
2461 // we are back active so skip it.
2462 unscheduleGcIdler();
2463
2464 if (localLOGV) Log.v(
2465 TAG, "Handling launch of " + r);
Christopher Tateb70f3df2009-04-07 16:07:59 -07002466 Activity a = performLaunchActivity(r, customIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467
2468 if (a != null) {
Dianne Hackborne88846e2009-09-30 21:34:25 -07002469 r.createdConfig = new Configuration(a.getResources().getConfiguration());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002470 handleResumeActivity(r.token, false, r.isForward);
2471
2472 if (!r.activity.mFinished && r.startsNotResumed) {
2473 // The activity manager actually wants this one to start out
2474 // paused, because it needs to be visible but isn't in the
2475 // foreground. We accomplish this by going through the
2476 // normal startup (because activities expect to go through
2477 // onResume() the first time they run, before their window
2478 // is displayed), and then pausing it. However, in this case
2479 // we do -not- need to do the full pause cycle (of freezing
2480 // and such) because the activity manager assumes it can just
2481 // retain the current state it has.
2482 try {
2483 r.activity.mCalled = false;
2484 mInstrumentation.callActivityOnPause(r.activity);
2485 if (!r.activity.mCalled) {
2486 throw new SuperNotCalledException(
2487 "Activity " + r.intent.getComponent().toShortString() +
2488 " did not call through to super.onPause()");
2489 }
2490
2491 } catch (SuperNotCalledException e) {
2492 throw e;
2493
2494 } catch (Exception e) {
2495 if (!mInstrumentation.onException(r.activity, e)) {
2496 throw new RuntimeException(
2497 "Unable to pause activity "
2498 + r.intent.getComponent().toShortString()
2499 + ": " + e.toString(), e);
2500 }
2501 }
2502 r.paused = true;
2503 }
2504 } else {
2505 // If there was an error, for any reason, tell the activity
2506 // manager to stop us.
2507 try {
2508 ActivityManagerNative.getDefault()
2509 .finishActivity(r.token, Activity.RESULT_CANCELED, null);
2510 } catch (RemoteException ex) {
2511 }
2512 }
2513 }
2514
2515 private final void deliverNewIntents(ActivityRecord r,
2516 List<Intent> intents) {
2517 final int N = intents.size();
2518 for (int i=0; i<N; i++) {
2519 Intent intent = intents.get(i);
2520 intent.setExtrasClassLoader(r.activity.getClassLoader());
2521 mInstrumentation.callActivityOnNewIntent(r.activity, intent);
2522 }
2523 }
2524
2525 public final void performNewIntents(IBinder token,
2526 List<Intent> intents) {
2527 ActivityRecord r = mActivities.get(token);
2528 if (r != null) {
2529 final boolean resumed = !r.paused;
2530 if (resumed) {
2531 mInstrumentation.callActivityOnPause(r.activity);
2532 }
2533 deliverNewIntents(r, intents);
2534 if (resumed) {
2535 mInstrumentation.callActivityOnResume(r.activity);
2536 }
2537 }
2538 }
Bob Leee5408332009-09-04 18:31:17 -07002539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002540 private final void handleNewIntent(NewIntentData data) {
2541 performNewIntents(data.token, data.intents);
2542 }
2543
2544 private final void handleReceiver(ReceiverData data) {
2545 // If we are getting ready to gc after going to the background, well
2546 // we are back active so skip it.
2547 unscheduleGcIdler();
2548
2549 String component = data.intent.getComponent().getClassName();
2550
2551 PackageInfo packageInfo = getPackageInfoNoCheck(
2552 data.info.applicationInfo);
2553
2554 IActivityManager mgr = ActivityManagerNative.getDefault();
2555
2556 BroadcastReceiver receiver = null;
2557 try {
2558 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2559 data.intent.setExtrasClassLoader(cl);
2560 if (data.resultExtras != null) {
2561 data.resultExtras.setClassLoader(cl);
2562 }
2563 receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
2564 } catch (Exception e) {
2565 try {
2566 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
2567 data.resultData, data.resultExtras, data.resultAbort);
2568 } catch (RemoteException ex) {
2569 }
2570 throw new RuntimeException(
2571 "Unable to instantiate receiver " + component
2572 + ": " + e.toString(), e);
2573 }
2574
2575 try {
Christopher Tate181fafa2009-05-14 11:12:14 -07002576 Application app = packageInfo.makeApplication(false);
Bob Leee5408332009-09-04 18:31:17 -07002577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 if (localLOGV) Log.v(
2579 TAG, "Performing receive of " + data.intent
2580 + ": app=" + app
2581 + ", appName=" + app.getPackageName()
2582 + ", pkg=" + packageInfo.getPackageName()
2583 + ", comp=" + data.intent.getComponent().toShortString()
2584 + ", dir=" + packageInfo.getAppDir());
2585
2586 ApplicationContext context = (ApplicationContext)app.getBaseContext();
2587 receiver.setOrderedHint(true);
2588 receiver.setResult(data.resultCode, data.resultData,
2589 data.resultExtras);
2590 receiver.setOrderedHint(data.sync);
2591 receiver.onReceive(context.getReceiverRestrictedContext(),
2592 data.intent);
2593 } catch (Exception e) {
2594 try {
2595 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
2596 data.resultData, data.resultExtras, data.resultAbort);
2597 } catch (RemoteException ex) {
2598 }
2599 if (!mInstrumentation.onException(receiver, e)) {
2600 throw new RuntimeException(
2601 "Unable to start receiver " + component
2602 + ": " + e.toString(), e);
2603 }
2604 }
2605
2606 try {
2607 if (data.sync) {
2608 mgr.finishReceiver(
2609 mAppThread.asBinder(), receiver.getResultCode(),
2610 receiver.getResultData(), receiver.getResultExtras(false),
2611 receiver.getAbortBroadcast());
2612 } else {
2613 mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false);
2614 }
2615 } catch (RemoteException ex) {
2616 }
2617 }
2618
Christopher Tate181fafa2009-05-14 11:12:14 -07002619 // Instantiate a BackupAgent and tell it that it's alive
2620 private final void handleCreateBackupAgent(CreateBackupAgentData data) {
2621 if (DEBUG_BACKUP) Log.v(TAG, "handleCreateBackupAgent: " + data);
2622
2623 // no longer idle; we have backup work to do
2624 unscheduleGcIdler();
2625
2626 // instantiate the BackupAgent class named in the manifest
2627 PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
2628 String packageName = packageInfo.mPackageName;
2629 if (mBackupAgents.get(packageName) != null) {
2630 Log.d(TAG, "BackupAgent " + " for " + packageName
2631 + " already exists");
2632 return;
2633 }
Bob Leee5408332009-09-04 18:31:17 -07002634
Christopher Tate181fafa2009-05-14 11:12:14 -07002635 BackupAgent agent = null;
2636 String classname = data.appInfo.backupAgentName;
2637 if (classname == null) {
2638 if (data.backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL) {
2639 Log.e(TAG, "Attempted incremental backup but no defined agent for "
2640 + packageName);
2641 return;
2642 }
2643 classname = "android.app.FullBackupAgent";
2644 }
2645 try {
Christopher Tated1475e02009-07-09 15:36:17 -07002646 IBinder binder = null;
2647 try {
2648 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2649 agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance();
2650
2651 // set up the agent's context
2652 if (DEBUG_BACKUP) Log.v(TAG, "Initializing BackupAgent "
2653 + data.appInfo.backupAgentName);
2654
2655 ApplicationContext context = new ApplicationContext();
2656 context.init(packageInfo, null, this);
2657 context.setOuterContext(agent);
2658 agent.attach(context);
2659
2660 agent.onCreate();
2661 binder = agent.onBind();
2662 mBackupAgents.put(packageName, agent);
2663 } catch (Exception e) {
2664 // If this is during restore, fail silently; otherwise go
2665 // ahead and let the user see the crash.
2666 Log.e(TAG, "Agent threw during creation: " + e);
2667 if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE) {
2668 throw e;
2669 }
2670 // falling through with 'binder' still null
2671 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002672
2673 // tell the OS that we're live now
Christopher Tate181fafa2009-05-14 11:12:14 -07002674 try {
2675 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
2676 } catch (RemoteException e) {
2677 // nothing to do.
2678 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002679 } catch (Exception e) {
2680 throw new RuntimeException("Unable to create BackupAgent "
2681 + data.appInfo.backupAgentName + ": " + e.toString(), e);
2682 }
2683 }
2684
2685 // Tear down a BackupAgent
2686 private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
2687 if (DEBUG_BACKUP) Log.v(TAG, "handleDestroyBackupAgent: " + data);
Bob Leee5408332009-09-04 18:31:17 -07002688
Christopher Tate181fafa2009-05-14 11:12:14 -07002689 PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
2690 String packageName = packageInfo.mPackageName;
2691 BackupAgent agent = mBackupAgents.get(packageName);
2692 if (agent != null) {
2693 try {
2694 agent.onDestroy();
2695 } catch (Exception e) {
2696 Log.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
2697 e.printStackTrace();
2698 }
2699 mBackupAgents.remove(packageName);
2700 } else {
2701 Log.w(TAG, "Attempt to destroy unknown backup agent " + data);
2702 }
2703 }
2704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 private final void handleCreateService(CreateServiceData data) {
2706 // If we are getting ready to gc after going to the background, well
2707 // we are back active so skip it.
2708 unscheduleGcIdler();
2709
2710 PackageInfo packageInfo = getPackageInfoNoCheck(
2711 data.info.applicationInfo);
2712 Service service = null;
2713 try {
2714 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2715 service = (Service) cl.loadClass(data.info.name).newInstance();
2716 } catch (Exception e) {
2717 if (!mInstrumentation.onException(service, e)) {
2718 throw new RuntimeException(
2719 "Unable to instantiate service " + data.info.name
2720 + ": " + e.toString(), e);
2721 }
2722 }
2723
2724 try {
2725 if (localLOGV) Log.v(TAG, "Creating service " + data.info.name);
2726
2727 ApplicationContext context = new ApplicationContext();
2728 context.init(packageInfo, null, this);
2729
Christopher Tate181fafa2009-05-14 11:12:14 -07002730 Application app = packageInfo.makeApplication(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 context.setOuterContext(service);
2732 service.attach(context, this, data.info.name, data.token, app,
2733 ActivityManagerNative.getDefault());
2734 service.onCreate();
2735 mServices.put(data.token, service);
2736 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07002737 ActivityManagerNative.getDefault().serviceDoneExecuting(
2738 data.token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002739 } catch (RemoteException e) {
2740 // nothing to do.
2741 }
2742 } catch (Exception e) {
2743 if (!mInstrumentation.onException(service, e)) {
2744 throw new RuntimeException(
2745 "Unable to create service " + data.info.name
2746 + ": " + e.toString(), e);
2747 }
2748 }
2749 }
2750
2751 private final void handleBindService(BindServiceData data) {
2752 Service s = mServices.get(data.token);
2753 if (s != null) {
2754 try {
2755 data.intent.setExtrasClassLoader(s.getClassLoader());
2756 try {
2757 if (!data.rebind) {
2758 IBinder binder = s.onBind(data.intent);
2759 ActivityManagerNative.getDefault().publishService(
2760 data.token, data.intent, binder);
2761 } else {
2762 s.onRebind(data.intent);
2763 ActivityManagerNative.getDefault().serviceDoneExecuting(
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07002764 data.token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 }
2766 } catch (RemoteException ex) {
2767 }
2768 } catch (Exception e) {
2769 if (!mInstrumentation.onException(s, e)) {
2770 throw new RuntimeException(
2771 "Unable to bind to service " + s
2772 + " with " + data.intent + ": " + e.toString(), e);
2773 }
2774 }
2775 }
2776 }
2777
2778 private final void handleUnbindService(BindServiceData data) {
2779 Service s = mServices.get(data.token);
2780 if (s != null) {
2781 try {
2782 data.intent.setExtrasClassLoader(s.getClassLoader());
2783 boolean doRebind = s.onUnbind(data.intent);
2784 try {
2785 if (doRebind) {
2786 ActivityManagerNative.getDefault().unbindFinished(
2787 data.token, data.intent, doRebind);
2788 } else {
2789 ActivityManagerNative.getDefault().serviceDoneExecuting(
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07002790 data.token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 }
2792 } catch (RemoteException ex) {
2793 }
2794 } catch (Exception e) {
2795 if (!mInstrumentation.onException(s, e)) {
2796 throw new RuntimeException(
2797 "Unable to unbind to service " + s
2798 + " with " + data.intent + ": " + e.toString(), e);
2799 }
2800 }
2801 }
2802 }
2803
2804 private void handleDumpService(DumpServiceInfo info) {
2805 try {
2806 Service s = mServices.get(info.service);
2807 if (s != null) {
2808 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
2809 s.dump(info.fd, pw, info.args);
2810 pw.close();
2811 }
2812 } finally {
2813 synchronized (info) {
2814 info.dumped = true;
2815 info.notifyAll();
2816 }
2817 }
2818 }
2819
2820 private final void handleServiceArgs(ServiceArgsData data) {
2821 Service s = mServices.get(data.token);
2822 if (s != null) {
2823 try {
2824 if (data.args != null) {
2825 data.args.setExtrasClassLoader(s.getClassLoader());
2826 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07002827 int res = s.onStartCommand(data.args, data.flags, data.startId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07002829 ActivityManagerNative.getDefault().serviceDoneExecuting(
2830 data.token, 1, data.startId, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002831 } catch (RemoteException e) {
2832 // nothing to do.
2833 }
2834 } catch (Exception e) {
2835 if (!mInstrumentation.onException(s, e)) {
2836 throw new RuntimeException(
2837 "Unable to start service " + s
2838 + " with " + data.args + ": " + e.toString(), e);
2839 }
2840 }
2841 }
2842 }
2843
2844 private final void handleStopService(IBinder token) {
2845 Service s = mServices.remove(token);
2846 if (s != null) {
2847 try {
2848 if (localLOGV) Log.v(TAG, "Destroying service " + s);
2849 s.onDestroy();
2850 Context context = s.getBaseContext();
2851 if (context instanceof ApplicationContext) {
2852 final String who = s.getClassName();
2853 ((ApplicationContext) context).scheduleFinalCleanup(who, "Service");
2854 }
2855 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07002856 ActivityManagerNative.getDefault().serviceDoneExecuting(
2857 token, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002858 } catch (RemoteException e) {
2859 // nothing to do.
2860 }
2861 } catch (Exception e) {
2862 if (!mInstrumentation.onException(s, e)) {
2863 throw new RuntimeException(
2864 "Unable to stop service " + s
2865 + ": " + e.toString(), e);
2866 }
2867 }
2868 }
2869 //Log.i(TAG, "Running services: " + mServices);
2870 }
2871
2872 public final ActivityRecord performResumeActivity(IBinder token,
2873 boolean clearHide) {
2874 ActivityRecord r = mActivities.get(token);
2875 if (localLOGV) Log.v(TAG, "Performing resume of " + r
2876 + " finished=" + r.activity.mFinished);
2877 if (r != null && !r.activity.mFinished) {
2878 if (clearHide) {
2879 r.hideForNow = false;
2880 r.activity.mStartedActivity = false;
2881 }
2882 try {
2883 if (r.pendingIntents != null) {
2884 deliverNewIntents(r, r.pendingIntents);
2885 r.pendingIntents = null;
2886 }
2887 if (r.pendingResults != null) {
2888 deliverResults(r, r.pendingResults);
2889 r.pendingResults = null;
2890 }
2891 r.activity.performResume();
2892
Bob Leee5408332009-09-04 18:31:17 -07002893 EventLog.writeEvent(LOG_ON_RESUME_CALLED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002894 r.activity.getComponentName().getClassName());
Bob Leee5408332009-09-04 18:31:17 -07002895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002896 r.paused = false;
2897 r.stopped = false;
2898 if (r.activity.mStartedActivity) {
2899 r.hideForNow = true;
2900 }
2901 r.state = null;
2902 } catch (Exception e) {
2903 if (!mInstrumentation.onException(r.activity, e)) {
2904 throw new RuntimeException(
2905 "Unable to resume activity "
2906 + r.intent.getComponent().toShortString()
2907 + ": " + e.toString(), e);
2908 }
2909 }
2910 }
2911 return r;
2912 }
2913
2914 final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
2915 // If we are getting ready to gc after going to the background, well
2916 // we are back active so skip it.
2917 unscheduleGcIdler();
2918
2919 ActivityRecord r = performResumeActivity(token, clearHide);
2920
2921 if (r != null) {
2922 final Activity a = r.activity;
2923
2924 if (localLOGV) Log.v(
2925 TAG, "Resume " + r + " started activity: " +
2926 a.mStartedActivity + ", hideForNow: " + r.hideForNow
2927 + ", finished: " + a.mFinished);
2928
2929 final int forwardBit = isForward ?
2930 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
Bob Leee5408332009-09-04 18:31:17 -07002931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 // If the window hasn't yet been added to the window manager,
2933 // and this guy didn't finish itself or start another activity,
2934 // then go ahead and add the window.
2935 if (r.window == null && !a.mFinished && !a.mStartedActivity) {
2936 r.window = r.activity.getWindow();
2937 View decor = r.window.getDecorView();
2938 decor.setVisibility(View.INVISIBLE);
2939 ViewManager wm = a.getWindowManager();
2940 WindowManager.LayoutParams l = r.window.getAttributes();
2941 a.mDecor = decor;
2942 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
2943 l.softInputMode |= forwardBit;
2944 if (a.mVisibleFromClient) {
2945 a.mWindowAdded = true;
2946 wm.addView(decor, l);
2947 }
2948
2949 // If the window has already been added, but during resume
2950 // we started another activity, then don't yet make the
2951 // window visisble.
2952 } else if (a.mStartedActivity) {
2953 if (localLOGV) Log.v(
2954 TAG, "Launch " + r + " mStartedActivity set");
2955 r.hideForNow = true;
2956 }
2957
2958 // The window is now visible if it has been added, we are not
2959 // simply finishing, and we are not starting another activity.
Dianne Hackbornc1e605e2009-09-25 17:18:15 -07002960 if (!r.activity.mFinished && !a.mStartedActivity
2961 && r.activity.mDecor != null && !r.hideForNow) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002962 if (r.newConfig != null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -07002963 if (DEBUG_CONFIGURATION) Log.v(TAG, "Resuming activity "
2964 + r.activityInfo.name + " with newConfig " + r.newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002965 performConfigurationChanged(r.activity, r.newConfig);
2966 r.newConfig = null;
2967 }
2968 if (localLOGV) Log.v(TAG, "Resuming " + r + " with isForward="
2969 + isForward);
2970 WindowManager.LayoutParams l = r.window.getAttributes();
2971 if ((l.softInputMode
2972 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
2973 != forwardBit) {
2974 l.softInputMode = (l.softInputMode
2975 & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
2976 | forwardBit;
Dianne Hackbornc1e605e2009-09-25 17:18:15 -07002977 if (r.activity.mVisibleFromClient) {
2978 ViewManager wm = a.getWindowManager();
2979 View decor = r.window.getDecorView();
2980 wm.updateViewLayout(decor, l);
2981 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002982 }
2983 r.activity.mVisibleFromServer = true;
2984 mNumVisibleActivities++;
2985 if (r.activity.mVisibleFromClient) {
2986 r.activity.makeVisible();
2987 }
2988 }
2989
2990 r.nextIdle = mNewActivities;
2991 mNewActivities = r;
2992 if (localLOGV) Log.v(
2993 TAG, "Scheduling idle handler for " + r);
2994 Looper.myQueue().addIdleHandler(new Idler());
2995
2996 } else {
2997 // If an exception was thrown when trying to resume, then
2998 // just end this activity.
2999 try {
3000 ActivityManagerNative.getDefault()
3001 .finishActivity(token, Activity.RESULT_CANCELED, null);
3002 } catch (RemoteException ex) {
3003 }
3004 }
3005 }
3006
3007 private int mThumbnailWidth = -1;
3008 private int mThumbnailHeight = -1;
3009
3010 private final Bitmap createThumbnailBitmap(ActivityRecord r) {
3011 Bitmap thumbnail = null;
3012 try {
3013 int w = mThumbnailWidth;
3014 int h;
3015 if (w < 0) {
3016 Resources res = r.activity.getResources();
3017 mThumbnailHeight = h =
3018 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
3019
3020 mThumbnailWidth = w =
3021 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
3022 } else {
3023 h = mThumbnailHeight;
3024 }
3025
3026 // XXX Only set hasAlpha if needed?
3027 thumbnail = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
3028 thumbnail.eraseColor(0);
3029 Canvas cv = new Canvas(thumbnail);
3030 if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
3031 thumbnail = null;
3032 }
3033 } catch (Exception e) {
3034 if (!mInstrumentation.onException(r.activity, e)) {
3035 throw new RuntimeException(
3036 "Unable to create thumbnail of "
3037 + r.intent.getComponent().toShortString()
3038 + ": " + e.toString(), e);
3039 }
3040 thumbnail = null;
3041 }
3042
3043 return thumbnail;
3044 }
3045
3046 private final void handlePauseActivity(IBinder token, boolean finished,
3047 boolean userLeaving, int configChanges) {
3048 ActivityRecord r = mActivities.get(token);
3049 if (r != null) {
3050 //Log.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
3051 if (userLeaving) {
3052 performUserLeavingActivity(r);
3053 }
Bob Leee5408332009-09-04 18:31:17 -07003054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 r.activity.mConfigChangeFlags |= configChanges;
3056 Bundle state = performPauseActivity(token, finished, true);
3057
3058 // Tell the activity manager we have paused.
3059 try {
3060 ActivityManagerNative.getDefault().activityPaused(token, state);
3061 } catch (RemoteException ex) {
3062 }
3063 }
3064 }
3065
3066 final void performUserLeavingActivity(ActivityRecord r) {
3067 mInstrumentation.callActivityOnUserLeaving(r.activity);
3068 }
3069
3070 final Bundle performPauseActivity(IBinder token, boolean finished,
3071 boolean saveState) {
3072 ActivityRecord r = mActivities.get(token);
3073 return r != null ? performPauseActivity(r, finished, saveState) : null;
3074 }
3075
3076 final Bundle performPauseActivity(ActivityRecord r, boolean finished,
3077 boolean saveState) {
3078 if (r.paused) {
3079 if (r.activity.mFinished) {
3080 // If we are finishing, we won't call onResume() in certain cases.
3081 // So here we likewise don't want to call onPause() if the activity
3082 // isn't resumed.
3083 return null;
3084 }
3085 RuntimeException e = new RuntimeException(
3086 "Performing pause of activity that is not resumed: "
3087 + r.intent.getComponent().toShortString());
3088 Log.e(TAG, e.getMessage(), e);
3089 }
3090 Bundle state = null;
3091 if (finished) {
3092 r.activity.mFinished = true;
3093 }
3094 try {
3095 // Next have the activity save its current state and managed dialogs...
3096 if (!r.activity.mFinished && saveState) {
3097 state = new Bundle();
3098 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
3099 r.state = state;
3100 }
3101 // Now we are idle.
3102 r.activity.mCalled = false;
3103 mInstrumentation.callActivityOnPause(r.activity);
3104 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
3105 if (!r.activity.mCalled) {
3106 throw new SuperNotCalledException(
3107 "Activity " + r.intent.getComponent().toShortString() +
3108 " did not call through to super.onPause()");
3109 }
3110
3111 } catch (SuperNotCalledException e) {
3112 throw e;
3113
3114 } catch (Exception e) {
3115 if (!mInstrumentation.onException(r.activity, e)) {
3116 throw new RuntimeException(
3117 "Unable to pause activity "
3118 + r.intent.getComponent().toShortString()
3119 + ": " + e.toString(), e);
3120 }
3121 }
3122 r.paused = true;
3123 return state;
3124 }
3125
3126 final void performStopActivity(IBinder token) {
3127 ActivityRecord r = mActivities.get(token);
3128 performStopActivityInner(r, null, false);
3129 }
3130
3131 private static class StopInfo {
3132 Bitmap thumbnail;
3133 CharSequence description;
3134 }
3135
3136 private final class ProviderRefCount {
3137 public int count;
3138 ProviderRefCount(int pCount) {
3139 count = pCount;
3140 }
3141 }
3142
3143 private final void performStopActivityInner(ActivityRecord r,
3144 StopInfo info, boolean keepShown) {
3145 if (localLOGV) Log.v(TAG, "Performing stop of " + r);
3146 if (r != null) {
3147 if (!keepShown && r.stopped) {
3148 if (r.activity.mFinished) {
3149 // If we are finishing, we won't call onResume() in certain
3150 // cases. So here we likewise don't want to call onStop()
3151 // if the activity isn't resumed.
3152 return;
3153 }
3154 RuntimeException e = new RuntimeException(
3155 "Performing stop of activity that is not resumed: "
3156 + r.intent.getComponent().toShortString());
3157 Log.e(TAG, e.getMessage(), e);
3158 }
3159
3160 if (info != null) {
3161 try {
3162 // First create a thumbnail for the activity...
3163 //info.thumbnail = createThumbnailBitmap(r);
3164 info.description = r.activity.onCreateDescription();
3165 } catch (Exception e) {
3166 if (!mInstrumentation.onException(r.activity, e)) {
3167 throw new RuntimeException(
3168 "Unable to save state of activity "
3169 + r.intent.getComponent().toShortString()
3170 + ": " + e.toString(), e);
3171 }
3172 }
3173 }
3174
3175 if (!keepShown) {
3176 try {
3177 // Now we are idle.
3178 r.activity.performStop();
3179 } catch (Exception e) {
3180 if (!mInstrumentation.onException(r.activity, e)) {
3181 throw new RuntimeException(
3182 "Unable to stop activity "
3183 + r.intent.getComponent().toShortString()
3184 + ": " + e.toString(), e);
3185 }
3186 }
3187 r.stopped = true;
3188 }
3189
3190 r.paused = true;
3191 }
3192 }
3193
3194 private final void updateVisibility(ActivityRecord r, boolean show) {
3195 View v = r.activity.mDecor;
3196 if (v != null) {
3197 if (show) {
3198 if (!r.activity.mVisibleFromServer) {
3199 r.activity.mVisibleFromServer = true;
3200 mNumVisibleActivities++;
3201 if (r.activity.mVisibleFromClient) {
3202 r.activity.makeVisible();
3203 }
3204 }
3205 if (r.newConfig != null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003206 if (DEBUG_CONFIGURATION) Log.v(TAG, "Updating activity vis "
3207 + r.activityInfo.name + " with new config " + r.newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208 performConfigurationChanged(r.activity, r.newConfig);
3209 r.newConfig = null;
3210 }
3211 } else {
3212 if (r.activity.mVisibleFromServer) {
3213 r.activity.mVisibleFromServer = false;
3214 mNumVisibleActivities--;
3215 v.setVisibility(View.INVISIBLE);
3216 }
3217 }
3218 }
3219 }
3220
3221 private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
3222 ActivityRecord r = mActivities.get(token);
3223 r.activity.mConfigChangeFlags |= configChanges;
3224
3225 StopInfo info = new StopInfo();
3226 performStopActivityInner(r, info, show);
3227
3228 if (localLOGV) Log.v(
3229 TAG, "Finishing stop of " + r + ": show=" + show
3230 + " win=" + r.window);
3231
3232 updateVisibility(r, show);
Bob Leee5408332009-09-04 18:31:17 -07003233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234 // Tell activity manager we have been stopped.
3235 try {
3236 ActivityManagerNative.getDefault().activityStopped(
3237 r.token, info.thumbnail, info.description);
3238 } catch (RemoteException ex) {
3239 }
3240 }
3241
3242 final void performRestartActivity(IBinder token) {
3243 ActivityRecord r = mActivities.get(token);
3244 if (r.stopped) {
3245 r.activity.performRestart();
3246 r.stopped = false;
3247 }
3248 }
3249
3250 private final void handleWindowVisibility(IBinder token, boolean show) {
3251 ActivityRecord r = mActivities.get(token);
3252 if (!show && !r.stopped) {
3253 performStopActivityInner(r, null, show);
3254 } else if (show && r.stopped) {
3255 // If we are getting ready to gc after going to the background, well
3256 // we are back active so skip it.
3257 unscheduleGcIdler();
3258
3259 r.activity.performRestart();
3260 r.stopped = false;
3261 }
3262 if (r.activity.mDecor != null) {
3263 if (Config.LOGV) Log.v(
3264 TAG, "Handle window " + r + " visibility: " + show);
3265 updateVisibility(r, show);
3266 }
3267 }
3268
3269 private final void deliverResults(ActivityRecord r, List<ResultInfo> results) {
3270 final int N = results.size();
3271 for (int i=0; i<N; i++) {
3272 ResultInfo ri = results.get(i);
3273 try {
3274 if (ri.mData != null) {
3275 ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
3276 }
Chris Tate8a7dc172009-03-24 20:11:42 -07003277 if (DEBUG_RESULTS) Log.v(TAG,
3278 "Delivering result to activity " + r + " : " + ri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003279 r.activity.dispatchActivityResult(ri.mResultWho,
3280 ri.mRequestCode, ri.mResultCode, ri.mData);
3281 } catch (Exception e) {
3282 if (!mInstrumentation.onException(r.activity, e)) {
3283 throw new RuntimeException(
3284 "Failure delivering result " + ri + " to activity "
3285 + r.intent.getComponent().toShortString()
3286 + ": " + e.toString(), e);
3287 }
3288 }
3289 }
3290 }
3291
3292 private final void handleSendResult(ResultData res) {
3293 ActivityRecord r = mActivities.get(res.token);
Chris Tate8a7dc172009-03-24 20:11:42 -07003294 if (DEBUG_RESULTS) Log.v(TAG, "Handling send result to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 if (r != null) {
3296 final boolean resumed = !r.paused;
3297 if (!r.activity.mFinished && r.activity.mDecor != null
3298 && r.hideForNow && resumed) {
3299 // We had hidden the activity because it started another
3300 // one... we have gotten a result back and we are not
3301 // paused, so make sure our window is visible.
3302 updateVisibility(r, true);
3303 }
3304 if (resumed) {
3305 try {
3306 // Now we are idle.
3307 r.activity.mCalled = false;
3308 mInstrumentation.callActivityOnPause(r.activity);
3309 if (!r.activity.mCalled) {
3310 throw new SuperNotCalledException(
3311 "Activity " + r.intent.getComponent().toShortString()
3312 + " did not call through to super.onPause()");
3313 }
3314 } catch (SuperNotCalledException e) {
3315 throw e;
3316 } catch (Exception e) {
3317 if (!mInstrumentation.onException(r.activity, e)) {
3318 throw new RuntimeException(
3319 "Unable to pause activity "
3320 + r.intent.getComponent().toShortString()
3321 + ": " + e.toString(), e);
3322 }
3323 }
3324 }
3325 deliverResults(r, res.results);
3326 if (resumed) {
3327 mInstrumentation.callActivityOnResume(r.activity);
3328 }
3329 }
3330 }
3331
3332 public final ActivityRecord performDestroyActivity(IBinder token, boolean finishing) {
3333 return performDestroyActivity(token, finishing, 0, false);
3334 }
3335
3336 private final ActivityRecord performDestroyActivity(IBinder token, boolean finishing,
3337 int configChanges, boolean getNonConfigInstance) {
3338 ActivityRecord r = mActivities.get(token);
3339 if (localLOGV) Log.v(TAG, "Performing finish of " + r);
3340 if (r != null) {
3341 r.activity.mConfigChangeFlags |= configChanges;
3342 if (finishing) {
3343 r.activity.mFinished = true;
3344 }
3345 if (!r.paused) {
3346 try {
3347 r.activity.mCalled = false;
3348 mInstrumentation.callActivityOnPause(r.activity);
Bob Leee5408332009-09-04 18:31:17 -07003349 EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003350 r.activity.getComponentName().getClassName());
3351 if (!r.activity.mCalled) {
3352 throw new SuperNotCalledException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003353 "Activity " + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003354 + " did not call through to super.onPause()");
3355 }
3356 } catch (SuperNotCalledException e) {
3357 throw e;
3358 } catch (Exception e) {
3359 if (!mInstrumentation.onException(r.activity, e)) {
3360 throw new RuntimeException(
3361 "Unable to pause activity "
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003362 + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 + ": " + e.toString(), e);
3364 }
3365 }
3366 r.paused = true;
3367 }
3368 if (!r.stopped) {
3369 try {
3370 r.activity.performStop();
3371 } catch (SuperNotCalledException e) {
3372 throw e;
3373 } catch (Exception e) {
3374 if (!mInstrumentation.onException(r.activity, e)) {
3375 throw new RuntimeException(
3376 "Unable to stop activity "
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003377 + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003378 + ": " + e.toString(), e);
3379 }
3380 }
3381 r.stopped = true;
3382 }
3383 if (getNonConfigInstance) {
3384 try {
3385 r.lastNonConfigurationInstance
3386 = r.activity.onRetainNonConfigurationInstance();
3387 } catch (Exception e) {
3388 if (!mInstrumentation.onException(r.activity, e)) {
3389 throw new RuntimeException(
3390 "Unable to retain activity "
3391 + r.intent.getComponent().toShortString()
3392 + ": " + e.toString(), e);
3393 }
3394 }
3395 try {
3396 r.lastNonConfigurationChildInstances
3397 = r.activity.onRetainNonConfigurationChildInstances();
3398 } catch (Exception e) {
3399 if (!mInstrumentation.onException(r.activity, e)) {
3400 throw new RuntimeException(
3401 "Unable to retain child activities "
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003402 + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003403 + ": " + e.toString(), e);
3404 }
3405 }
Bob Leee5408332009-09-04 18:31:17 -07003406
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003407 }
3408 try {
3409 r.activity.mCalled = false;
3410 r.activity.onDestroy();
3411 if (!r.activity.mCalled) {
3412 throw new SuperNotCalledException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003413 "Activity " + safeToComponentShortString(r.intent) +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003414 " did not call through to super.onDestroy()");
3415 }
3416 if (r.window != null) {
3417 r.window.closeAllPanels();
3418 }
3419 } catch (SuperNotCalledException e) {
3420 throw e;
3421 } catch (Exception e) {
3422 if (!mInstrumentation.onException(r.activity, e)) {
3423 throw new RuntimeException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003424 "Unable to destroy activity " + safeToComponentShortString(r.intent)
3425 + ": " + e.toString(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 }
3427 }
3428 }
3429 mActivities.remove(token);
3430
3431 return r;
3432 }
3433
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003434 private static String safeToComponentShortString(Intent intent) {
3435 ComponentName component = intent.getComponent();
3436 return component == null ? "[Unknown]" : component.toShortString();
3437 }
3438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003439 private final void handleDestroyActivity(IBinder token, boolean finishing,
3440 int configChanges, boolean getNonConfigInstance) {
3441 ActivityRecord r = performDestroyActivity(token, finishing,
3442 configChanges, getNonConfigInstance);
3443 if (r != null) {
3444 WindowManager wm = r.activity.getWindowManager();
3445 View v = r.activity.mDecor;
3446 if (v != null) {
3447 if (r.activity.mVisibleFromServer) {
3448 mNumVisibleActivities--;
3449 }
3450 IBinder wtoken = v.getWindowToken();
3451 if (r.activity.mWindowAdded) {
3452 wm.removeViewImmediate(v);
3453 }
3454 if (wtoken != null) {
3455 WindowManagerImpl.getDefault().closeAll(wtoken,
3456 r.activity.getClass().getName(), "Activity");
3457 }
3458 r.activity.mDecor = null;
3459 }
3460 WindowManagerImpl.getDefault().closeAll(token,
3461 r.activity.getClass().getName(), "Activity");
3462
3463 // Mocked out contexts won't be participating in the normal
3464 // process lifecycle, but if we're running with a proper
3465 // ApplicationContext we need to have it tear down things
3466 // cleanly.
3467 Context c = r.activity.getBaseContext();
3468 if (c instanceof ApplicationContext) {
3469 ((ApplicationContext) c).scheduleFinalCleanup(
3470 r.activity.getClass().getName(), "Activity");
3471 }
3472 }
3473 if (finishing) {
3474 try {
3475 ActivityManagerNative.getDefault().activityDestroyed(token);
3476 } catch (RemoteException ex) {
3477 // If the system process has died, it's game over for everyone.
3478 }
3479 }
3480 }
3481
3482 private final void handleRelaunchActivity(ActivityRecord tmp, int configChanges) {
3483 // If we are getting ready to gc after going to the background, well
3484 // we are back active so skip it.
3485 unscheduleGcIdler();
3486
3487 Configuration changedConfig = null;
Bob Leee5408332009-09-04 18:31:17 -07003488
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003489 if (DEBUG_CONFIGURATION) Log.v(TAG, "Relaunching activity "
3490 + tmp.token + " with configChanges=0x"
3491 + Integer.toHexString(configChanges));
3492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003493 // First: make sure we have the most recent configuration and most
3494 // recent version of the activity, or skip it if some previous call
3495 // had taken a more recent version.
3496 synchronized (mRelaunchingActivities) {
3497 int N = mRelaunchingActivities.size();
3498 IBinder token = tmp.token;
3499 tmp = null;
3500 for (int i=0; i<N; i++) {
3501 ActivityRecord r = mRelaunchingActivities.get(i);
3502 if (r.token == token) {
3503 tmp = r;
3504 mRelaunchingActivities.remove(i);
3505 i--;
3506 N--;
3507 }
3508 }
Bob Leee5408332009-09-04 18:31:17 -07003509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510 if (tmp == null) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003511 if (DEBUG_CONFIGURATION) Log.v(TAG, "Abort, activity not relaunching!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003512 return;
3513 }
Bob Leee5408332009-09-04 18:31:17 -07003514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 if (mPendingConfiguration != null) {
3516 changedConfig = mPendingConfiguration;
3517 mPendingConfiguration = null;
3518 }
3519 }
Bob Leee5408332009-09-04 18:31:17 -07003520
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003521 if (DEBUG_CONFIGURATION) Log.v(TAG, "Relaunching activity "
3522 + tmp.token + ": changedConfig=" + changedConfig);
3523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524 // If there was a pending configuration change, execute it first.
3525 if (changedConfig != null) {
3526 handleConfigurationChanged(changedConfig);
3527 }
Bob Leee5408332009-09-04 18:31:17 -07003528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 ActivityRecord r = mActivities.get(tmp.token);
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003530 if (DEBUG_CONFIGURATION) Log.v(TAG, "Handling relaunch of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003531 if (r == null) {
3532 return;
3533 }
Bob Leee5408332009-09-04 18:31:17 -07003534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003535 r.activity.mConfigChangeFlags |= configChanges;
Christopher Tateb70f3df2009-04-07 16:07:59 -07003536 Intent currentIntent = r.activity.mIntent;
Bob Leee5408332009-09-04 18:31:17 -07003537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538 Bundle savedState = null;
3539 if (!r.paused) {
3540 savedState = performPauseActivity(r.token, false, true);
3541 }
Bob Leee5408332009-09-04 18:31:17 -07003542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543 handleDestroyActivity(r.token, false, configChanges, true);
Bob Leee5408332009-09-04 18:31:17 -07003544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545 r.activity = null;
3546 r.window = null;
3547 r.hideForNow = false;
3548 r.nextIdle = null;
The Android Open Source Project10592532009-03-18 17:39:46 -07003549 // Merge any pending results and pending intents; don't just replace them
3550 if (tmp.pendingResults != null) {
3551 if (r.pendingResults == null) {
3552 r.pendingResults = tmp.pendingResults;
3553 } else {
3554 r.pendingResults.addAll(tmp.pendingResults);
3555 }
3556 }
3557 if (tmp.pendingIntents != null) {
3558 if (r.pendingIntents == null) {
3559 r.pendingIntents = tmp.pendingIntents;
3560 } else {
3561 r.pendingIntents.addAll(tmp.pendingIntents);
3562 }
3563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003564 r.startsNotResumed = tmp.startsNotResumed;
3565 if (savedState != null) {
3566 r.state = savedState;
3567 }
Bob Leee5408332009-09-04 18:31:17 -07003568
Christopher Tateb70f3df2009-04-07 16:07:59 -07003569 handleLaunchActivity(r, currentIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 }
3571
3572 private final void handleRequestThumbnail(IBinder token) {
3573 ActivityRecord r = mActivities.get(token);
3574 Bitmap thumbnail = createThumbnailBitmap(r);
3575 CharSequence description = null;
3576 try {
3577 description = r.activity.onCreateDescription();
3578 } catch (Exception e) {
3579 if (!mInstrumentation.onException(r.activity, e)) {
3580 throw new RuntimeException(
3581 "Unable to create description of activity "
3582 + r.intent.getComponent().toShortString()
3583 + ": " + e.toString(), e);
3584 }
3585 }
3586 //System.out.println("Reporting top thumbnail " + thumbnail);
3587 try {
3588 ActivityManagerNative.getDefault().reportThumbnail(
3589 token, thumbnail, description);
3590 } catch (RemoteException ex) {
3591 }
3592 }
3593
3594 ArrayList<ComponentCallbacks> collectComponentCallbacksLocked(
3595 boolean allActivities, Configuration newConfig) {
3596 ArrayList<ComponentCallbacks> callbacks
3597 = new ArrayList<ComponentCallbacks>();
Bob Leee5408332009-09-04 18:31:17 -07003598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 if (mActivities.size() > 0) {
3600 Iterator<ActivityRecord> it = mActivities.values().iterator();
3601 while (it.hasNext()) {
3602 ActivityRecord ar = it.next();
3603 Activity a = ar.activity;
3604 if (a != null) {
3605 if (!ar.activity.mFinished && (allActivities ||
3606 (a != null && !ar.paused))) {
3607 // If the activity is currently resumed, its configuration
3608 // needs to change right now.
3609 callbacks.add(a);
3610 } else if (newConfig != null) {
3611 // Otherwise, we will tell it about the change
3612 // the next time it is resumed or shown. Note that
3613 // the activity manager may, before then, decide the
3614 // activity needs to be destroyed to handle its new
3615 // configuration.
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003616 if (DEBUG_CONFIGURATION) Log.v(TAG, "Setting activity "
3617 + ar.activityInfo.name + " newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 ar.newConfig = newConfig;
3619 }
3620 }
3621 }
3622 }
3623 if (mServices.size() > 0) {
3624 Iterator<Service> it = mServices.values().iterator();
3625 while (it.hasNext()) {
3626 callbacks.add(it.next());
3627 }
3628 }
3629 synchronized (mProviderMap) {
3630 if (mLocalProviders.size() > 0) {
3631 Iterator<ProviderRecord> it = mLocalProviders.values().iterator();
3632 while (it.hasNext()) {
3633 callbacks.add(it.next().mLocalProvider);
3634 }
3635 }
3636 }
3637 final int N = mAllApplications.size();
3638 for (int i=0; i<N; i++) {
3639 callbacks.add(mAllApplications.get(i));
3640 }
Bob Leee5408332009-09-04 18:31:17 -07003641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 return callbacks;
3643 }
Bob Leee5408332009-09-04 18:31:17 -07003644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003645 private final void performConfigurationChanged(
3646 ComponentCallbacks cb, Configuration config) {
3647 // Only for Activity objects, check that they actually call up to their
3648 // superclass implementation. ComponentCallbacks is an interface, so
3649 // we check the runtime type and act accordingly.
3650 Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
3651 if (activity != null) {
3652 activity.mCalled = false;
3653 }
Bob Leee5408332009-09-04 18:31:17 -07003654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003655 boolean shouldChangeConfig = false;
3656 if ((activity == null) || (activity.mCurrentConfig == null)) {
3657 shouldChangeConfig = true;
3658 } else {
Bob Leee5408332009-09-04 18:31:17 -07003659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 // If the new config is the same as the config this Activity
3661 // is already running with then don't bother calling
3662 // onConfigurationChanged
3663 int diff = activity.mCurrentConfig.diff(config);
3664 if (diff != 0) {
Bob Leee5408332009-09-04 18:31:17 -07003665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003666 // If this activity doesn't handle any of the config changes
3667 // then don't bother calling onConfigurationChanged as we're
3668 // going to destroy it.
3669 if ((~activity.mActivityInfo.configChanges & diff) == 0) {
3670 shouldChangeConfig = true;
3671 }
3672 }
3673 }
Bob Leee5408332009-09-04 18:31:17 -07003674
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003675 if (DEBUG_CONFIGURATION) Log.v(TAG, "Config callback " + cb
3676 + ": shouldChangeConfig=" + shouldChangeConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003677 if (shouldChangeConfig) {
3678 cb.onConfigurationChanged(config);
Bob Leee5408332009-09-04 18:31:17 -07003679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 if (activity != null) {
3681 if (!activity.mCalled) {
3682 throw new SuperNotCalledException(
3683 "Activity " + activity.getLocalClassName() +
3684 " did not call through to super.onConfigurationChanged()");
3685 }
3686 activity.mConfigChangeFlags = 0;
3687 activity.mCurrentConfig = new Configuration(config);
3688 }
3689 }
3690 }
3691
3692 final void handleConfigurationChanged(Configuration config) {
Bob Leee5408332009-09-04 18:31:17 -07003693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 synchronized (mRelaunchingActivities) {
3695 if (mPendingConfiguration != null) {
3696 config = mPendingConfiguration;
3697 mPendingConfiguration = null;
3698 }
3699 }
Bob Leee5408332009-09-04 18:31:17 -07003700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 ArrayList<ComponentCallbacks> callbacks
3702 = new ArrayList<ComponentCallbacks>();
Bob Leee5408332009-09-04 18:31:17 -07003703
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003704 if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle configuration changed: "
3705 + config);
3706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003707 synchronized(mPackages) {
3708 if (mConfiguration == null) {
3709 mConfiguration = new Configuration();
3710 }
3711 mConfiguration.updateFrom(config);
3712 DisplayMetrics dm = getDisplayMetricsLocked(true);
3713
3714 // set it for java, this also affects newly created Resources
3715 if (config.locale != null) {
3716 Locale.setDefault(config.locale);
3717 }
3718
Dianne Hackborn0d907fa2009-07-27 20:48:50 -07003719 Resources.updateSystemConfiguration(config, dm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720
3721 ApplicationContext.ApplicationPackageManager.configurationChanged();
3722 //Log.i(TAG, "Configuration changed in " + currentPackageName());
3723 {
3724 Iterator<WeakReference<Resources>> it =
3725 mActiveResources.values().iterator();
3726 //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
3727 // mActiveResources.entrySet().iterator();
3728 while (it.hasNext()) {
3729 WeakReference<Resources> v = it.next();
3730 Resources r = v.get();
3731 if (r != null) {
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07003732 r.updateConfiguration(config, dm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003733 //Log.i(TAG, "Updated app resources " + v.getKey()
3734 // + " " + r + ": " + r.getConfiguration());
3735 } else {
3736 //Log.i(TAG, "Removing old resources " + v.getKey());
3737 it.remove();
3738 }
3739 }
3740 }
Bob Leee5408332009-09-04 18:31:17 -07003741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742 callbacks = collectComponentCallbacksLocked(false, config);
3743 }
Bob Leee5408332009-09-04 18:31:17 -07003744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 final int N = callbacks.size();
3746 for (int i=0; i<N; i++) {
3747 performConfigurationChanged(callbacks.get(i), config);
3748 }
3749 }
3750
3751 final void handleActivityConfigurationChanged(IBinder token) {
3752 ActivityRecord r = mActivities.get(token);
3753 if (r == null || r.activity == null) {
3754 return;
3755 }
Bob Leee5408332009-09-04 18:31:17 -07003756
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003757 if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle activity config changed: "
3758 + r.activityInfo.name);
3759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760 performConfigurationChanged(r.activity, mConfiguration);
3761 }
3762
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07003763 final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08003764 if (start) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08003765 try {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07003766 Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
3767 8 * 1024 * 1024, 0);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08003768 } catch (RuntimeException e) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07003769 Log.w(TAG, "Profiling failed on path " + pcd.path
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08003770 + " -- can the process access this path?");
Dianne Hackborn9c8dd552009-06-23 19:22:52 -07003771 } finally {
3772 try {
3773 pcd.fd.close();
3774 } catch (IOException e) {
3775 Log.w(TAG, "Failure closing profile fd", e);
3776 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08003777 }
3778 } else {
3779 Debug.stopMethodTracing();
3780 }
3781 }
Bob Leee5408332009-09-04 18:31:17 -07003782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 final void handleLowMemory() {
3784 ArrayList<ComponentCallbacks> callbacks
3785 = new ArrayList<ComponentCallbacks>();
3786
3787 synchronized(mPackages) {
3788 callbacks = collectComponentCallbacksLocked(true, null);
3789 }
Bob Leee5408332009-09-04 18:31:17 -07003790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003791 final int N = callbacks.size();
3792 for (int i=0; i<N; i++) {
3793 callbacks.get(i).onLowMemory();
3794 }
3795
Chris Tatece229052009-03-25 16:44:52 -07003796 // Ask SQLite to free up as much memory as it can, mostly from its page caches.
3797 if (Process.myUid() != Process.SYSTEM_UID) {
3798 int sqliteReleased = SQLiteDatabase.releaseMemory();
3799 EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
3800 }
Bob Leee5408332009-09-04 18:31:17 -07003801
Mike Reedcaf0df12009-04-27 14:32:05 -04003802 // Ask graphics to free up as much as possible (font/image caches)
3803 Canvas.freeCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804
3805 BinderInternal.forceGc("mem");
3806 }
3807
3808 private final void handleBindApplication(AppBindData data) {
3809 mBoundApplication = data;
3810 mConfiguration = new Configuration(data.config);
3811
3812 // We now rely on this being set by zygote.
3813 //Process.setGid(data.appInfo.gid);
3814 //Process.setUid(data.appInfo.uid);
3815
3816 // send up app name; do this *before* waiting for debugger
3817 android.ddm.DdmHandleAppName.setAppName(data.processName);
3818
3819 /*
3820 * Before spawning a new process, reset the time zone to be the system time zone.
3821 * This needs to be done because the system time zone could have changed after the
3822 * the spawning of this process. Without doing this this process would have the incorrect
3823 * system time zone.
3824 */
3825 TimeZone.setDefault(null);
3826
3827 /*
3828 * Initialize the default locale in this process for the reasons we set the time zone.
3829 */
3830 Locale.setDefault(data.config.locale);
3831
Suchi Amalapurapuc9843292009-06-24 17:02:25 -07003832 /*
3833 * Update the system configuration since its preloaded and might not
3834 * reflect configuration changes. The configuration object passed
3835 * in AppBindData can be safely assumed to be up to date
3836 */
3837 Resources.getSystem().updateConfiguration(mConfiguration, null);
3838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 data.info = getPackageInfoNoCheck(data.appInfo);
3840
Dianne Hackborn96e240f2009-07-26 17:42:30 -07003841 /**
3842 * Switch this process to density compatibility mode if needed.
3843 */
3844 if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
3845 == 0) {
3846 Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
3847 }
Bob Leee5408332009-09-04 18:31:17 -07003848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003849 if (data.debugMode != IApplicationThread.DEBUG_OFF) {
3850 // XXX should have option to change the port.
3851 Debug.changeDebugPort(8100);
3852 if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
3853 Log.w(TAG, "Application " + data.info.getPackageName()
3854 + " is waiting for the debugger on port 8100...");
3855
3856 IActivityManager mgr = ActivityManagerNative.getDefault();
3857 try {
3858 mgr.showWaitingForDebugger(mAppThread, true);
3859 } catch (RemoteException ex) {
3860 }
3861
3862 Debug.waitForDebugger();
3863
3864 try {
3865 mgr.showWaitingForDebugger(mAppThread, false);
3866 } catch (RemoteException ex) {
3867 }
3868
3869 } else {
3870 Log.w(TAG, "Application " + data.info.getPackageName()
3871 + " can be debugged on port 8100...");
3872 }
3873 }
3874
3875 if (data.instrumentationName != null) {
3876 ApplicationContext appContext = new ApplicationContext();
3877 appContext.init(data.info, null, this);
3878 InstrumentationInfo ii = null;
3879 try {
3880 ii = appContext.getPackageManager().
3881 getInstrumentationInfo(data.instrumentationName, 0);
3882 } catch (PackageManager.NameNotFoundException e) {
3883 }
3884 if (ii == null) {
3885 throw new RuntimeException(
3886 "Unable to find instrumentation info for: "
3887 + data.instrumentationName);
3888 }
3889
3890 mInstrumentationAppDir = ii.sourceDir;
3891 mInstrumentationAppPackage = ii.packageName;
3892 mInstrumentedAppDir = data.info.getAppDir();
3893
3894 ApplicationInfo instrApp = new ApplicationInfo();
3895 instrApp.packageName = ii.packageName;
3896 instrApp.sourceDir = ii.sourceDir;
3897 instrApp.publicSourceDir = ii.publicSourceDir;
3898 instrApp.dataDir = ii.dataDir;
3899 PackageInfo pi = getPackageInfo(instrApp,
3900 appContext.getClassLoader(), false, true);
3901 ApplicationContext instrContext = new ApplicationContext();
3902 instrContext.init(pi, null, this);
3903
3904 try {
3905 java.lang.ClassLoader cl = instrContext.getClassLoader();
3906 mInstrumentation = (Instrumentation)
3907 cl.loadClass(data.instrumentationName.getClassName()).newInstance();
3908 } catch (Exception e) {
3909 throw new RuntimeException(
3910 "Unable to instantiate instrumentation "
3911 + data.instrumentationName + ": " + e.toString(), e);
3912 }
3913
3914 mInstrumentation.init(this, instrContext, appContext,
3915 new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
3916
3917 if (data.profileFile != null && !ii.handleProfiling) {
3918 data.handlingProfiling = true;
3919 File file = new File(data.profileFile);
3920 file.getParentFile().mkdirs();
3921 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
3922 }
3923
3924 try {
3925 mInstrumentation.onCreate(data.instrumentationArgs);
3926 }
3927 catch (Exception e) {
3928 throw new RuntimeException(
3929 "Exception thrown in onCreate() of "
3930 + data.instrumentationName + ": " + e.toString(), e);
3931 }
3932
3933 } else {
3934 mInstrumentation = new Instrumentation();
3935 }
3936
Christopher Tate181fafa2009-05-14 11:12:14 -07003937 // If the app is being launched for full backup or restore, bring it up in
3938 // a restricted environment with the base application class.
3939 Application app = data.info.makeApplication(data.restrictedBackupMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003940 mInitialApplication = app;
3941
3942 List<ProviderInfo> providers = data.providers;
3943 if (providers != null) {
3944 installContentProviders(app, providers);
3945 }
3946
3947 try {
3948 mInstrumentation.callApplicationOnCreate(app);
3949 } catch (Exception e) {
3950 if (!mInstrumentation.onException(app, e)) {
3951 throw new RuntimeException(
3952 "Unable to create application " + app.getClass().getName()
3953 + ": " + e.toString(), e);
3954 }
3955 }
3956 }
3957
3958 /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
3959 IActivityManager am = ActivityManagerNative.getDefault();
3960 if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) {
3961 Debug.stopMethodTracing();
3962 }
3963 //Log.i(TAG, "am: " + ActivityManagerNative.getDefault()
3964 // + ", app thr: " + mAppThread);
3965 try {
3966 am.finishInstrumentation(mAppThread, resultCode, results);
3967 } catch (RemoteException ex) {
3968 }
3969 }
3970
3971 private final void installContentProviders(
3972 Context context, List<ProviderInfo> providers) {
3973 final ArrayList<IActivityManager.ContentProviderHolder> results =
3974 new ArrayList<IActivityManager.ContentProviderHolder>();
3975
3976 Iterator<ProviderInfo> i = providers.iterator();
3977 while (i.hasNext()) {
3978 ProviderInfo cpi = i.next();
3979 StringBuilder buf = new StringBuilder(128);
3980 buf.append("Publishing provider ");
3981 buf.append(cpi.authority);
3982 buf.append(": ");
3983 buf.append(cpi.name);
3984 Log.i(TAG, buf.toString());
3985 IContentProvider cp = installProvider(context, null, cpi, false);
3986 if (cp != null) {
3987 IActivityManager.ContentProviderHolder cph =
3988 new IActivityManager.ContentProviderHolder(cpi);
3989 cph.provider = cp;
3990 results.add(cph);
3991 // Don't ever unload this provider from the process.
3992 synchronized(mProviderMap) {
3993 mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
3994 }
3995 }
3996 }
3997
3998 try {
3999 ActivityManagerNative.getDefault().publishContentProviders(
4000 getApplicationThread(), results);
4001 } catch (RemoteException ex) {
4002 }
4003 }
4004
4005 private final IContentProvider getProvider(Context context, String name) {
4006 synchronized(mProviderMap) {
4007 final ProviderRecord pr = mProviderMap.get(name);
4008 if (pr != null) {
4009 return pr.mProvider;
4010 }
4011 }
4012
4013 IActivityManager.ContentProviderHolder holder = null;
4014 try {
4015 holder = ActivityManagerNative.getDefault().getContentProvider(
4016 getApplicationThread(), name);
4017 } catch (RemoteException ex) {
4018 }
4019 if (holder == null) {
4020 Log.e(TAG, "Failed to find provider info for " + name);
4021 return null;
4022 }
4023 if (holder.permissionFailure != null) {
4024 throw new SecurityException("Permission " + holder.permissionFailure
4025 + " required for provider " + name);
4026 }
4027
4028 IContentProvider prov = installProvider(context, holder.provider,
4029 holder.info, true);
4030 //Log.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
4031 if (holder.noReleaseNeeded || holder.provider == null) {
4032 // We are not going to release the provider if it is an external
4033 // provider that doesn't care about being released, or if it is
4034 // a local provider running in this process.
4035 //Log.i(TAG, "*** NO RELEASE NEEDED");
4036 synchronized(mProviderMap) {
4037 mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
4038 }
4039 }
4040 return prov;
4041 }
4042
4043 public final IContentProvider acquireProvider(Context c, String name) {
4044 IContentProvider provider = getProvider(c, name);
4045 if(provider == null)
4046 return null;
4047 IBinder jBinder = provider.asBinder();
4048 synchronized(mProviderMap) {
4049 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4050 if(prc == null) {
4051 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
4052 } else {
4053 prc.count++;
4054 } //end else
4055 } //end synchronized
4056 return provider;
4057 }
4058
4059 public final boolean releaseProvider(IContentProvider provider) {
4060 if(provider == null) {
4061 return false;
4062 }
4063 IBinder jBinder = provider.asBinder();
4064 synchronized(mProviderMap) {
4065 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4066 if(prc == null) {
4067 if(localLOGV) Log.v(TAG, "releaseProvider::Weird shouldnt be here");
4068 return false;
4069 } else {
4070 prc.count--;
4071 if(prc.count == 0) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004072 // Schedule the actual remove asynchronously, since we
4073 // don't know the context this will be called in.
4074 Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
4075 mH.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004076 } //end if
4077 } //end else
4078 } //end synchronized
4079 return true;
4080 }
4081
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07004082 final void completeRemoveProvider(IContentProvider provider) {
4083 IBinder jBinder = provider.asBinder();
4084 synchronized(mProviderMap) {
4085 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4086 if(prc != null && prc.count == 0) {
4087 mProviderRefCountMap.remove(jBinder);
4088 //invoke removeProvider to dereference provider
4089 removeProviderLocked(provider);
4090 }
4091 }
4092 }
4093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004094 public final void removeProviderLocked(IContentProvider provider) {
4095 if (provider == null) {
4096 return;
4097 }
4098 IBinder providerBinder = provider.asBinder();
4099 boolean amRemoveFlag = false;
4100
4101 // remove the provider from mProviderMap
4102 Iterator<ProviderRecord> iter = mProviderMap.values().iterator();
4103 while (iter.hasNext()) {
4104 ProviderRecord pr = iter.next();
4105 IBinder myBinder = pr.mProvider.asBinder();
4106 if (myBinder == providerBinder) {
4107 //find if its published by this process itself
4108 if(pr.mLocalProvider != null) {
4109 if(localLOGV) Log.i(TAG, "removeProvider::found local provider returning");
4110 return;
4111 }
4112 if(localLOGV) Log.v(TAG, "removeProvider::Not local provider Unlinking " +
4113 "death recipient");
4114 //content provider is in another process
4115 myBinder.unlinkToDeath(pr, 0);
4116 iter.remove();
4117 //invoke remove only once for the very first name seen
4118 if(!amRemoveFlag) {
4119 try {
4120 if(localLOGV) Log.v(TAG, "removeProvider::Invoking " +
4121 "ActivityManagerNative.removeContentProvider("+pr.mName);
4122 ActivityManagerNative.getDefault().removeContentProvider(getApplicationThread(), pr.mName);
4123 amRemoveFlag = true;
4124 } catch (RemoteException e) {
4125 //do nothing content provider object is dead any way
4126 } //end catch
4127 }
4128 } //end if myBinder
4129 } //end while iter
4130 }
4131
4132 final void removeDeadProvider(String name, IContentProvider provider) {
4133 synchronized(mProviderMap) {
4134 ProviderRecord pr = mProviderMap.get(name);
4135 if (pr.mProvider.asBinder() == provider.asBinder()) {
4136 Log.i(TAG, "Removing dead content provider: " + name);
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004137 ProviderRecord removed = mProviderMap.remove(name);
4138 if (removed != null) {
4139 removed.mProvider.asBinder().unlinkToDeath(removed, 0);
4140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004141 }
4142 }
4143 }
4144
4145 final void removeDeadProviderLocked(String name, IContentProvider provider) {
4146 ProviderRecord pr = mProviderMap.get(name);
4147 if (pr.mProvider.asBinder() == provider.asBinder()) {
4148 Log.i(TAG, "Removing dead content provider: " + name);
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004149 ProviderRecord removed = mProviderMap.remove(name);
4150 if (removed != null) {
4151 removed.mProvider.asBinder().unlinkToDeath(removed, 0);
4152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004153 }
4154 }
4155
4156 private final IContentProvider installProvider(Context context,
4157 IContentProvider provider, ProviderInfo info, boolean noisy) {
4158 ContentProvider localProvider = null;
4159 if (provider == null) {
4160 if (noisy) {
4161 Log.d(TAG, "Loading provider " + info.authority + ": "
4162 + info.name);
4163 }
4164 Context c = null;
4165 ApplicationInfo ai = info.applicationInfo;
4166 if (context.getPackageName().equals(ai.packageName)) {
4167 c = context;
4168 } else if (mInitialApplication != null &&
4169 mInitialApplication.getPackageName().equals(ai.packageName)) {
4170 c = mInitialApplication;
4171 } else {
4172 try {
4173 c = context.createPackageContext(ai.packageName,
4174 Context.CONTEXT_INCLUDE_CODE);
4175 } catch (PackageManager.NameNotFoundException e) {
4176 }
4177 }
4178 if (c == null) {
4179 Log.w(TAG, "Unable to get context for package " +
4180 ai.packageName +
4181 " while loading content provider " +
4182 info.name);
4183 return null;
4184 }
4185 try {
4186 final java.lang.ClassLoader cl = c.getClassLoader();
4187 localProvider = (ContentProvider)cl.
4188 loadClass(info.name).newInstance();
4189 provider = localProvider.getIContentProvider();
4190 if (provider == null) {
4191 Log.e(TAG, "Failed to instantiate class " +
4192 info.name + " from sourceDir " +
4193 info.applicationInfo.sourceDir);
4194 return null;
4195 }
4196 if (Config.LOGV) Log.v(
4197 TAG, "Instantiating local provider " + info.name);
4198 // XXX Need to create the correct context for this provider.
4199 localProvider.attachInfo(c, info);
4200 } catch (java.lang.Exception e) {
4201 if (!mInstrumentation.onException(null, e)) {
4202 throw new RuntimeException(
4203 "Unable to get provider " + info.name
4204 + ": " + e.toString(), e);
4205 }
4206 return null;
4207 }
4208 } else if (localLOGV) {
4209 Log.v(TAG, "Installing external provider " + info.authority + ": "
4210 + info.name);
4211 }
4212
4213 synchronized (mProviderMap) {
4214 // Cache the pointer for the remote provider.
4215 String names[] = PATTERN_SEMICOLON.split(info.authority);
4216 for (int i=0; i<names.length; i++) {
4217 ProviderRecord pr = new ProviderRecord(names[i], provider,
4218 localProvider);
4219 try {
4220 provider.asBinder().linkToDeath(pr, 0);
4221 mProviderMap.put(names[i], pr);
4222 } catch (RemoteException e) {
4223 return null;
4224 }
4225 }
4226 if (localProvider != null) {
4227 mLocalProviders.put(provider.asBinder(),
4228 new ProviderRecord(null, provider, localProvider));
4229 }
4230 }
4231
4232 return provider;
4233 }
4234
4235 private final void attach(boolean system) {
4236 sThreadLocal.set(this);
4237 mSystemThread = system;
4238 AndroidHttpClient.setThreadBlocked(true);
4239 if (!system) {
4240 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
4241 RuntimeInit.setApplicationObject(mAppThread.asBinder());
4242 IActivityManager mgr = ActivityManagerNative.getDefault();
4243 try {
4244 mgr.attachApplication(mAppThread);
4245 } catch (RemoteException ex) {
4246 }
4247 } else {
4248 // Don't set application object here -- if the system crashes,
4249 // we can't display an alert, we just want to die die die.
4250 android.ddm.DdmHandleAppName.setAppName("system_process");
4251 try {
4252 mInstrumentation = new Instrumentation();
4253 ApplicationContext context = new ApplicationContext();
4254 context.init(getSystemContext().mPackageInfo, null, this);
4255 Application app = Instrumentation.newApplication(Application.class, context);
4256 mAllApplications.add(app);
4257 mInitialApplication = app;
4258 app.onCreate();
4259 } catch (Exception e) {
4260 throw new RuntimeException(
4261 "Unable to instantiate Application():" + e.toString(), e);
4262 }
4263 }
4264 }
4265
4266 private final void detach()
4267 {
4268 AndroidHttpClient.setThreadBlocked(false);
4269 sThreadLocal.set(null);
4270 }
4271
4272 public static final ActivityThread systemMain() {
4273 ActivityThread thread = new ActivityThread();
4274 thread.attach(true);
4275 return thread;
4276 }
4277
4278 public final void installSystemProviders(List providers) {
4279 if (providers != null) {
4280 installContentProviders(mInitialApplication,
4281 (List<ProviderInfo>)providers);
4282 }
4283 }
4284
4285 public static final void main(String[] args) {
Bob Leee5408332009-09-04 18:31:17 -07004286 SamplingProfilerIntegration.start();
4287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004288 Process.setArgV0("<pre-initialized>");
4289
4290 Looper.prepareMainLooper();
4291
4292 ActivityThread thread = new ActivityThread();
4293 thread.attach(false);
4294
4295 Looper.loop();
4296
4297 if (Process.supportsProcesses()) {
4298 throw new RuntimeException("Main thread loop unexpectedly exited");
4299 }
4300
4301 thread.detach();
Bob Leeeec2f412009-09-10 11:01:24 +02004302 String name = (thread.mInitialApplication != null)
4303 ? thread.mInitialApplication.getPackageName()
4304 : "<unknown>";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004305 Log.i(TAG, "Main thread of " + name + " is now exiting");
4306 }
4307}